From af06fd2f88574ec85dc7eed915200e4812de8732 Mon Sep 17 00:00:00 2001 From: loganb1max Date: Sat, 22 Jun 2019 01:12:56 -0500 Subject: [PATCH] Progress --- build.gradle | 3 +- .../me/loganb1max/minions/MinionsPlugin.java | 5 +- .../minions/manager/MinionManager.java | 63 ++++ .../loganb1max/minions/menu/MinionMenu.java | 86 ++++++ .../minions/model/AbstractMinion.java | 99 +++++++ .../me/loganb1max/minions/model/Minion.java | 43 +++ .../minions/model/minions/FarmerMinion.java | 93 ++++++ .../minions/model/minions/FisherMinion.java | 98 +++++++ .../minions/model/minions/MinerMinion.java | 93 ++++++ .../loganb1max/minions/util/ItemBuilder.java | 53 ++++ .../me/loganb1max/minions/util/ItemUtil.java | 159 ++++++++++ .../me/loganb1max/minions/util/Replacer.java | 26 ++ .../loganb1max/minions/util/SkullCreator.java | 276 ++++++++++++++++++ .../java/me/loganb1max/minions/util/Text.java | 11 + src/main/resources/config.yml | 157 ++++++++++ src/main/resources/plugin.yml | 9 +- 16 files changed, 1271 insertions(+), 3 deletions(-) create mode 100644 src/main/java/me/loganb1max/minions/manager/MinionManager.java create mode 100644 src/main/java/me/loganb1max/minions/menu/MinionMenu.java create mode 100644 src/main/java/me/loganb1max/minions/model/AbstractMinion.java create mode 100644 src/main/java/me/loganb1max/minions/model/Minion.java create mode 100644 src/main/java/me/loganb1max/minions/model/minions/FarmerMinion.java create mode 100644 src/main/java/me/loganb1max/minions/model/minions/FisherMinion.java create mode 100644 src/main/java/me/loganb1max/minions/model/minions/MinerMinion.java create mode 100644 src/main/java/me/loganb1max/minions/util/ItemBuilder.java create mode 100644 src/main/java/me/loganb1max/minions/util/ItemUtil.java create mode 100644 src/main/java/me/loganb1max/minions/util/Replacer.java create mode 100644 src/main/java/me/loganb1max/minions/util/SkullCreator.java create mode 100644 src/main/java/me/loganb1max/minions/util/Text.java diff --git a/build.gradle b/build.gradle index 1551a1c..8eb48f2 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,8 @@ repositories { dependencies { compileOnly(files('libs/paper-server-1.8.8-R0.1.jar')) - compileOnly('org.projectlombok:lombok:1.16.20') + compile('org.projectlombok:lombok:1.16.20') + annotationProcessor ('org.projectlombok:lombok:1.16.20') } clean { diff --git a/src/main/java/me/loganb1max/minions/MinionsPlugin.java b/src/main/java/me/loganb1max/minions/MinionsPlugin.java index 47efb2a..f4dd132 100644 --- a/src/main/java/me/loganb1max/minions/MinionsPlugin.java +++ b/src/main/java/me/loganb1max/minions/MinionsPlugin.java @@ -1,20 +1,23 @@ package me.loganb1max.minions; import lombok.Getter; +import me.loganb1max.minions.manager.MinionManager; import org.bukkit.plugin.java.JavaPlugin; public class MinionsPlugin extends JavaPlugin { @Getter private static MinionsPlugin instance; + @Getter private MinionManager minionManager; @Override public void onEnable() { saveDefaultConfig(); + this.minionManager = new MinionManager(this); } @Override public void onDisable() { - + this.minionManager.close(); } } diff --git a/src/main/java/me/loganb1max/minions/manager/MinionManager.java b/src/main/java/me/loganb1max/minions/manager/MinionManager.java new file mode 100644 index 0000000..988fd90 --- /dev/null +++ b/src/main/java/me/loganb1max/minions/manager/MinionManager.java @@ -0,0 +1,63 @@ +package me.loganb1max.minions.manager; + +import lombok.Getter; +import me.loganb1max.minions.MinionsPlugin; +import me.loganb1max.minions.menu.MinionMenu; +import me.loganb1max.minions.model.Minion; +import me.loganb1max.minions.util.Text; +import org.bukkit.Bukkit; +import org.bukkit.entity.ArmorStand; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerArmorStandManipulateEvent; +import org.bukkit.scheduler.BukkitTask; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +public class MinionManager implements Listener { + + private final MinionsPlugin plugin; + private BukkitTask animationTask; + + @Getter private Set minions = new HashSet<>(); + + public MinionManager(final MinionsPlugin plugin) { + this.plugin = plugin; + this.animationTask = Bukkit.getScheduler().runTaskTimer(this.plugin, () -> this.minions.forEach(Minion::tick), 10, 10); + Bukkit.getPluginManager().registerEvents(this, this.plugin); + } + + public void close() { + this.animationTask.cancel(); + HandlerList.unregisterAll(this); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onDamage(final EntityDamageEvent e) { + if (!(e.getEntity() instanceof ArmorStand)) return; + if (this.minions.stream().map(Minion::getId).filter(Objects::nonNull).anyMatch(uuid -> uuid.equals(e.getEntity().getUniqueId()))) { + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onRightClick(final PlayerArmorStandManipulateEvent e) { + this.minions.stream().filter(minion -> minion.getId().equals(e.getRightClicked().getUniqueId())).findFirst().ifPresent(minion -> { + e.setCancelled(true); + if (!minion.getOwner().equals(e.getPlayer().getUniqueId())) { + e.getPlayer().sendMessage(Text.color("&cOnly the owner of the minion can interact with it.")); + return; + } + if (e.getPlayer().isSneaking()) { + minion.pickup(e.getPlayer()); + return; + } + new MinionMenu(minion, e.getPlayer()); + }); + } + +} diff --git a/src/main/java/me/loganb1max/minions/menu/MinionMenu.java b/src/main/java/me/loganb1max/minions/menu/MinionMenu.java new file mode 100644 index 0000000..4ea0b8c --- /dev/null +++ b/src/main/java/me/loganb1max/minions/menu/MinionMenu.java @@ -0,0 +1,86 @@ +package me.loganb1max.minions.menu; + +import me.loganb1max.minions.MinionsPlugin; +import me.loganb1max.minions.model.Minion; +import me.loganb1max.minions.util.ItemBuilder; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +public class MinionMenu implements Listener { + + private final Minion minion; + private final Player player; + private final Inventory inventory; + private final Map> clickHandlerMap = new HashMap<>(); + + public MinionMenu(final Minion minion, final Player player) { + this.minion = minion; + this.player = player; + Bukkit.getPluginManager().registerEvents(this, MinionsPlugin.getInstance()); + this.inventory = Bukkit.createInventory(this.player, 9, "Minion Menu"); + + bindItem( + ItemBuilder.of(Material.CHEST) + .name("&6Link Chest") + .lore("&7click to link a deposit chest.") + .build(), + 2, + clickType -> { + + } + ); + + bindItem( + minion.getIcon(), + 4, + clickType -> { } + ); + + bindItem( + ItemBuilder.of(Material.GOLD_INGOT) + .name("&6Upgrade") + .lore("&7click to upgrade this minion.") + .build(), + 6, + clickType -> { + + } + ); + + this.player.openInventory(this.inventory); + } + + private void bindItem(final ItemStack item, final int slot, final Consumer consumer) { + this.inventory.setItem(slot, item); + this.clickHandlerMap.remove(slot); + this.clickHandlerMap.put(slot, consumer); + this.player.updateInventory(); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onClose(final InventoryCloseEvent e) { + if (!e.getInventory().equals(this.inventory)) return; + HandlerList.unregisterAll(this); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onClick(final InventoryClickEvent e) { + if (!e.getClickedInventory().equals(this.inventory)) return; + e.setCancelled(true); + this.clickHandlerMap.get(e.getSlot()).accept(e.getClick()); + } + +} diff --git a/src/main/java/me/loganb1max/minions/model/AbstractMinion.java b/src/main/java/me/loganb1max/minions/model/AbstractMinion.java new file mode 100644 index 0000000..90bb434 --- /dev/null +++ b/src/main/java/me/loganb1max/minions/model/AbstractMinion.java @@ -0,0 +1,99 @@ +package me.loganb1max.minions.model; + +import com.google.common.collect.ImmutableSet; +import lombok.Getter; +import me.loganb1max.minions.MinionsPlugin; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import java.util.Set; +import java.util.UUID; + +@Getter +public abstract class AbstractMinion implements Minion { + + private final UUID owner; + private final String ownerName; + private Location location; + private double energy; + private int level; + private Set linkedBlocks; + private ArmorStand stand; + + private double offset = 0.1; + + public AbstractMinion(final Player owner) { + this.owner = owner.getUniqueId(); + this.ownerName = owner.getName(); + } + + public void spawn(final Location location) { + this.location = location; + if (this.stand == null) { + this.stand = (ArmorStand) location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND); + this.stand.setSmall(true); + this.stand.setBasePlate(false); + this.stand.setGravity(false); + this.stand.setCanPickupItems(false); + this.stand.setRemoveWhenFarAway(false); + this.stand.setMarker(false); + this.equipEquipment(this.stand); + MinionsPlugin.getInstance().getMinionManager().getMinions().add(this); + } else { + this.stand.teleport(location); + } + } + + public void despawn(final Player player) { + if (this.stand == null) return; + this.location = null; + this.stand.remove(); + this.stand = null; + this.linkedBlocks.clear(); + player.getInventory().addItem(this.toItemStack()).forEach((integer, itemStack) -> player.getWorld().dropItemNaturally(player.getLocation(), itemStack)); + } + + @Override + public void pickup(Player player) { + this.despawn(player); + MinionsPlugin.getInstance().getMinionManager().getMinions().remove(this); + } + + @Override + public Set getLinkedBlocks() { + return ImmutableSet.copyOf(this.linkedBlocks); + } + + @Override + public double gainEnergy(final double amount) { + return this.energy += amount; + } + + @Override + public double consumeEnergy(final double amount) { + return this.energy -= amount; + } + + @Override + public UUID getId() { + if (this.stand == null) return null; + return this.stand.getUniqueId(); + } + + @Override + public void tick() { + if (this.stand == null) return; + if (this.stand.getRightArmPose().getX() > 300) offset = -0.1; + if (this.stand.getRightArmPose().getX() < 230) offset = 0.1; + this.stand.setRightArmPose(this.stand.getRightArmPose().add(offset, 0, 0)); + this.stand.setFireTicks(0); + } + + public abstract ItemStack toItemStack(); + + public abstract void equipEquipment(final ArmorStand stand); + +} diff --git a/src/main/java/me/loganb1max/minions/model/Minion.java b/src/main/java/me/loganb1max/minions/model/Minion.java new file mode 100644 index 0000000..10f5d5e --- /dev/null +++ b/src/main/java/me/loganb1max/minions/model/Minion.java @@ -0,0 +1,43 @@ +package me.loganb1max.minions.model; + +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Set; +import java.util.UUID; + +public interface Minion { + + String getName(); + + UUID getId(); + + UUID getOwner(); + + String getOwnerName(); + + Location getLocation(); + + double getEnergy(); + + int getLevel(); + + Set getLinkedBlocks(); + + double gainEnergy(final double amount); + + double consumeEnergy(final double amount); + + void spawn(final Location location); + + void despawn(final Player player); + + ItemStack getIcon(); + + void tick(); + + void pickup(final Player player); + +} diff --git a/src/main/java/me/loganb1max/minions/model/minions/FarmerMinion.java b/src/main/java/me/loganb1max/minions/model/minions/FarmerMinion.java new file mode 100644 index 0000000..5d6e6ef --- /dev/null +++ b/src/main/java/me/loganb1max/minions/model/minions/FarmerMinion.java @@ -0,0 +1,93 @@ +package me.loganb1max.minions.model.minions; + +import me.loganb1max.minions.MinionsPlugin; +import me.loganb1max.minions.model.AbstractMinion; +import me.loganb1max.minions.util.ItemUtil; +import me.loganb1max.minions.util.Replacer; +import me.loganb1max.minions.util.SkullCreator; +import me.loganb1max.minions.util.Text; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import java.util.List; +import java.util.stream.Collectors; + +public class FarmerMinion extends AbstractMinion { + + private final ConfigurationSection section; + + public FarmerMinion(final Player owner) { + super(owner); + this.section = MinionsPlugin.getInstance().getConfig().getConfigurationSection("Farmer"); + } + + @Override + public ItemStack getIcon() { + final Material material = Material.getMaterial(section.getString("Item.Material")); + final int durability = section.getInt("Item.Durability"); + final String skull = section.getString("Item.Skull", null); + final String displayName = section.getString("Item.DisplayName"); + final List lore = section.getStringList("Item.Lore"); + final Replacer replacer = Replacer.create() + .add("%level%", String.valueOf(getLevel())) + .add("%energy%", String.valueOf(getEnergy())) + .add("%owner%", getOwnerName()) + .add("%radius%", String.valueOf(getRadius(getLevel()))); + ItemStack item = new ItemStack(material, 1); + item.setDurability((short) durability); + if (material == Material.SKULL_ITEM && skull != null) { + item = SkullCreator.itemWithBase64(item, skull); + } + final ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(Text.color(displayName)); + meta.setLore(lore.stream().map(Text::color).map(replacer::replace).collect(Collectors.toList())); + item.setItemMeta(meta); + return item; + } + + @Override + public ItemStack toItemStack() { + ItemStack item = getIcon(); + item = ItemUtil.setKeyString(item, "minion-owner", getOwner().toString()); + item = ItemUtil.setKeyString(item, "minion-owner-name", getOwnerName()); + item = ItemUtil.setKeyInt(item, "minion-level", getLevel()); + item = ItemUtil.setKeyDouble(item, "minion-energy", getEnergy()); + return item; + } + + @Override + public void equipEquipment(ArmorStand stand) { + final String skull = section.getString("Equipment.Skull", ""); + ItemStack skullItem = SkullCreator.itemFromBase64(skull); + stand.setHelmet(skullItem); + final ItemStack chestplate = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.Chestplate")); + stand.setChestplate(chestplate); + final ItemStack leggings = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.Leggings")); + stand.setLeggings(leggings); + final ItemStack boots = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.Boots")); + stand.setBoots(boots); + final ItemStack rightHand = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.RightHand")); + stand.setItemInHand(rightHand); + } + + public int getRadius(final int level) { + return section.getInt("Levels." + level + ".Radius", 1); + } + + public double getPrice(final int level) { + return section.getDouble("Levels." + level + ".Price", 0.0); + } + + public double getEnergyPerUse(final int level) { + return section.getDouble("Levels." + level + ".EnergyPerAction", 0.0); + } + + @Override + public String getName() { + return section.getString("Name"); + } + +} diff --git a/src/main/java/me/loganb1max/minions/model/minions/FisherMinion.java b/src/main/java/me/loganb1max/minions/model/minions/FisherMinion.java new file mode 100644 index 0000000..2bb9367 --- /dev/null +++ b/src/main/java/me/loganb1max/minions/model/minions/FisherMinion.java @@ -0,0 +1,98 @@ +package me.loganb1max.minions.model.minions; + +import me.loganb1max.minions.MinionsPlugin; +import me.loganb1max.minions.model.AbstractMinion; +import me.loganb1max.minions.util.ItemUtil; +import me.loganb1max.minions.util.Replacer; +import me.loganb1max.minions.util.SkullCreator; +import me.loganb1max.minions.util.Text; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import java.util.List; +import java.util.stream.Collectors; + +public class FisherMinion extends AbstractMinion { + + private final ConfigurationSection section; + + public FisherMinion(final Player owner) { + super(owner); + this.section = MinionsPlugin.getInstance().getConfig().getConfigurationSection("Fisher"); + } + + @Override + public ItemStack getIcon() { + final Material material = Material.getMaterial(section.getString("Item.Material")); + final int durability = section.getInt("Item.Durability"); + final String skull = section.getString("Item.Skull", null); + final String displayName = section.getString("Item.DisplayName"); + final List lore = section.getStringList("Item.Lore"); + final Replacer replacer = Replacer.create() + .add("%level%", String.valueOf(getLevel())) + .add("%energy%", String.valueOf(getEnergy())) + .add("%owner%", getOwnerName()) + .add("%radius%", String.valueOf(getRadius(getLevel()))) + .add("%chanceperblockpersecond%", String.valueOf(getChancePerBlockPerSecond(getLevel()))); + ItemStack item = new ItemStack(material, 1); + item.setDurability((short) durability); + if (material == Material.SKULL_ITEM && skull != null) { + item = SkullCreator.itemWithBase64(item, skull); + } + final ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(Text.color(displayName)); + meta.setLore(lore.stream().map(Text::color).map(replacer::replace).collect(Collectors.toList())); + item.setItemMeta(meta); + return item; + } + + @Override + public ItemStack toItemStack() { + ItemStack item = getIcon(); + item = ItemUtil.setKeyString(item, "minion-owner", getOwner().toString()); + item = ItemUtil.setKeyString(item, "minion-owner-name", getOwnerName()); + item = ItemUtil.setKeyInt(item, "minion-level", getLevel()); + item = ItemUtil.setKeyDouble(item, "minion-energy", getEnergy()); + return item; + } + + @Override + public void equipEquipment(ArmorStand stand) { + final String skull = section.getString("Equipment.Skull", ""); + ItemStack skullItem = SkullCreator.itemFromBase64(skull); + stand.setHelmet(skullItem); + final ItemStack chestplate = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.Chestplate")); + stand.setChestplate(chestplate); + final ItemStack leggings = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.Leggings")); + stand.setLeggings(leggings); + final ItemStack boots = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.Boots")); + stand.setBoots(boots); + final ItemStack rightHand = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.RightHand")); + stand.setItemInHand(rightHand); + } + + public double getChancePerBlockPerSecond(final int level) { + return section.getDouble("Levels." + level + ".ChancePerBlockPerSecond", 0.0); + } + + public int getRadius(final int level) { + return section.getInt("Levels." + level + ".Radius", 1); + } + + public double getPrice(final int level) { + return section.getDouble("Levels." + level + ".Price", 0.0); + } + + public double getEnergyPerUse(final int level) { + return section.getDouble("Levels." + level + ".EnergyPerAction", 0.0); + } + + @Override + public String getName() { + return section.getString("Name"); + } + +} diff --git a/src/main/java/me/loganb1max/minions/model/minions/MinerMinion.java b/src/main/java/me/loganb1max/minions/model/minions/MinerMinion.java new file mode 100644 index 0000000..473dd45 --- /dev/null +++ b/src/main/java/me/loganb1max/minions/model/minions/MinerMinion.java @@ -0,0 +1,93 @@ +package me.loganb1max.minions.model.minions; + +import me.loganb1max.minions.MinionsPlugin; +import me.loganb1max.minions.model.AbstractMinion; +import me.loganb1max.minions.util.ItemUtil; +import me.loganb1max.minions.util.Replacer; +import me.loganb1max.minions.util.SkullCreator; +import me.loganb1max.minions.util.Text; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import java.util.List; +import java.util.stream.Collectors; + +public class MinerMinion extends AbstractMinion { + + private final ConfigurationSection section; + + public MinerMinion(final Player owner) { + super(owner); + this.section = MinionsPlugin.getInstance().getConfig().getConfigurationSection("Miner"); + } + + @Override + public ItemStack getIcon() { + final Material material = Material.getMaterial(section.getString("Item.Material")); + final int durability = section.getInt("Item.Durability"); + final String skull = section.getString("Item.Skull", null); + final String displayName = section.getString("Item.DisplayName"); + final List lore = section.getStringList("Item.Lore"); + final Replacer replacer = Replacer.create() + .add("%level%", String.valueOf(getLevel())) + .add("%energy%", String.valueOf(getEnergy())) + .add("%owner%", getOwnerName()) + .add("%blocklimit%", String.valueOf(getBlockLimit(getLevel()))); + ItemStack item = new ItemStack(material, 1); + item.setDurability((short) durability); + if (material == Material.SKULL_ITEM && skull != null) { + item = SkullCreator.itemWithBase64(item, skull); + } + final ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(Text.color(displayName)); + meta.setLore(lore.stream().map(Text::color).map(replacer::replace).collect(Collectors.toList())); + item.setItemMeta(meta); + return item; + } + + @Override + public ItemStack toItemStack() { + ItemStack item = getIcon(); + item = ItemUtil.setKeyString(item, "minion-owner", getOwner().toString()); + item = ItemUtil.setKeyString(item, "minion-owner-name", getOwnerName()); + item = ItemUtil.setKeyInt(item, "minion-level", getLevel()); + item = ItemUtil.setKeyDouble(item, "minion-energy", getEnergy()); + return item; + } + + @Override + public void equipEquipment(ArmorStand stand) { + final String skull = section.getString("Equipment.Skull", ""); + ItemStack skullItem = SkullCreator.itemFromBase64(skull); + stand.setHelmet(skullItem); + final ItemStack chestplate = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.Chestplate")); + stand.setChestplate(chestplate); + final ItemStack leggings = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.Leggings")); + stand.setLeggings(leggings); + final ItemStack boots = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.Boots")); + stand.setBoots(boots); + final ItemStack rightHand = ItemUtil.fromConfigSection(section.getConfigurationSection("Equipment.RightHand")); + stand.setItemInHand(rightHand); + } + + public int getBlockLimit(final int level) { + return section.getInt("Levels." + level + ".BlockLimit", 1); + } + + public double getPrice(final int level) { + return section.getDouble("Levels." + level + ".Price", 0.0); + } + + public double getEnergyPerUse(final int level) { + return section.getDouble("Levels." + level + ".EnergyPerAction", 0.0); + } + + @Override + public String getName() { + return section.getString("Name"); + } + +} diff --git a/src/main/java/me/loganb1max/minions/util/ItemBuilder.java b/src/main/java/me/loganb1max/minions/util/ItemBuilder.java new file mode 100644 index 0000000..09576d7 --- /dev/null +++ b/src/main/java/me/loganb1max/minions/util/ItemBuilder.java @@ -0,0 +1,53 @@ +package me.loganb1max.minions.util; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import java.util.List; +import java.util.stream.Collectors; + +public class ItemBuilder { + + private ItemStack itemStack; + + public ItemBuilder(final Material material) { + this.itemStack = new ItemStack(material); + } + + public static ItemBuilder of(final Material material) { + return new ItemBuilder(material); + } + + public ItemBuilder amount(final int amount) { + itemStack.setAmount(amount); + return this; + } + + public ItemBuilder name(final String name) { + ItemMeta meta = itemStack.getItemMeta(); + meta.setDisplayName(Text.color(name)); + itemStack.setItemMeta(meta); + return this; + } + + public ItemBuilder lore(final String lore) { + ItemMeta meta = itemStack.getItemMeta(); + List loreList = meta.getLore(); + loreList.add(Text.color(lore)); + meta.setLore(loreList); + itemStack.setItemMeta(meta); + return this; + } + + public ItemBuilder lore(final List lore) { + ItemMeta meta = itemStack.getItemMeta(); + meta.setLore(lore.stream().map(Text::color).collect(Collectors.toList())); + itemStack.setItemMeta(meta); + return this; + } + + public ItemStack build() { + return itemStack.clone(); + } + +} diff --git a/src/main/java/me/loganb1max/minions/util/ItemUtil.java b/src/main/java/me/loganb1max/minions/util/ItemUtil.java new file mode 100644 index 0000000..9d807ba --- /dev/null +++ b/src/main/java/me/loganb1max/minions/util/ItemUtil.java @@ -0,0 +1,159 @@ +package me.loganb1max.minions.util; + +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.LeatherArmorMeta; + +import java.util.Map; + +public class ItemUtil { + + public static ItemStack setKeyInt(ItemStack itemStack, String key, int value) { + net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack); + nms.getTag().setInt(key, value); + return CraftItemStack.asBukkitCopy(nms); + } + + public static ItemStack setKeyDouble(ItemStack itemStack, String key, double value) { + net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack); + nms.getTag().setDouble(key, value); + return CraftItemStack.asBukkitCopy(nms); + } + + public static ItemStack setKeyString(ItemStack itemStack, String key, String value) { + net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack); + nms.getTag().setString(key, value); + return CraftItemStack.asBukkitCopy(nms); + } + + public static ItemStack setKeyLong(ItemStack itemStack, String key, long value) { + net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack); + nms.getTag().setLong(key, value); + return CraftItemStack.asBukkitCopy(nms); + } + + public static int getKeyInt(ItemStack itemStack, String key) { + net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack); + return nms.getTag().getInt(key); + } + + public static double getKeyDouble(ItemStack itemStack, String key) { + net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack); + return nms.getTag().getDouble(key); + } + + public static String getKeyString(ItemStack itemStack, String key) { + net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack); + return nms.getTag().getString(key); + } + + public static long getKeyLong(ItemStack itemStack, String key) { + net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack); + return nms.getTag().getLong(key); + } + + public static boolean hasKey(ItemStack itemStack, String key) { + net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack); + if (nms.getTag() == null) return false; + return nms.getTag().hasKey(key); + } + + public static ItemStack setMaxStackSize(ItemStack stack, int size) { + try { + net.minecraft.server.v1_8_R3.ItemStack item = CraftItemStack.asNMSCopy(stack); + item.getItem().c(size); + return CraftItemStack.asBukkitCopy(item); + } catch (Throwable e) { + e.printStackTrace(); + } + return null; + } + + public static boolean areSimilar(ItemStack stack1, ItemStack stack2) { + if (stack1 != null && stack2 != null) { + if (stack1.getType() == stack2.getType()) { + if (stack1.getDurability() == stack2.getDurability()) { + if (stack1.getAmount() == stack2.getAmount()) { + if (stack1.hasItemMeta() && stack2.hasItemMeta()) { + if (stack1.getItemMeta().equals(stack2.getItemMeta())) { + return true; + } + } else { + return true; + } + } + } + } + } + return false; + } + + public static boolean consumeItem(Inventory inventory, int count, ItemStack itemStack) { + Map ammo = inventory.all(itemStack.getType()); + + int found = 0; + for (ItemStack stack : ammo.values()) { + if (stack.getDurability() != itemStack.getDurability()) continue; + if (!stack.getItemMeta().equals(itemStack.getItemMeta())) continue; + found += stack.getAmount(); + } + if (count > found) + return false; + + for (Integer index : ammo.keySet()) { + ItemStack stack = ammo.get(index); + if (stack.getDurability() != itemStack.getDurability()) continue; + if (!stack.getItemMeta().equals(itemStack.getItemMeta())) continue; + int removed = Math.min(count, stack.getAmount()); + count -= removed; + + if (stack.getAmount() == removed) + inventory.setItem(index, null); + else + stack.setAmount(stack.getAmount() - removed); + + if (count <= 0) + break; + } + + inventory.getViewers().stream().filter(humanEntity -> humanEntity instanceof Player).forEach(humanEntity -> ((Player)humanEntity).updateInventory()); + return true; + } + + public static boolean containsItems(Inventory inventory, int count, ItemStack itemStack) { + Map ammo = inventory.all(itemStack.getType()); + + int found = 0; + for (ItemStack stack : ammo.values()) { + if (stack.getDurability() != itemStack.getDurability()) continue; + if (!stack.getItemMeta().equals(itemStack.getItemMeta())) continue; + found += stack.getAmount(); + } + if (count > found) + return false; + + return true; + } + + public static ItemStack fromConfigSection(final ConfigurationSection section) { + final Material material = Material.getMaterial(section.getString("Material")); + final int durability = section.getInt("Durability"); + final ItemStack item = new ItemStack(material, 1); + item.setDurability((short) durability); + if (section.contains("Color") && material.name().toLowerCase().contains("leather")) { + LeatherArmorMeta meta = (LeatherArmorMeta) item.getItemMeta(); + int red = section.getInt("Color.Red"); + int green = section.getInt("Color.Green"); + int blue = section.getInt("Color.Blue"); + meta.setColor(Color.fromRGB(red, green, blue)); + item.setItemMeta(meta); + } + return item; + } + +} diff --git a/src/main/java/me/loganb1max/minions/util/Replacer.java b/src/main/java/me/loganb1max/minions/util/Replacer.java new file mode 100644 index 0000000..df832d1 --- /dev/null +++ b/src/main/java/me/loganb1max/minions/util/Replacer.java @@ -0,0 +1,26 @@ +package me.loganb1max.minions.util; + +import java.util.HashMap; +import java.util.Map; + +public class Replacer { + + private Map replaceMap = new HashMap<>(); + + public static Replacer create() { + return new Replacer(); + } + + public Replacer add(final String key, final String value) { + this.replaceMap.put(key, value); + return this; + } + + public String replace(String string) { + for (Map.Entry entry : this.replaceMap.entrySet()) { + string = string.replaceAll(entry.getKey(), entry.getValue()); + } + return string; + } + +} diff --git a/src/main/java/me/loganb1max/minions/util/SkullCreator.java b/src/main/java/me/loganb1max/minions/util/SkullCreator.java new file mode 100644 index 0000000..18088a1 --- /dev/null +++ b/src/main/java/me/loganb1max/minions/util/SkullCreator.java @@ -0,0 +1,276 @@ +package me.loganb1max.minions.util; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.Skull; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Base64; +import java.util.UUID; + +/** + * A library for the Bukkit API to create player skulls + * from names, base64 strings, and texture URLs. + * + * Does not use any NMS code, and should work across all versions. + * + * @author Dean B on 12/28/2016. + */ +public class SkullCreator { + + /** + * Creates a player skull based on a player's name. + * + * @param name The Player's name + * @return The head of the Player + * + * @deprecated names don't make for good identifiers + */ + @Deprecated + public static ItemStack itemFromName(String name) { + ItemStack item = getPlayerSkullItem(); + + return itemWithName(item, name); + } + + /** + * Creates a player skull based on a player's name. + * + * @param item The item to apply the name to + * @param name The Player's name + * @return The head of the Player + * + * @deprecated names don't make for good identifiers + */ + @Deprecated + public static ItemStack itemWithName(ItemStack item, String name) { + notNull(item, "item"); + notNull(name, "name"); + + return Bukkit.getUnsafe().modifyItemStack(item, + "{SkullOwner:\"" + name + "\"}" + ); + } + + /** + * Creates a player skull with a UUID. 1.13 only. + * + * @param id The Player's UUID + * @return The head of the Player + */ + public static ItemStack itemFromUuid(UUID id) { + ItemStack item = getPlayerSkullItem(); + + return itemWithUuid(item, id); + } + + /** + * Creates a player skull based on a UUID. 1.13 only. + * + * @param item The item to apply the name to + * @param id The Player's UUID + * @return The head of the Player + */ + public static ItemStack itemWithUuid(ItemStack item, UUID id) { + notNull(item, "item"); + notNull(id, "id"); + + SkullMeta meta = (SkullMeta) item.getItemMeta(); + meta.setOwner(Bukkit.getOfflinePlayer(id).getName()); + item.setItemMeta(meta); + + return item; + } + + /** + * Creates a player skull based on a Mojang server URL. + * + * @param url The URL of the Mojang skin + * @return The head associated with the URL + */ + public static ItemStack itemFromUrl(String url) { + ItemStack item = getPlayerSkullItem(); + + return itemWithUrl(item, url); + } + + + /** + * Creates a player skull based on a Mojang server URL. + * + * @param item The item to apply the skin to + * @param url The URL of the Mojang skin + * @return The head associated with the URL + */ + public static ItemStack itemWithUrl(ItemStack item, String url) { + notNull(item, "item"); + notNull(url, "url"); + + return itemWithBase64(item, urlToBase64(url)); + } + + /** + * Creates a player skull based on a base64 string containing the link to the skin. + * + * @param base64 The base64 string containing the texture + * @return The head with a custom texture + */ + public static ItemStack itemFromBase64(String base64) { + ItemStack item = getPlayerSkullItem(); + return itemWithBase64(item, base64); + } + + /** + * Applies the base64 string to the ItemStack. + * + * @param item The ItemStack to put the base64 onto + * @param base64 The base64 string containing the texture + * @return The head with a custom texture + */ + public static ItemStack itemWithBase64(ItemStack item, String base64) { + notNull(item, "item"); + notNull(base64, "base64"); + + UUID hashAsId = new UUID(base64.hashCode(), base64.hashCode()); + return Bukkit.getUnsafe().modifyItemStack(item, + "{SkullOwner:{Id:\"" + hashAsId + "\",Properties:{textures:[{Value:\"" + base64 + "\"}]}}}" + ); + } + + /** + * Sets the block to a skull with the given name. + * + * @param block The block to set + * @param name The player to set it to + * + * @deprecated names don't make for good identifiers + */ + @Deprecated + public static void blockWithName(Block block, String name) { + notNull(block, "block"); + notNull(name, "name"); + + setBlockType(block); + ((Skull) block.getState()).setOwner(name); + } + + /** + * Sets the block to a skull with the given UUID. + * + * @param block The block to set + * @param id The player to set it to + */ + public static void blockWithUuid(Block block, UUID id) { + notNull(block, "block"); + notNull(id, "id"); + + setBlockType(block); + ((Skull) block.getState()).setOwner(Bukkit.getOfflinePlayer(id).getName()); + } + + /** + * Sets the block to a skull with the given UUID. + * + * @param block The block to set + * @param url The mojang URL to set it to use + */ + public static void blockWithUrl(Block block, String url) { + notNull(block, "block"); + notNull(url, "url"); + + blockWithBase64(block, urlToBase64(url)); + } + + /** + * Sets the block to a skull with the given UUID. + * + * @param block The block to set + * @param base64 The base64 to set it to use + */ + public static void blockWithBase64(Block block, String base64) { + notNull(block, "block"); + notNull(base64, "base64"); + + UUID hashAsId = new UUID(base64.hashCode(), base64.hashCode()); + + String args = String.format( + "%d %d %d %s", + block.getX(), + block.getY(), + block.getZ(), + "{Owner:{Id:\"" + hashAsId + "\",Properties:{textures:[{Value:\"" + base64 + "\"}]}}}" + ); + + if (newerApi()) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "data merge block " + args); + } else { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(),"blockdata " + args); + } + } + + private static boolean newerApi() { + try { + + Material.valueOf("PLAYER_HEAD"); + return true; + + } catch (IllegalArgumentException e) { // If PLAYER_HEAD doesn't exist + return false; + } + } + + private static ItemStack getPlayerSkullItem() { + if (newerApi()) { + return new ItemStack(Material.valueOf("PLAYER_HEAD")); + } else { + return new ItemStack(Material.valueOf("SKULL_ITEM"), 1, (byte) 3); + } + } + + private static void setBlockType(Block block) { + try { + block.setType(Material.valueOf("PLAYER_HEAD"), false); + } catch (IllegalArgumentException e) { + block.setType(Material.valueOf("SKULL"), false); + } + } + + private static void notNull(Object o, String name) { + if (o == null) { + throw new NullPointerException(name + " should not be null!"); + } + } + + private static String urlToBase64(String url) { + + URI actualUrl; + try { + actualUrl = new URI(url); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + String toEncode = "{\"textures\":{\"SKIN\":{\"url\":\"" + actualUrl.toString() + "\"}}}"; + return Base64.getEncoder().encodeToString(toEncode.getBytes()); + } +} + +/* Format for skull +{ + display:{ + Name:"Cheese" + }, + SkullOwner:{ + Id:"9c919b83-f3fe-456f-a824-7d1d08cc8bd2", + Properties:{ + textures:[ + { + Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTU1ZDYxMWE4NzhlODIxMjMxNzQ5YjI5NjU3MDhjYWQ5NDI2NTA2NzJkYjA5ZTI2ODQ3YTg4ZTJmYWMyOTQ2In19fQ==" + } + ] + } + } +} + */ diff --git a/src/main/java/me/loganb1max/minions/util/Text.java b/src/main/java/me/loganb1max/minions/util/Text.java new file mode 100644 index 0000000..32a6acd --- /dev/null +++ b/src/main/java/me/loganb1max/minions/util/Text.java @@ -0,0 +1,11 @@ +package me.loganb1max.minions.util; + +import org.bukkit.ChatColor; + +public class Text { + + public static String color(final String string) { + return ChatColor.translateAlternateColorCodes('&', string); + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index e69de29..2ace086 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -0,0 +1,157 @@ +############################################################################ +###################### Minions ############################# +############################################################################ + +########## Placeholders ############# +# %level% +# %energy% +# %owner% +# %blocklimit% +# %radius% +# %chanceperblockpersecond% + +Miner: + Name: "Miner Minion" + Item: + Material: SKULL_ITEM + Durability: 3 + Skull: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWYzMTljZTYzNTVlMmI2M2NmZTExY2RlYmVmODU3MjAyMTFmYzAxODQ0YTdlMDRlZjU5ODc5NTIyMTI0ZGUifX19 + DisplayName: "&6Miner Minion" + Lore: + - "" + - "&7Level: %level%" + - "&7Energy: %energy%" + - "&7Owner: %owner%" + Equipment: + Skull: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWYzMTljZTYzNTVlMmI2M2NmZTExY2RlYmVmODU3MjAyMTFmYzAxODQ0YTdlMDRlZjU5ODc5NTIyMTI0ZGUifX19 + Chestplate: + Material: LEATHER_CHESTPLATE + Durability: 0 + Color: + Red: 255 + Green: 255 + Blue: 255 + Leggings: + Material: LEATHER_LEGGINGS + Durability: 0 + Color: + Red: 255 + Green: 255 + Blue: 255 + Boots: + Material: LEATHER_BOOTS + Durability: 0 + Color: + Red: 255 + Green: 255 + Blue: 255 + RightHand: + Material: DIAMOND_PICKAXE + Durability: 0 + Levels: + '1': + Price: 0.0 + EnergyPerAction: 0.5 + BlockLimit: 1 + '2': + Price: 1000.0 + EnergyPerAction: 0.3 + BlockLimit: 3 + +Farmer: + Name: "Farmer Minion" + Item: + Material: SKULL_ITEM + Durability: 3 + Skull: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWY1ZDM4MTlhNjVkYjc5YzQ1ZmQwMDE0MWMwODgyZTQ3YWQyMzRjMGU1Zjg5OTJiZjRhZjE4Y2VkMGUxZWNkYyJ9fX0= + DisplayName: "&6Farmer Minion" + Lore: + - "" + - "&7Level: %level%" + - "&7Energy: %energy%" + - "&7Owner: %owner%" + Equipment: + Skull: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWY1ZDM4MTlhNjVkYjc5YzQ1ZmQwMDE0MWMwODgyZTQ3YWQyMzRjMGU1Zjg5OTJiZjRhZjE4Y2VkMGUxZWNkYyJ9fX0= + Chestplate: + Material: LEATHER_CHESTPLATE + Durability: 0 + Color: + Red: 0 + Green: 0 + Blue: 255 + Leggings: + Material: LEATHER_LEGGINGS + Durability: 0 + Color: + Red: 0 + Green: 0 + Blue: 255 + Boots: + Material: LEATHER_BOOTS + Durability: 0 + Color: + Red: 0 + Green: 0 + Blue: 255 + RightHand: + Material: DIAMOND_HOE + Durability: 0 + Levels: + '1': + Price: 0.0 + EnergyPerAction: 0.5 + Radius: 3 + '2': + Price: 1000.0 + EnergyPerAction: 0.3 + Radius: 5 + +Fisher: + Name: "Fisher Minion" + Item: + Material: SKULL_ITEM + Durability: 3 + Skull: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjhjOTg2Nzk5YmFmZTcxODRhOGFlMjMzZGI2ZDlhYjhlOWI4NDRmYTlkNGRhNjhmYTNkYzk0YWM4ZmU4MjAifX19 + DisplayName: "&6Fisher Minion" + Lore: + - "" + - "&7Level: %level%" + - "&7Energy: %energy" + - "&7Owner: %owner%" + Equipment: + Skull: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjhjOTg2Nzk5YmFmZTcxODRhOGFlMjMzZGI2ZDlhYjhlOWI4NDRmYTlkNGRhNjhmYTNkYzk0YWM4ZmU4MjAifX19 + Chestplate: + Material: LEATHER_CHESTPLATE + Durability: 0 + Color: + Red: 255 + Green: 0 + Blue: 0 + Leggings: + Material: LEATHER_LEGGINGS + Durability: 0 + Color: + Red: 255 + Green: 0 + Blue: 0 + Boots: + Material: LEATHER_BOOTS + Durability: 0 + Color: + Red: 255 + Green: 0 + Blue: 0 + RightHand: + Material: FISHING_ROD + Durability: 0 + Levels: + '1': + Price: 0.0 + EnergyPerAction: 0.5 + Radius: 3 + ChancePerBlockPerSecond: 20.0 + '2': + Price: 1000.0 + EnergyPerAction: 0.3 + Radius: 5 + ChancePerBlockPerSecond: 50.0 \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 1ae67eb..e52c155 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -3,4 +3,11 @@ main: me.loganb1max.minions.MinionsPlugin version: 1.0-SNAPSHOT description: Minions Plugin for Skyblock Servers author: loganb1max -depend: [] \ No newline at end of file +load: POSTWORLD +depend: [] +commands: + minions: + aliases: [minion] + description: Command for Minions + usage: /minions [sub-command] + permission: minions.command \ No newline at end of file