diff --git a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java index 675a2a3..a438b65 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java @@ -9,11 +9,11 @@ import nl.pim16aap2.armoredElytra.handlers.LoginHandler; import nl.pim16aap2.armoredElytra.handlers.NetheriteUpgradeListener; import nl.pim16aap2.armoredElytra.handlers.SmithingTableCraftHandler; import nl.pim16aap2.armoredElytra.handlers.Uninstaller; +import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.ArmorTierName; import nl.pim16aap2.armoredElytra.util.ConfigLoader; -import nl.pim16aap2.armoredElytra.util.DurabilityManager; import nl.pim16aap2.armoredElytra.util.MinecraftVersion; import nl.pim16aap2.armoredElytra.util.UpdateManager; import nl.pim16aap2.armoredElytra.util.messages.Message; @@ -22,7 +22,7 @@ import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; +import org.bukkit.entity.HumanEntity; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; @@ -183,13 +183,13 @@ public class ArmoredElytra extends JavaPlugin implements Listener messages.getString(Message.TIER_SHORT_NETHERITE))); } - public boolean playerHasCraftPerm(Player player, ArmorTier armorTier) + public boolean playerHasCraftPerm(HumanEntity player, ArmorTier armorTier) { return getConfigLoader().bypassCraftPerm() || player.hasPermission("armoredelytra.craft." + ArmorTier.getName(armorTier)); } - public boolean playerHasWearPerm(Player player, ArmorTier armorTier) + public boolean playerHasWearPerm(HumanEntity player, ArmorTier armorTier) { return getConfigLoader().bypassWearPerm() || player.hasPermission("armoredelytra.wear." + ArmorTier.getName(armorTier)); @@ -202,13 +202,13 @@ public class ArmoredElytra extends JavaPlugin implements Listener } // Send a message to a player in a specific color. - public void messagePlayer(Player player, ChatColor color, String str) + public void messagePlayer(HumanEntity player, ChatColor color, String str) { player.sendMessage(color + str); } // Send a message to a player. - public void messagePlayer(Player player, String str) + public void messagePlayer(HumanEntity player, String str) { messagePlayer(player, ChatColor.WHITE, str); } @@ -222,7 +222,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener } // Send the usageDeniedMessage message to the player. - public void usageDeniedMessage(Player player, ArmorTier armorTier) + public void usageDeniedMessage(HumanEntity player, ArmorTier armorTier) { final String message = getMessageWithTierNames(Message.MESSAGES_USAGEDENIED, armorTier); if (!message.equals("NONE")) @@ -230,14 +230,14 @@ public class ArmoredElytra extends JavaPlugin implements Listener } // Send the elytraReceivedMessage message to the player. - public void elytraReceivedMessage(Player player, ArmorTier armorTier) + public void elytraReceivedMessage(HumanEntity player, ArmorTier armorTier) { final String message = getMessageWithTierNames(Message.MESSAGES_ELYTRARECEIVED, armorTier); if (!message.equals("NONE")) messagePlayer(player, ChatColor.GREEN, message); } - public void sendNoGivePermissionMessage(Player player, ArmorTier armorTier) + public void sendNoGivePermissionMessage(HumanEntity player, ArmorTier armorTier) { final String message = getMessageWithTierNames(Message.MESSAGES_NOGIVEPERMISSION, armorTier); messagePlayer(player, ChatColor.RED, message); @@ -263,7 +263,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener } // Give the provided player the provided item. - public void giveArmoredElytraToPlayer(Player player, ItemStack item) + public void giveArmoredElytraToPlayer(HumanEntity player, ItemStack item) { if (item != null) player.getInventory().addItem(item); diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/AnvilHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/AnvilHandler.java index 2937f9a..b9e69ad 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/AnvilHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/AnvilHandler.java @@ -1,16 +1,14 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import nl.pim16aap2.armoredElytra.util.Action; import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.ConfigLoader; -import nl.pim16aap2.armoredElytra.util.DurabilityManager; -import nl.pim16aap2.armoredElytra.util.EnchantmentContainer; import nl.pim16aap2.armoredElytra.util.Util; import nl.pim16aap2.armoredElytra.util.XMaterial; import org.bukkit.ChatColor; -import org.bukkit.Color; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -23,6 +21,7 @@ import org.bukkit.inventory.AnvilInventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import javax.annotation.Nullable; import java.util.logging.Level; public class AnvilHandler extends ArmoredElytraHandler implements Listener @@ -49,7 +48,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener // Ignoring: // - Elytra (not armored) + !chestplate -> None // - * + * -> None - private Action isValidInput(ItemStack itemOne, ItemStack itemTwo) + private Action isValidInput(ArmorTier itemOneTier, ItemStack itemOne, ItemStack itemTwo) { if (itemOne == null || itemTwo == null) return Action.NONE; @@ -57,32 +56,30 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener if (itemOne.getType() != Material.ELYTRA) return Action.NONE; - Material matTwo = itemTwo.getType(); + final Material matTwo = itemTwo.getType(); // If the elytra is to be combined with chest armor... if (Util.isChestPlate(matTwo)) return creationEnabled ? Action.CREATE : Action.NONE; - ArmorTier tier = nbtEditor.getArmorTier(itemOne); - - if (tier != ArmorTier.NONE) + if (itemOneTier != ArmorTier.NONE) { // If the armored elytra is to be enchanted using an enchanted book... if (matTwo == Material.ENCHANTED_BOOK) return config.allowAddingEnchantments() ? Action.ENCHANT : Action.BLOCK; // If the armored elytra is to be repaired using its repair item... - if (ArmorTier.getRepairItem(tier) == matTwo) - return durabilityManager.getRealDurability(itemOne, tier) == 0 ? Action.BLOCK : Action.REPAIR; + if (ArmorTier.getRepairItem(itemOneTier) == matTwo) + return durabilityManager.getRealDurability(itemOne, itemOneTier) == 0 ? Action.BLOCK : Action.REPAIR; // If the armored elytra is to be combined with another armored elytra of the same tier... - if (nbtEditor.getArmorTier(itemTwo) == tier) + if (nbtEditor.getArmorTier(itemTwo) == itemOneTier) return creationEnabled ? Action.COMBINE : Action.NONE; // If the armored elytra is not of the leather tier, but itemTwo is leather, // Pick the block action, as that would repair the elytra by default (vanilla). // Also block Armored Elytra + Elytra and Elytra + Membrane - if (tier != ArmorTier.LEATHER && matTwo == Material.LEATHER || matTwo == Material.ELYTRA || + if (itemOneTier != ArmorTier.LEATHER && matTwo == Material.LEATHER || matTwo == Material.ELYTRA || matTwo.equals(XMaterial.PHANTOM_MEMBRANE.parseMaterial())) return Action.BLOCK; } @@ -93,10 +90,11 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener @EventHandler(priority = EventPriority.LOWEST) private void onAnvilInventoryOpen(PrepareAnvilEvent event) { - Player player = (Player) event.getView().getPlayer(); + if (!(event.getView().getPlayer() instanceof Player player)) + return; + ItemStack itemA = event.getInventory().getItem(0); ItemStack itemB = event.getInventory().getItem(1); - ItemStack result; if (itemA != null && itemB != null) // If itemB is the (armored) elytra, while itemA isn't, switch itemA and itemB. @@ -107,81 +105,57 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener itemB = tmp; } - // Check if there are items in both input slots. - if (itemA != null && itemB != null) - { - final Action action = isValidInput(itemA, itemB); - ArmorTier newTier = ArmorTier.NONE; - final ArmorTier curTier = nbtEditor.getArmorTier(itemA); - - int newDurability = 0; - final EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemA, plugin); - - switch (action) - { - case REPAIR: - newTier = curTier; - newDurability = durabilityManager.getRepairedDurability(itemA, itemB.getAmount(), curTier); - break; - case COMBINE: - newTier = curTier; - newDurability = durabilityManager.getCombinedDurability(itemA, itemB, curTier, newTier); - enchantments.merge(EnchantmentContainer.getEnchantments(itemB, plugin)); - break; - case CREATE: - newTier = Util.armorToTier(itemB.getType()); - newDurability = durabilityManager.getCombinedDurability(itemA, itemB, curTier, newTier); - enchantments.merge(EnchantmentContainer.getEnchantments(itemB, plugin)); - break; - case ENCHANT: - newTier = curTier; - newDurability = durabilityManager.getRealDurability(itemA, newTier); - - // If there aren't any illegal enchantments on the book, continue as normal. - // Otherwise... Block. - final EnchantmentContainer enchantmentsB = EnchantmentContainer.getEnchantments(itemB, plugin); - if (enchantmentsB.getEnchantmentCount() > 0) - { - enchantments.merge(enchantmentsB); - break; - } - //$FALL-THROUGH$ - case BLOCK: - event.setResult(null); - player.updateInventory(); - //$FALL-THROUGH$ - case NONE: - return; - } - - if (plugin.playerHasCraftPerm(player, newTier)) - { - result = new ItemStack(Material.ELYTRA, 1); - enchantments.applyEnchantments(result); - durabilityManager.setDurability(result, newDurability, newTier); - - final String name = getElytraResultName(itemA, action, newTier, event.getInventory().getRenameText()); - final Color color = getItemColor(itemA, itemB); - - result = nbtEditor.addArmorNBTTags(result, newTier, config.unbreakable(), name, color); - - event.setResult(result); - return; - } - } - // If one of the input items is null and the other an armored elytra, remove the result. // This prevents some naming issues. if ((itemA == null ^ itemB == null) && nbtEditor.getArmorTier(itemA == null ? itemB : itemA) != ArmorTier.NONE) event.setResult(null); + + if (itemA == null || itemB == null) + return; + + final ArmorTier currentArmorTier = nbtEditor.getArmorTier(itemA); + final Action action = isValidInput(currentArmorTier, itemA, itemB); + + if (action == Action.NONE) + return; + + final ArmorTier newArmorTier; + if (action == Action.CREATE) + newArmorTier = Util.armorToTier(itemB); + else if (action == Action.COMBINE) + newArmorTier = nbtEditor.getArmorTier(itemB); + else + newArmorTier = currentArmorTier; + + final @Nullable String name = getElytraResultName(itemA, action, currentArmorTier, newArmorTier, + event.getInventory().getRenameText()); + + final @Nullable ItemStack result = + !plugin.playerHasCraftPerm(player, newArmorTier) ? null : + switch (action) + { + case REPAIR -> armoredElytraBuilder.repair(itemA, itemB, name); + case ENCHANT -> armoredElytraBuilder.enchant(itemA, itemB, name); + case COMBINE, CREATE -> armoredElytraBuilder.combine(itemA, itemB, newArmorTier, name); + case BLOCK -> null; + //noinspection ConstantConditions + case NONE -> itemA; + }; + + event.setResult(result); + player.updateInventory(); } - private String getElytraResultName(final ItemStack baseItem, final Action action, - final ArmorTier armorTier, final String renameText) + private @Nullable String getElytraResultName(final ItemStack baseItem, final Action action, + final ArmorTier currentArmorTier, final ArmorTier newArmorTier, + final String renameText) { - final String tierName = plugin.getArmoredElytraName(armorTier); - if (renameText == null || !config.allowRenaming()) + final String currentTierName = plugin.getArmoredElytraName(currentArmorTier); + final String tierName = plugin.getArmoredElytraName(newArmorTier); + + if (renameText == null || !config.allowRenaming() || + ChatColor.stripColor(currentTierName).equals(ChatColor.stripColor(renameText))) return tierName; final ItemMeta meta = baseItem.getItemMeta(); @@ -201,11 +175,10 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener @EventHandler public void onInventoryClick(InventoryClickEvent e) { - if (e.getRawSlot() != 2 || !(e.getWhoClicked() instanceof Player)) + if (e.getRawSlot() != 2 || !(e.getWhoClicked() instanceof Player player)) return; // Check if the event was a player who interacted with an anvil. - Player player = (Player) e.getWhoClicked(); if (e.getView().getType() != InventoryType.ANVIL) return; @@ -226,17 +199,18 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener return; } - if (anvilInventory.getItem(0) != null && anvilInventory.getItem(1) != null && - anvilInventory.getItem(2) != null && anvilInventory.getItem(2).getType() == Material.ELYTRA) + final @Nullable ItemStack item0 = anvilInventory.getItem(0); + final @Nullable ItemStack item1 = anvilInventory.getItem(1); + final @Nullable ItemStack item2 = anvilInventory.getItem(2); + + if (item0 != null && item1 != null && item2 != null && item2.getType() == Material.ELYTRA) { - ArmorTier armortier = nbtEditor.getArmorTier(anvilInventory.getItem(2)); + final ArmorTier armortier = nbtEditor.getArmorTier(anvilInventory.getItem(2)); // If there's an armored elytra in the final slot... if (armortier != ArmorTier.NONE && plugin.playerHasCraftPerm(player, armortier)) { - final ItemStack result = anvilInventory.getItem(2); - // Give the result to the player and clear the anvil's inventory. - if (!giveItemToPlayer(player, result, e.isShiftClick())) + if (!giveItemToPlayer(player, item2, e.isShiftClick())) return; // Clean the anvil's inventory after transferring the items. diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/ArmoredElytraHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/ArmoredElytraHandler.java index 3d50e2f..04b66f0 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/ArmoredElytraHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/ArmoredElytraHandler.java @@ -1,15 +1,12 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.nbtEditor.ArmoredElytraBuilder; +import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import nl.pim16aap2.armoredElytra.util.ConfigLoader; -import nl.pim16aap2.armoredElytra.util.DurabilityManager; -import org.bukkit.Bukkit; -import org.bukkit.Color; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.LeatherArmorMeta; import javax.annotation.CheckReturnValue; @@ -20,55 +17,30 @@ import javax.annotation.CheckReturnValue; */ abstract class ArmoredElytraHandler { - private static final Color DEFAULT_LEATHER_COLOR = Bukkit.getServer().getItemFactory().getDefaultLeatherColor(); - protected final ArmoredElytra plugin; protected final boolean creationEnabled; protected final ConfigLoader config; protected final NBTEditor nbtEditor; protected final DurabilityManager durabilityManager; + protected final ArmoredElytraBuilder armoredElytraBuilder; protected ArmoredElytraHandler(ArmoredElytra plugin, boolean creationEnabled, NBTEditor nbtEditor, - DurabilityManager durabilityManager, ConfigLoader config) + DurabilityManager durabilityManager, ConfigLoader config, + ArmoredElytraBuilder armoredElytraBuilder) { this.plugin = plugin; this.creationEnabled = creationEnabled; this.nbtEditor = nbtEditor; this.durabilityManager = durabilityManager; this.config = config; + this.armoredElytraBuilder = armoredElytraBuilder; } - /** - * Gets the color of the item if the item has a color. - *

- * See {@link LeatherArmorMeta#getColor()}. - * - * @param itemA The first {@link ItemStack} to check. - * @param itemB The second {@link ItemStack} to check. - * @return The color of the item, if it has a color, otherwise null. - */ - protected Color getItemColor(final ItemStack itemA, final ItemStack itemB) + protected ArmoredElytraHandler(ArmoredElytra plugin, boolean creationEnabled, NBTEditor nbtEditor, + DurabilityManager durabilityManager, ConfigLoader config) { - final Color colorA = getItemColor(itemA); - if (colorA != null && !colorA.equals(DEFAULT_LEATHER_COLOR)) - return colorA; - - final Color colorB = getItemColor(itemB); - return colorB != null ? colorB : colorA; - } - - private Color getItemColor(final ItemStack itemStack) - { - if (itemStack == null) - return null; - - if (itemStack.getType() == Material.ELYTRA) - return nbtEditor.getColorOfArmoredElytra(itemStack); - - if (!itemStack.hasItemMeta() || !(itemStack.getItemMeta() instanceof LeatherArmorMeta)) - return null; - - return ((LeatherArmorMeta) itemStack.getItemMeta()).getColor(); + this(plugin, creationEnabled, nbtEditor, durabilityManager, config, + new ArmoredElytraBuilder(nbtEditor, durabilityManager, config, plugin)); } /** @@ -76,8 +48,8 @@ abstract class ArmoredElytraHandler * * @param player The player to give the item to. * @param item The item to give. - * @param direct Whether or not to put it in the player's inventory. When set to false it will be put in their - * cursor instead. + * @param direct Whether to put it in the player's inventory. When set to false it will be put in their cursor + * instead. * @return True if the item could be given to the player, otherwise false (e.g. when their inventory is full). */ @CheckReturnValue diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java index ad5176d..f11b9b7 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java @@ -1,13 +1,13 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.nbtEditor.ArmoredElytraBuilder; +import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; -import nl.pim16aap2.armoredElytra.util.DurabilityManager; import nl.pim16aap2.armoredElytra.util.messages.Message; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; @@ -23,15 +23,13 @@ import java.util.logging.Level; public class CommandHandler implements CommandExecutor { private final ArmoredElytra plugin; - private final NBTEditor nbtEditor; - private final DurabilityManager durabilityManager; private static Field BY_KEY_FIELD; + private final ArmoredElytraBuilder armoredElytraBuilder; public CommandHandler(ArmoredElytra plugin, NBTEditor nbtEditor, DurabilityManager durabilityManager) { this.plugin = plugin; - this.nbtEditor = nbtEditor; - this.durabilityManager = durabilityManager; + armoredElytraBuilder = new ArmoredElytraBuilder(nbtEditor, durabilityManager, plugin.getConfigLoader(), plugin); } @Override @@ -86,10 +84,7 @@ public class CommandHandler implements CommandExecutor if (allowed) { plugin.elytraReceivedMessage(receiver, armorTier); - newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, - plugin.getConfigLoader().unbreakable()); - durabilityManager.setDurability(newElytra, 0, armorTier); - plugin.giveArmoredElytraToPlayer(receiver, newElytra); + plugin.giveArmoredElytraToPlayer(receiver, armoredElytraBuilder.newArmoredElytra(armorTier)); } else plugin.sendNoGivePermissionMessage(player, armorTier); @@ -115,7 +110,6 @@ public class CommandHandler implements CommandExecutor if (args.length == 2) { - ItemStack newElytra; final String tier = args[1]; player = Bukkit.getPlayer(args[0]); if (player != null) @@ -125,11 +119,7 @@ public class CommandHandler implements CommandExecutor return false; plugin.elytraReceivedMessage(player, armorTier); - newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, - plugin.getConfigLoader().unbreakable()); - durabilityManager.setDurability(newElytra, 0, armorTier); - - plugin.giveArmoredElytraToPlayer(player, newElytra); + plugin.giveArmoredElytraToPlayer(player, armoredElytraBuilder.newArmoredElytra(armorTier)); plugin.myLogger(Level.INFO, ("Giving an armored elytra of the " + ArmorTier.getArmor(armorTier) + " armor tier to player " + player.getName())); return true; diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java index 6133854..4386c4d 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java @@ -5,10 +5,10 @@ import nl.pim16aap2.armoredElytra.lib.armorequip.ArmorEquipEvent; import nl.pim16aap2.armoredElytra.lib.armorequip.ArmorListener; import nl.pim16aap2.armoredElytra.lib.armorequip.ArmorType; import nl.pim16aap2.armoredElytra.lib.armorequip.DispenserArmorListener; +import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import nl.pim16aap2.armoredElytra.util.AllowedToWearEnum; import nl.pim16aap2.armoredElytra.util.ArmorTier; -import nl.pim16aap2.armoredElytra.util.DurabilityManager; import nl.pim16aap2.armoredElytra.util.Util; import nl.pim16aap2.armoredElytra.util.messages.Message; import org.bukkit.Bukkit; @@ -63,9 +63,8 @@ public class EventHandlers implements Listener @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) public void onPlayerDamage(EntityDamageEvent e) { - if (!(e.getEntity() instanceof Player)) + if (!(e.getEntity() instanceof final Player p)) return; - final Player p = (Player) e.getEntity(); final ItemStack elytra = p.getInventory().getChestplate(); if (elytra == null) diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java index 0549b9b..2f50b1d 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java @@ -1,8 +1,8 @@ package nl.pim16aap2.armoredElytra.handlers; +import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; -import nl.pim16aap2.armoredElytra.util.DurabilityManager; import nl.pim16aap2.armoredElytra.util.Util; import org.bukkit.Material; import org.bukkit.event.EventHandler; diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/NetheriteUpgradeListener.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/NetheriteUpgradeListener.java index 88b972d..46b1e1d 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/NetheriteUpgradeListener.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/NetheriteUpgradeListener.java @@ -1,18 +1,19 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.ConfigLoader; -import nl.pim16aap2.armoredElytra.util.DurabilityManager; import org.bukkit.Material; -import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.PrepareSmithingEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.SmithingInventory; +import javax.annotation.Nullable; + public class NetheriteUpgradeListener extends SmithingTableListener { public NetheriteUpgradeListener(final ArmoredElytra plugin, NBTEditor nbtEditor, @@ -21,43 +22,47 @@ public class NetheriteUpgradeListener extends SmithingTableListener super(plugin, false, nbtEditor, durabilityManager, config); } - @Override @EventHandler(ignoreCancelled = true) + @EventHandler(ignoreCancelled = true) public void onSmithingTableUsage(final PrepareSmithingEvent event) { - super.onSmithingTableUsage(event); + final SmithingInventory inventory = event.getInventory(); + final ItemStack[] contents = inventory.getContents(); + + final ItemStack itemStackA = contents[0]; + final ItemStack itemStackB = contents[1]; + + if (!validInput(itemStackA, itemStackB)) + return; + + if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), ArmorTier.NETHERITE)) + return; + + event.setResult(armoredElytraBuilder + .newBuilder() + .ofElytra(itemStackA) + .upgradeToTier(ArmorTier.NETHERITE) + .build()); } - @Override - protected ArmorTier getArmorTier(ItemStack itemStackA, ItemStack itemStackB) + private boolean validInput(@Nullable ItemStack itemStackA, @Nullable ItemStack itemStackB) { if (itemStackA == null || itemStackB == null || itemStackA.getType() != Material.ELYTRA || plugin.getNbtEditor().getArmorTier(itemStackA) != ArmorTier.DIAMOND || itemStackB.getType() != Material.NETHERITE_INGOT) - return ArmorTier.NONE; + return false; // For some reason, adding multiple netherite ingots causes the view to not update properly. // The resulting armored elytra is hidden and the red cross indicates the combination is impossible. // But if you click on where the output was supposed to be, it DOES work for some reason. // It kinda works if you add a slight delay, but I don't really like that. Might revisit this later. CBA now. - if (itemStackA.getAmount() != 1 || itemStackB.getAmount() != 1) - return ArmorTier.NONE; - - return ArmorTier.NETHERITE; + return itemStackA.getAmount() == 1 && itemStackB.getAmount() == 1; } + @Override @EventHandler(ignoreCancelled = true) public void onInventoryClick(InventoryClickEvent event) { - if (!isAESmithingTableEvent(event)) - return; - - // These casts may look unchecked, but it was checked by isSmithingTableEvent already. - SmithingInventory smithingInventory = (SmithingInventory) event.getInventory(); - Player player = (Player) event.getWhoClicked(); - - if (!giveItemToPlayer(player, smithingInventory.getItem(2), event.isShiftClick())) - return; - smithingInventory.clear(); + super.onInventoryClick(event); } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableCraftHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableCraftHandler.java index 24476d2..254fcf9 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableCraftHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableCraftHandler.java @@ -1,14 +1,13 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.ConfigLoader; -import nl.pim16aap2.armoredElytra.util.DurabilityManager; import nl.pim16aap2.armoredElytra.util.Util; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.PrepareSmithingEvent; @@ -26,15 +25,26 @@ public class SmithingTableCraftHandler extends SmithingTableListener .registerEvents(new AnvilHandler(plugin, false, nbtEditor, durabilityManager, config), plugin); } - @Override @EventHandler(ignoreCancelled = true) public void onSmithingTableUsage(final PrepareSmithingEvent event) { - super.onSmithingTableUsage(event); + final SmithingInventory inventory = event.getInventory(); + final ItemStack[] contents = inventory.getContents(); + + final ItemStack itemStackA = contents[0]; + final ItemStack itemStackB = contents[1]; + + final ArmorTier newArmorTier = getNewArmorTier(itemStackA, itemStackB); + if (newArmorTier == ArmorTier.NONE) + return; + + if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), newArmorTier)) + return; + + event.setResult(armoredElytraBuilder.combine(itemStackA, itemStackB, newArmorTier, null)); } - @Override - protected ArmorTier getArmorTier(ItemStack itemStackA, ItemStack itemStackB) + protected ArmorTier getNewArmorTier(ItemStack itemStackA, ItemStack itemStackB) { if (itemStackA == null || itemStackB == null || itemStackA.getType() != Material.ELYTRA || !Util.isChestPlate(itemStackB)) @@ -43,17 +53,10 @@ public class SmithingTableCraftHandler extends SmithingTableListener return Util.armorToTier(itemStackB.getType()); } + @Override @EventHandler(ignoreCancelled = true) - public void onInventoryClick(InventoryClickEvent e) + public void onInventoryClick(InventoryClickEvent event) { - if (!isAESmithingTableEvent(e)) - return; - final SmithingInventory smithingInventory = (SmithingInventory) e.getInventory(); - final ItemStack result = smithingInventory.getItem(2); - - // This cast may look unchecked, but it was checked by isSmithingTableEvent already. - if (!giveItemToPlayer((Player) e.getWhoClicked(), result, e.isShiftClick())) - return; - smithingInventory.clear(); + super.onInventoryClick(event); } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableListener.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableListener.java index b151a9a..0adfe37 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableListener.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableListener.java @@ -1,18 +1,15 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.ConfigLoader; -import nl.pim16aap2.armoredElytra.util.DurabilityManager; -import nl.pim16aap2.armoredElytra.util.EnchantmentContainer; -import org.bukkit.Color; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryType; -import org.bukkit.event.inventory.PrepareSmithingEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.SmithingInventory; @@ -26,47 +23,19 @@ abstract class SmithingTableListener extends ArmoredElytraHandler implements Lis super(plugin, creationEnabled, nbtEditor, durabilityManager, config); } - public void onSmithingTableUsage(final PrepareSmithingEvent event) + protected void onInventoryClick(InventoryClickEvent event) { - final SmithingInventory inventory = event.getInventory(); - final ItemStack[] contents = inventory.getContents(); - - final ItemStack itemStackA = contents[0]; - final ItemStack itemStackB = contents[1]; - - final ArmorTier newTier = getArmorTier(itemStackA, itemStackB); - if (newTier == ArmorTier.NONE) + if (!isAESmithingTableEvent(event)) return; + final SmithingInventory smithingInventory = (SmithingInventory) event.getInventory(); + final ItemStack result = smithingInventory.getItem(2); - final Player player = (Player) event.getView().getPlayer(); - - if (plugin.playerHasCraftPerm(player, newTier)) - { - final EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemStackA, plugin); - enchantments.merge(EnchantmentContainer.getEnchantments(itemStackB, plugin)); - final Color color = getItemColor(itemStackA, itemStackB); - - final ItemStack result = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), newTier, - plugin.getConfigLoader().unbreakable(), color); - durabilityManager.setCombinedDurability(result, itemStackA, itemStackB, - nbtEditor.getArmorTier(itemStackA), newTier); - - enchantments.applyEnchantments(result); - event.setResult(result); - } + // This cast may look unchecked, but it was checked by isSmithingTableEvent already. + if (!giveItemToPlayer((Player) event.getWhoClicked(), result, event.isShiftClick())) + return; + smithingInventory.clear(); } - /** - * Checks if the provided input {@link ItemStack}s form a valid input pattern for a smithing table, and, if so, - * which tier it combines into. - * - * @param itemStackA The first {@link ItemStack}. - * @param itemStackB The second {@link ItemStack}. - * @return The {@link ArmorTier} as figured out from the input pattern. If the pattern is invalid, {@link - * ArmorTier#NONE} is returned. - */ - protected abstract ArmorTier getArmorTier(ItemStack itemStackA, ItemStack itemStackB); - /** * Checks if an {@link InventoryClickEvent} is useful for this plugin. I.e., it is about a smithing inventory and * there is an (armored) elytra involved somehow. diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/ArmoredElytraBuilder.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/ArmoredElytraBuilder.java new file mode 100644 index 0000000..12bda6a --- /dev/null +++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/ArmoredElytraBuilder.java @@ -0,0 +1,469 @@ +package nl.pim16aap2.armoredElytra.nbtEditor; + +import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.util.ArmorTier; +import nl.pim16aap2.armoredElytra.util.ConfigLoader; +import nl.pim16aap2.armoredElytra.util.EnchantmentContainer; +import nl.pim16aap2.armoredElytra.util.Util; +import org.bukkit.Bukkit; +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.LeatherArmorMeta; + +import javax.annotation.Nullable; +import java.util.List; + +@SuppressWarnings({"unused", "UnusedReturnValue", "ClassCanBeRecord"}) +public class ArmoredElytraBuilder +{ + private final NBTEditor nbtEditor; + private final DurabilityManager durabilityManager; + private final ConfigLoader config; + private final ArmoredElytra plugin; + + public ArmoredElytraBuilder(NBTEditor nbtEditor, DurabilityManager durabilityManager, + ConfigLoader config, ArmoredElytra plugin) + { + + this.nbtEditor = nbtEditor; + this.durabilityManager = durabilityManager; + this.config = config; + this.plugin = plugin; + } + + /** + * Creates a new builder for an armored elytra. + * + * @return The first step of the new builder. + */ + public IStep0 newBuilder() + { + return new Builder(nbtEditor, durabilityManager, config, plugin); + } + + /** + * Shortcut for repairing an armored elytra. + * + * @param armoredElytra The armored elytra to repair. + * @param repairItems The repair item(s) to use for repairing the armored elytra. It is assumed that they are of + * the correct type. + * @param name The new name of the output armored elytra. When this is null, {@link + * ArmoredElytra#getArmoredElytraName(ArmorTier)} is used to set the name. + * @return The new armored elytra. + */ + public @Nullable ItemStack repair(ItemStack armoredElytra, ItemStack repairItems, @Nullable String name) + { + return newBuilder().ofElytra(armoredElytra).repair(repairItems.getAmount()).withName(name).build(); + } + + /** + * Shortcut for enchanting an armored elytra. + * + * @param armoredElytra The armored elytra to repair. + * @param sourceItem The source item from which to copy the enchantments from. + * @param name The new name of the output armored elytra. When this is null, {@link + * ArmoredElytra#getArmoredElytraName(ArmorTier)} is used to set the name. + * @return The new armored elytra. + */ + public @Nullable ItemStack enchant(ItemStack armoredElytra, ItemStack sourceItem, @Nullable String name) + { + final EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(sourceItem, plugin); + if (enchantments.isEmpty()) + return null; + return newBuilder().ofElytra(armoredElytra).addEnchantments(enchantments).withName(name).build(); + } + + /** + * Shortcut for creating a new armored elytra from two items. + * + * @param elytra The input item. This should be an (armored) elytra. + * @param combiner The item to combine with the elytra. This should either be an armored elytra of the same + * non-NONE tier as the input elytra or a chestplate. + * @param armorTier The armor tier of the input item. If this is not known, use {@link #combine(ItemStack, + * ItemStack, String)} instead. + * @param name The new name of the output armored elytra. When this is null, {@link + * ArmoredElytra#getArmoredElytraName(ArmorTier)} is used to set the name. + * @return The new armored elytra. + */ + public ItemStack combine(ItemStack elytra, ItemStack combiner, ArmorTier armorTier, @Nullable String name) + { + return newBuilder().ofElytra(elytra).combineWith(combiner, armorTier).withName(name).build(); + } + + /** + * See {@link #combine(ItemStack, ItemStack, ArmorTier, String)} for unknown armor tiers. + */ + public ItemStack combine(ItemStack elytra, ItemStack combiner, @Nullable String name) + { + return newBuilder().ofElytra(elytra).combineWith(combiner).withName(name).build(); + } + + /** + * Creates a new armored elytra of a specific tier. + * + * @param armorTier The tier of the new armored elytra. + * @return The new armored elytra. + */ + public ItemStack newArmoredElytra(ArmorTier armorTier) + { + return newBuilder().newItem(armorTier).build(); + } + + /** + * Represents the third and last step of the armored elytra build process. + */ + public interface IStep2 + { + /** + * Specifies the new name of the armored elytra. + * + * @param name The new name of the armored elytra. When this is null (default), the default name for the new + * tier will be used. + * @return The current builder step. + */ + IStep2 withName(@Nullable String name); + + /** + * Specifies the new color of the armored elytra. + * + * @param color The new color of the armored elytra. When this is null (default), the color to use is inferred + * from the creation process. + * @return The current builder step. + */ + IStep2 withColor(@Nullable Color color); + + /** + * Specifies the new lore of the armored elytra. + * + * @param lore The new lore of the armored elytra. When this is null (default), the default lore for the new + * tier will be used. + * @return The current builder step. + */ + IStep2 withLore(@Nullable List lore); + + /** + * Specifies whether the armored elytra should be unbreakable. + *

+ * By default, this value is read from {@link ConfigLoader#unbreakable()}. + * + * @param isUnbreakable True if the armored elytra should be unbreakable. + * @return The current builder step. + */ + IStep2 unbreakable(boolean isUnbreakable); + + /** + * Constructs the armored elytra from the provided configuration. + * + * @return The new armored elytra. + */ + ItemStack build(); + } + + /** + * Represents the second and last step of the armored elytra build process. + */ + public interface IStep1 + { + /** + * Repairs the armored elytra provided as input. + * + * @param count The amount of repair items to process. + * @return The next step of the builder process. + */ + IStep2 repair(int count); + + /** + * Adds a set of enchantments to the armored elytra. + * + * @param enchantmentContainer The enchantments to add. + * @return The next step of the builder process. + */ + IStep2 addEnchantments(EnchantmentContainer enchantmentContainer); + + /** + * Adds a set of enchantments to the armored elytra. + * + * @param sourceItem The source item from which to take the enchantments. + * @return The next step of the builder process. + */ + IStep2 addEnchantments(ItemStack sourceItem); + + /** + * Combines the input elytra with another item. + * + * @param item The item to combine with the input elytra. This can either be a chestplate or, if the input + * elytra is an armored one, another armored elytra. + * @param armorTier The armor tier of the input item. If this is not known, use {@link #combineWith(ItemStack)} + * instead. + * @return The next step of the builder process. + */ + IStep2 combineWith(ItemStack item, ArmorTier armorTier); + + /** + * See {@link #combineWith(ItemStack, ArmorTier)}. Used when the armor tier of the input item is not known. + * + * @return The next step of the builder process. + */ + IStep2 combineWith(ItemStack item); + + /** + * Upgrades the elytra to a specific armor tier. + * + * @param armorTier The new armor tier. + * @return The next step of the builder process. + */ + IStep2 upgradeToTier(ArmorTier armorTier); + } + + /** + * Represents the first and last step of the armored elytra build process. + */ + public interface IStep0 + { + /** + * Use an elytra as base item to create the new armored elytra from. + * + * @param elytra An itemstack that represents an elytra. It does not matter whether the elytra is armored or + * not. + * @return The next step of the builder process. + */ + IStep1 ofElytra(ItemStack elytra); + + /** + * Creates a fresh new armored elytra of a specific tier. + * + * @param armorTier The tier of the new armored elytra. + * @return The next step of the builder process. + */ + IStep2 newItem(ArmorTier armorTier); + } + + private static final class Builder implements IStep0, IStep1, IStep2 + { + private static final Color DEFAULT_LEATHER_COLOR = Bukkit.getServer().getItemFactory().getDefaultLeatherColor(); + + private final NBTEditor nbtEditor; + private final DurabilityManager durabilityManager; + private final ConfigLoader config; + private final ArmoredElytra plugin; + + // These aren't nullable, as they are set by the only entry points. + /** + * The new armored elytra that will be returned at the end of the build process. + */ + private ItemStack newArmoredElytra; + /** + * The combined enchantments of the input items. + */ + private EnchantmentContainer combinedEnchantments; + /** + * The current armor tier of the input elytra. + */ + private ArmorTier currentArmorTier; + /** + * The durability of the output armored elytra. + */ + private int durability; + + + /** + * The armor tier of the output armored elytra. This defaults to {@link #currentArmorTier} if this isn't set. + */ + private @Nullable ArmorTier newArmorTier; + /** + * The name of the output armored elytra. This defaults to {@link ArmoredElytra#getArmoredElytraName(ArmorTier)} + * when not overridden. + */ + private @Nullable String name; + /** + * The lore of the output armored elytra. This defaults to {@link ArmoredElytra#getElytraLore(ArmorTier)} when + * not overridden. + */ + private @Nullable List lore; + /** + * The color of the output armored elytra. By default, the existing color (if any is used). When combined with + * another item, the color is inferred using {@link #getItemColor(ItemStack, ItemStack)}. + */ + private @Nullable Color color; + /** + * Whether the output armored elytra should be unbreakable. This defaults to {@link ConfigLoader#unbreakable()} + * when not overridden. + */ + private boolean isUnbreakable; + + private Builder(NBTEditor nbtEditor, DurabilityManager durabilityManager, + ConfigLoader config, ArmoredElytra plugin) + { + this.nbtEditor = nbtEditor; + this.durabilityManager = durabilityManager; + this.config = config; + this.plugin = plugin; + } + + @Override + public ItemStack build() + { + // Get default values if unset. + newArmorTier = newArmorTier == null ? currentArmorTier : newArmorTier; + name = name == null ? plugin.getArmoredElytraName(newArmorTier) : name; + lore = lore == null ? plugin.getElytraLore(newArmorTier) : lore; + + final ItemStack output = nbtEditor.addArmorNBTTags(newArmoredElytra, newArmorTier, + isUnbreakable, name, lore, color); + durabilityManager.setDurability(output, durability, newArmorTier); + combinedEnchantments.applyEnchantments(output); + + return output; + } + + @Override + public IStep2 withName(@Nullable String name) + { + this.name = name; + return this; + } + + @Override + public IStep2 withColor(@Nullable Color color) + { + this.color = color; + return this; + } + + @Override + public IStep2 withLore(@Nullable List lore) + { + this.lore = lore; + return this; + } + + @Override + public IStep2 unbreakable(boolean isUnbreakable) + { + this.isUnbreakable = isUnbreakable; + return this; + } + + @Override + public IStep2 repair(int count) + { + if (currentArmorTier == ArmorTier.NONE) + throw new IllegalArgumentException("Non-armored elytras cannot be repaired!"); + durabilityManager.getRepairedDurability(newArmoredElytra, count, currentArmorTier); + return this; + } + + @Override + public IStep2 addEnchantments(EnchantmentContainer enchantmentContainer) + { + combinedEnchantments.merge(enchantmentContainer); + return this; + } + + @Override + public IStep2 addEnchantments(ItemStack sourceItem) + { + return addEnchantments(EnchantmentContainer.getEnchantments(sourceItem, plugin)); + } + + @Override + public IStep2 combineWith(ItemStack item, ArmorTier armorTier) + { + if (armorTier == ArmorTier.NONE && !Util.isChestPlate(item)) + throw new IllegalArgumentException("Non-armored elytras can only be combined with chest plates!"); + + newArmorTier = armorTier; + if (currentArmorTier == ArmorTier.NONE && + item.getType().equals(Material.ELYTRA) && newArmorTier != ArmorTier.NONE) + throw new IllegalArgumentException("A regular elytra cannot be combined with an armored one!"); + + withColor(getItemColor(newArmoredElytra, item)); + unbreakable(config.unbreakable()); + + addEnchantments(item); + + durability = durabilityManager.getCombinedDurability(newArmoredElytra, item, + currentArmorTier, newArmorTier); + return this; + } + + @Override + public IStep2 combineWith(ItemStack item) + { + final ArmorTier armorTier = item.getType().equals(Material.ELYTRA) ? + nbtEditor.getArmorTier(item) : Util.armorToTier(item.getType()); + return combineWith(item, armorTier); + } + + @Override + public IStep2 upgradeToTier(ArmorTier armorTier) + { + newArmorTier = armorTier; + return this; + } + + @Override + public IStep1 ofElytra(ItemStack elytra) + { + if (!elytra.getType().equals(Material.ELYTRA)) + throw new IllegalArgumentException("Expected elytra as input, but got: " + elytra); + + newArmoredElytra = new ItemStack(elytra); + + if (currentArmorTier == null) + currentArmorTier = nbtEditor.getArmorTier(elytra); + + combinedEnchantments = EnchantmentContainer.getEnchantments(newArmoredElytra, plugin); + + durability = durabilityManager.getRealDurability(newArmoredElytra, currentArmorTier); + return this; + } + + @Override + public IStep2 newItem(ArmorTier armorTier) + { + currentArmorTier = newArmorTier = armorTier; + ofElytra(new ItemStack(Material.ELYTRA)); + return this; + } + + /** + * Gets the color of the item if the item has a color. + *

+ * See {@link LeatherArmorMeta#getColor()}. + * + * @param itemA The first {@link ItemStack} to check. + * @param itemB The second {@link ItemStack} to check. + * @return The color of the item, if it has a color, otherwise null. + */ + private @Nullable Color getItemColor(final ItemStack itemA, final ItemStack itemB) + { + final @Nullable Color colorA = getItemColor(itemA); + if (colorA != null && !colorA.equals(DEFAULT_LEATHER_COLOR)) + return colorA; + + final @Nullable Color colorB = getItemColor(itemB); + return colorB != null ? colorB : colorA; + } + + /** + * Gets the colors of an item if available. + *

+ * This currently only applies to leather armor(ed elytras). + * + * @param itemStack The item to analyze. + * @return The color of the item, if available, otherwise null. + */ + private @Nullable Color getItemColor(final ItemStack itemStack) + { + if (itemStack.getType() == Material.ELYTRA) + return nbtEditor.getColorOfArmoredElytra(itemStack); + + if (!itemStack.hasItemMeta() || !(itemStack.getItemMeta() instanceof LeatherArmorMeta)) + return null; + + return ((LeatherArmorMeta) itemStack.getItemMeta()).getColor(); + } + } +} diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/DurabilityManager.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/DurabilityManager.java similarity index 98% rename from src/main/java/nl/pim16aap2/armoredElytra/util/DurabilityManager.java rename to src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/DurabilityManager.java index 74745f8..25eae1b 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/util/DurabilityManager.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/DurabilityManager.java @@ -1,6 +1,8 @@ -package nl.pim16aap2.armoredElytra.util; +package nl.pim16aap2.armoredElytra.nbtEditor; -import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; +import nl.pim16aap2.armoredElytra.util.ArmorTier; +import nl.pim16aap2.armoredElytra.util.ConfigLoader; +import nl.pim16aap2.armoredElytra.util.Util; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java index 186b6e2..c62e79f 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java @@ -118,7 +118,7 @@ public class NBTEditor return ret; } - private void overwriteNBTValue(ItemMeta meta, Attribute attribute, double value, String modifierName) + void overwriteNBTValue(ItemMeta meta, Attribute attribute, double value, String modifierName) { if (meta.hasAttributeModifiers()) meta.removeAttributeModifier(attribute); @@ -129,7 +129,7 @@ public class NBTEditor meta.addAttributeModifier(attribute, attributeModifier); } - private ArmorTier getArmorTier(@Nullable ItemMeta meta) + ArmorTier getArmorTier(@Nullable ItemMeta meta) { if (meta == null || !meta.hasAttributeModifiers()) return ArmorTier.NONE; @@ -191,7 +191,7 @@ public class NBTEditor return rgb == null ? null : Color.fromRGB(rgb); } - private static ItemMeta getOrCreateItemMeta(ItemStack item) + static ItemMeta getOrCreateItemMeta(ItemStack item) { final ItemMeta meta = item.hasItemMeta() ? item.getItemMeta() : @@ -200,71 +200,4 @@ public class NBTEditor throw new IllegalArgumentException("Tried to add armor to invalid item: " + item); return meta; } - - /** - * Adds a given {@link ArmorTier} to an item. The item will be cloned. Note that setting the armor tier to {@link - * ArmorTier#NONE} has no effect (besides making a copy of the item). The default name for the given tier is - * applied. See {@link ArmoredElytra#getArmoredElytraName(ArmorTier)}. - * - * @param item The item. - * @param armorTier The {@link ArmorTier} that will be added to it. - * @param unbreakable Whether the resulting item should be unbreakable. - * @return The NEW item. - */ - public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable) - { - return addArmorNBTTags(item, armorTier, unbreakable, (Color) null); - } - - /** - * Adds a given {@link ArmorTier} to an item. The item will be cloned. Note that setting the armor tier to {@link - * ArmorTier#NONE} has no effect (besides making a copy of the item). - * - * @param item The item. - * @param armorTier The {@link ArmorTier} that will be added to it. - * @param unbreakable Whether the resulting item should be unbreakable. - * @param name The name fo the item. - * @return The NEW item. - */ - public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable, final String name) - { - return addArmorNBTTags(item, armorTier, unbreakable, name, null, null); - } - - /** - * Adds a given {@link ArmorTier} to an item. The item will be cloned. Note that setting the armor tier to {@link - * ArmorTier#NONE} has no effect (besides making a copy of the item). The default name for the given tier is - * applied. See {@link ArmoredElytra#getArmoredElytraName(ArmorTier)}. - * - * @param item The item. - * @param armorTier The {@link ArmorTier} that will be added to it. - * @param unbreakable Whether the resulting item should be unbreakable. - * @param color The color of the armor to store. May be null. - * @return The NEW item. - */ - public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable, final Color color) - { - return addArmorNBTTags(item, armorTier, unbreakable, - ArmoredElytra.getInstance().getArmoredElytraName(armorTier), - ArmoredElytra.getInstance().getElytraLore(armorTier), color); - } - - /** - * Adds a given {@link ArmorTier} to an item. The item will be cloned. Note that setting the armor tier to {@link - * ArmorTier#NONE} has no effect (besides making a copy of the item). The default name for the given tier is - * applied. See {@link ArmoredElytra#getArmoredElytraName(ArmorTier)}. - * - * @param item The item. - * @param armorTier The {@link ArmorTier} that will be added to it. - * @param unbreakable Whether the resulting item should be unbreakable. - * @param name The name of the item. - * @param color The color of the armor to store. May be null. - * @return The NEW item. - */ - public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable, String name, - Color color) - { - return addArmorNBTTags(item, armorTier, unbreakable, name, - ArmoredElytra.getInstance().getElytraLore(armorTier), color); - } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/EnchantmentContainer.java b/src/main/java/nl/pim16aap2/armoredElytra/util/EnchantmentContainer.java index eecc127..0b41fe2 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/util/EnchantmentContainer.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/EnchantmentContainer.java @@ -28,6 +28,19 @@ public class EnchantmentContainer filter(plugin.getConfigLoader().allowedEnchantments()); } + /** + * Copy constructor. + */ + public EnchantmentContainer(EnchantmentContainer other) + { + this(other.enchantments); + } + + public EnchantmentContainer() + { + enchantments = new HashMap<>(); + } + private EnchantmentContainer(final Map enchantments) { this.enchantments = new HashMap<>(enchantments); @@ -117,6 +130,8 @@ public class EnchantmentContainer */ public void merge(EnchantmentContainer other) { + if (this == other) + throw new IllegalArgumentException("EnchantmentContainers cannot be combined with themselves!"); enchantments = merge(enchantments, other.enchantments); } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java b/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java index c8667ee..4461677 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java @@ -34,6 +34,12 @@ public class Util return item.getDurability() >= item.getType().getMaxDurability(); } + // Get the armor tier from a chest plate. + public static ArmorTier armorToTier(ItemStack itemStack) + { + return armorToTier(itemStack.getType()); + } + // Get the armor tier from a chest plate. public static ArmorTier armorToTier(Material mat) {