diff --git a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java index a0497a2..c141784 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java @@ -6,7 +6,8 @@ import nl.pim16aap2.armoredElytra.handlers.EventHandlers; import nl.pim16aap2.armoredElytra.handlers.FlyDurabilityHandler; import nl.pim16aap2.armoredElytra.handlers.ItemDropListener; import nl.pim16aap2.armoredElytra.handlers.LoginHandler; -import nl.pim16aap2.armoredElytra.handlers.SmithingTableHandler; +import nl.pim16aap2.armoredElytra.handlers.NetheriteUpgradeListener; +import nl.pim16aap2.armoredElytra.handlers.SmithingTableCraftHandler; import nl.pim16aap2.armoredElytra.handlers.Uninstaller; import nl.pim16aap2.armoredElytra.nbtEditor.INBTEditor; import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; @@ -105,8 +106,10 @@ public class ArmoredElytra extends JavaPlugin implements Listener myLogger(Level.INFO, "Durability penalty for flying enabled!"); final Listener creationListener = config.craftingInSmithingTable() ? - new SmithingTableHandler(this) : new AnvilHandler(this); + new SmithingTableCraftHandler(this) : new AnvilHandler(this); Bukkit.getPluginManager().registerEvents(creationListener, this); + if (config.allowUpgradeToNetherite()) + Bukkit.getPluginManager().registerEvents(new NetheriteUpgradeListener(this), this); if (config.dropNetheriteAsChestplate()) Bukkit.getPluginManager().registerEvents(new ItemDropListener(this), this); diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/NetheriteUpgradeListener.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/NetheriteUpgradeListener.java new file mode 100644 index 0000000..862dc4e --- /dev/null +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/NetheriteUpgradeListener.java @@ -0,0 +1,58 @@ +package nl.pim16aap2.armoredElytra.handlers; + +import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.util.ArmorTier; +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; + +public class NetheriteUpgradeListener extends SmithingTableListener +{ + public NetheriteUpgradeListener(final ArmoredElytra plugin) + { + super(plugin); + } + + @EventHandler(ignoreCancelled = true) + public void onSmithingTableUsage(final PrepareSmithingEvent event) + { + super.onSmithingTableUsage(event); + } + + @Override + protected ArmorTier getArmorTier(ItemStack itemStackA, 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; + + // 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; + } + + @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(); + + giveItemToPlayer(player, smithingInventory.getItem(2), event.isShiftClick()); + smithingInventory.clear(); + } +} diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableCraftHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableCraftHandler.java new file mode 100644 index 0000000..3770ad3 --- /dev/null +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableCraftHandler.java @@ -0,0 +1,52 @@ +package nl.pim16aap2.armoredElytra.handlers; + +import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.util.ArmorTier; +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; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.SmithingInventory; + +public class SmithingTableCraftHandler extends SmithingTableListener +{ + public SmithingTableCraftHandler(final ArmoredElytra plugin) + { + super(plugin, true); + // Register the anvil handler with creation disabled so AEs can still be repaired and stuff. + Bukkit.getPluginManager().registerEvents(new AnvilHandler(plugin, false), plugin); + } + + @EventHandler(ignoreCancelled = true) + public void onSmithingTableUsage(final PrepareSmithingEvent event) + { + super.onSmithingTableUsage(event); + } + + @Override + protected ArmorTier getArmorTier(ItemStack itemStackA, ItemStack itemStackB) + { + if (itemStackA == null || itemStackB == null || + itemStackA.getType() != Material.ELYTRA || !Util.isChestPlate(itemStackB)) + return ArmorTier.NONE; + + return Util.armorToTier(itemStackB.getType()); + } + + @EventHandler(ignoreCancelled = true) + public void onInventoryClick(InventoryClickEvent e) + { + if (!isAESmithingTableEvent(e)) + return; + SmithingInventory smithingInventory = (SmithingInventory) e.getInventory(); + final ItemStack result = smithingInventory.getItem(2); + + // This cast may look unchecked, but it was checked by isSmithingTableEvent already. + giveItemToPlayer((Player) e.getWhoClicked(), result, e.isShiftClick()); + smithingInventory.clear(); + } +} diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableListener.java similarity index 56% rename from src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableHandler.java rename to src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableListener.java index 8f87e60..16804c5 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableListener.java @@ -3,11 +3,8 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.EnchantmentContainer; -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.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryType; @@ -17,16 +14,19 @@ import org.bukkit.inventory.SmithingInventory; import java.util.logging.Level; -public class SmithingTableHandler extends ArmoredElytraHandler implements Listener +abstract class SmithingTableListener extends ArmoredElytraHandler implements Listener { - public SmithingTableHandler(final ArmoredElytra plugin) + public SmithingTableListener(ArmoredElytra plugin, boolean creationEnabled) { - super(plugin, true); - // Register the anvil handler with creation disabled so AEs can still be repaired and stuff. - Bukkit.getPluginManager().registerEvents(new AnvilHandler(plugin, false), plugin); + super(plugin, creationEnabled); + + } + + public SmithingTableListener(ArmoredElytra plugin) + { + this(plugin, false); } - @EventHandler(ignoreCancelled = true) public void onSmithingTableUsage(final PrepareSmithingEvent event) { final SmithingInventory inventory = event.getInventory(); @@ -35,11 +35,10 @@ public class SmithingTableHandler extends ArmoredElytraHandler implements Listen final ItemStack itemStackA = contents[0]; final ItemStack itemStackB = contents[1]; - if (itemStackA == null || itemStackB == null || - itemStackA.getType() != Material.ELYTRA || !Util.isChestPlate(itemStackB)) + final ArmorTier newTier = getArmorTier(itemStackA, itemStackB); + if (newTier == ArmorTier.NONE) return; - final ArmorTier newTier = Util.armorToTier(itemStackB.getType()); EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemStackA, plugin); final Player player = (Player) event.getView().getPlayer(); @@ -54,24 +53,40 @@ public class SmithingTableHandler extends ArmoredElytraHandler implements Listen } } - // Let the player take items out of the smithing table. - @EventHandler(ignoreCancelled = true) - public void onInventoryClick(InventoryClickEvent e) + /** + * 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. + * + * @param event The {@link InventoryClickEvent} which may be of use to us. + * @return True if this plugin can process this event further. + */ + protected boolean isAESmithingTableEvent(final InventoryClickEvent event) { - if (e.getRawSlot() != 2 || !(e.getWhoClicked() instanceof Player)) - return; + if (event.getRawSlot() != 2) + return false; // Check if the event was a player who interacted with a smithing table. - Player player = (Player) e.getWhoClicked(); - if (e.getView().getType() != InventoryType.SMITHING) - return; + Player player = (Player) event.getWhoClicked(); + if (event.getView().getType() != InventoryType.SMITHING) + return false; SmithingInventory smithingInventory; // Try to cast inventory being used in the event to a smithing inventory. // This will throw a ClassCastException when a CraftInventoryCustom is used. try { - smithingInventory = (SmithingInventory) e.getInventory(); + smithingInventory = (SmithingInventory) event.getInventory(); } catch (ClassCastException exception) { @@ -80,15 +95,19 @@ public class SmithingTableHandler extends ArmoredElytraHandler implements Listen plugin.debugMsg(Level.WARNING, "Could not cast inventory to SmithingInventory for player " + player.getName() + "! Armored Elytras cannot be crafted!"); exception.printStackTrace(); - return; + return false; } - final ItemStack result = smithingInventory.getItem(2); - if (result == null || result.getType() != Material.ELYTRA || - ArmoredElytra.getInstance().getNbtEditor().getArmorTier(result) == ArmorTier.NONE) - return; + if (smithingInventory.getItem(0) == null || + smithingInventory.getItem(1) == null || + smithingInventory.getItem(2) == null) + return false; - giveItemToPlayer(player, result, e.isShiftClick()); - smithingInventory.clear(); + final ItemStack result = smithingInventory.getItem(2); + if (result.getType() != Material.ELYTRA || + ArmoredElytra.getInstance().getNbtEditor().getArmorTier(result) == ArmorTier.NONE) + return false; + + return true; } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java b/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java index 32b89a7..dc1567f 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java @@ -35,6 +35,7 @@ public class ConfigLoader private LinkedHashSet allowedEnchantments; private boolean allowMultipleProtectionEnchantments; private boolean craftingInSmithingTable; + private boolean allowUpgradeToNetherite; private boolean bypassWearPerm; private boolean bypassCraftPerm; private boolean allowRenaming; @@ -126,6 +127,12 @@ public class ConfigLoader "This option only works on 1.16+! When enabled, armored elytra creation in anvils is disabled. ", "Instead, you will have to craft them in a smithy. Enchanting/repairing them still works via the anvil." }; + String[] allowUpgradeToNetheriteComment = + { + "Whether or not to allow upgrading diamond armored elytras to netherite ones is possible.", + "When allowed (on 1.16+), you can combine a diamond one with a netherite ingot in a smithing table", + "and you'll receive a netherite one." + }; String[] allowRenamingComment = { "Whether or not to allow renaming of armored elytras in anvils." @@ -158,6 +165,14 @@ public class ConfigLoader "but this is only supported on 1.16+! Reverting to disabled."); craftingInSmithingTable = false; } + allowUpgradeToNetherite = addNewConfigOption(config, "allowUpgradeToNetherite", smithingTableAllowed, + allowUpgradeToNetheriteComment); + if (allowUpgradeToNetherite && !smithingTableAllowed) + { + Bukkit.getLogger().log(Level.WARNING, "You tried to enable crafting in smithing tables, " + + "but this is only supported on 1.16+! Reverting to disabled."); + allowUpgradeToNetherite = false; + } defaultAllowedEnchantments = addNewConfigOption(config, "allowedEnchantments", defaultAllowedEnchantments, enchantmentsComment); @@ -258,6 +273,11 @@ public class ConfigLoader return craftingInSmithingTable; } + public boolean allowUpgradeToNetherite() + { + return allowUpgradeToNetherite; + } + public boolean unbreakable() { return unbreakable;