From d4d8e307c5a547626a0073fbedf335a8933c81b5 Mon Sep 17 00:00:00 2001 From: Pim van der Loos Date: Mon, 1 Nov 2021 19:20:28 +0100 Subject: [PATCH] Use new durability in other classes --- .../armoredElytra/ArmoredElytra.java | 31 +++--- .../armoredElytra/DurabilityManager.java | 75 ++++++++++---- .../armoredElytra/handlers/AnvilHandler.java | 29 +++--- .../handlers/ArmoredElytraHandler.java | 42 +++----- .../handlers/CommandHandler.java | 21 ++-- .../armoredElytra/handlers/EventHandlers.java | 98 ++++++++----------- .../handlers/FlyDurabilityHandler.java | 34 +++++-- .../handlers/ItemDropListener.java | 16 +-- .../handlers/NetheriteUpgradeListener.java | 10 +- .../handlers/SmithingTableCraftHandler.java | 14 ++- .../handlers/SmithingTableListener.java | 31 +++--- .../armoredElytra/handlers/Uninstaller.java | 7 +- .../armoredElytra/nbtEditor/INBTEditor.java | 8 -- .../armoredElytra/util/ConfigLoader.java | 13 ++- .../nl/pim16aap2/armoredElytra/util/Util.java | 15 +++ 15 files changed, 247 insertions(+), 197 deletions(-) diff --git a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java index 8d3116c..0ef4d1b 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java @@ -50,6 +50,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener private UpdateManager updateManager; private INBTEditor nbtEditor; + private DurabilityManager durabilityManager; @Override public void onEnable() @@ -75,6 +76,9 @@ public class ArmoredElytra extends JavaPlugin implements Listener nbtEditor = new NBTEditor(); config = new ConfigLoader(this); + + durabilityManager = new DurabilityManager(nbtEditor, config); + messages = new Messages(this); readMessages(); @@ -94,29 +98,26 @@ public class ArmoredElytra extends JavaPlugin implements Listener "Stats disabled, not loading stats :(... Please consider enabling it! I am a simple man, " + "seeing higher user numbers helps me stay motivated!"); - Bukkit.getPluginManager().registerEvents(new EventHandlers(this), this); - getCommand("ArmoredElytra").setExecutor(new CommandHandler(this)); + Bukkit.getPluginManager().registerEvents(new EventHandlers(this, nbtEditor, durabilityManager), this); + getCommand("ArmoredElytra").setExecutor(new CommandHandler(this, nbtEditor, durabilityManager)); // Load the plugin normally if not in uninstall mode. if (!config.uninstallMode()) { - // Check if the user wants to disable durability penalty for flying with an armored elytra. - if (config.noFlightDurability()) - { - Bukkit.getPluginManager().registerEvents(new FlyDurabilityHandler(), this); - myLogger(Level.INFO, "Durability penalty for flying disabled!"); - } - else - myLogger(Level.INFO, "Durability penalty for flying enabled!"); + Bukkit.getPluginManager().registerEvents(new FlyDurabilityHandler(config.noFlightDurability(), + nbtEditor, durabilityManager), this); + final Listener creationListener = + config.craftingInSmithingTable() ? + new SmithingTableCraftHandler(this, nbtEditor, durabilityManager, config) : + new AnvilHandler(this, nbtEditor, durabilityManager, config); - final Listener creationListener = config.craftingInSmithingTable() ? - new SmithingTableCraftHandler(this) : new AnvilHandler(this); Bukkit.getPluginManager().registerEvents(creationListener, this); if (config.allowUpgradeToNetherite()) - Bukkit.getPluginManager().registerEvents(new NetheriteUpgradeListener(this), this); + Bukkit.getPluginManager() + .registerEvents(new NetheriteUpgradeListener(this, nbtEditor, durabilityManager, config), this); if (config.dropNetheriteAsChestplate()) - Bukkit.getPluginManager().registerEvents(new ItemDropListener(this), this); + Bukkit.getPluginManager().registerEvents(new ItemDropListener(nbtEditor), this); // Log all allowed enchantments. myLogger(Level.INFO, ("Allowed enchantments:")); @@ -126,7 +127,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener else { myLogger(Level.WARNING, "Plugin in uninstall mode!"); - Bukkit.getPluginManager().registerEvents(new Uninstaller(this), this); + Bukkit.getPluginManager().registerEvents(new Uninstaller(this, nbtEditor), this); } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/DurabilityManager.java b/src/main/java/nl/pim16aap2/armoredElytra/DurabilityManager.java index 604cc1c..710c091 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/DurabilityManager.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/DurabilityManager.java @@ -13,7 +13,7 @@ public class DurabilityManager { private static final int ELYTRA_MAX_DURABILITY = Material.ELYTRA.getMaxDurability(); - private final int[] repairSteps = new int[ArmorTier.values().length]; + private final int[] repairAmounts = new int[ArmorTier.values().length]; private final int[] maxDurabilities = new int[ArmorTier.values().length]; private final INBTEditor nbtEditor; @@ -26,6 +26,28 @@ public class DurabilityManager init(); } + /** + * Combination of {@link #getCombinedDurability(ItemStack, ItemStack, ArmorTier, ArmorTier)} and {@link + * #setDurability(ItemStack, int, ArmorTier)}. + *

+ * First gets the combined of the input armored elytra and the other item and then applies it to the target armored + * elytra. + * + * @param armoredElytraOut The output armored elytra item. This is the elytra that will be updated. + * @param armoredElytraIn The input armored elytra item. + * @param other The other item that will be combined with the armored elytra. This can be another armored + * elytra, a chestplate, or any other item. + * @param currentTier The current armor tier of the armored elytra. + * @param targetTier The target tier of the armored elytra. + */ + public int setCombinedDurability(ItemStack armoredElytraOut, ItemStack armoredElytraIn, ItemStack other, + ArmorTier currentTier, ArmorTier targetTier) + { + final int combinedDurability = getCombinedDurability(armoredElytraIn, other, currentTier, targetTier); + setDurability(armoredElytraOut, combinedDurability, targetTier); + return combinedDurability; + } + /** * Gets durability value resulting from combining an armored elytra with some other item with durability. * @@ -43,17 +65,36 @@ public class DurabilityManager final int currentMaxDurability = getMaxDurability(currentTier); final int targetMaxDurability = getMaxDurability(targetTier); - final int otherMaxDurability = otherTier == ArmorTier.NONE ? - other.getType().getMaxDurability() : getMaxDurability(otherTier); - + final int otherMaxDurability = otherTier != ArmorTier.NONE ? + getMaxDurability(otherTier) : other.getType().getMaxDurability(); + //noinspection deprecation final int otherDurability = other.getType().equals(Material.ELYTRA) ? - getRealDurability(other, null) : other.getType().getMaxDurability(); - + getRealDurability(other, null) : other.getDurability(); final int currentDurability = getRealDurability(armoredElytra, currentTier); - return targetMaxDurability - + final int combinedDurability = targetMaxDurability - (otherMaxDurability - otherDurability) - (currentMaxDurability - currentDurability); + + return Util.between(combinedDurability, 0, targetMaxDurability); + } + + /** + * Removes durability from an armored elytra. + * + * @param armoredElytra The armored elytra item to damage. + * @param durabilityLoss The amount of durability to remove from the armored elytra. + * @param providedTier The tier of the armored elytra (if this is available). If this is null, it will be + * retrieved from the item itself. + * @return The new durability after removing the provided amount. + */ + public int removeDurability(ItemStack armoredElytra, int durabilityLoss, @Nullable ArmorTier providedTier) + { + final ArmorTier currentTier = providedTier == null ? nbtEditor.getArmorTier(armoredElytra) : providedTier; + final int currentDurability = getRealDurability(armoredElytra, currentTier); + final int newDurability = Util.between(currentDurability + durabilityLoss, 0, getMaxDurability(currentTier)); + setDurability(armoredElytra, newDurability, providedTier); + return newDurability; } /** @@ -71,7 +112,7 @@ public class DurabilityManager { final ArmorTier currentTier = providedTier == null ? nbtEditor.getArmorTier(armoredElytra) : providedTier; final int repairableDurability = getMaxDurability(currentTier) - getRealDurability(armoredElytra, currentTier); - return (int) Math.ceil((float) repairableDurability / getRepairSteps(currentTier)); + return (int) Math.ceil((float) repairableDurability / getRepairAmount(currentTier)); } /** @@ -87,7 +128,7 @@ public class DurabilityManager public int getRepairedDurability(ItemStack armoredElytra, int repairCount, @Nullable ArmorTier providedTier) { final ArmorTier currentTier = providedTier == null ? nbtEditor.getArmorTier(armoredElytra) : providedTier; - final int restoredDurability = repairCount * getRepairSteps(currentTier); + final int restoredDurability = repairCount * getRepairAmount(currentTier); final int currentDurability = getRealDurability(armoredElytra, currentTier); return Math.max(0, currentDurability - restoredDurability); } @@ -125,8 +166,8 @@ public class DurabilityManager public void setDurability(ItemStack item, int durability, @Nullable ArmorTier providedTier) { final ArmorTier currentTier = providedTier == null ? nbtEditor.getArmorTier(item) : providedTier; - final int rawDurability = getRemappedDurability(durability, getMaxDurability(currentTier), - ELYTRA_MAX_DURABILITY); + final int oldMaxDurability = getMaxDurability(currentTier); + final int rawDurability = getRemappedDurability(durability, oldMaxDurability, ELYTRA_MAX_DURABILITY); nbtEditor.updateDurability(item, durability, rawDurability); } @@ -174,7 +215,7 @@ public class DurabilityManager * @param armorTier The armor tier for which to get the maximum durability. * @return The maximum durability of the given armor tier. */ - private int getMaxDurability(ArmorTier armorTier) + public int getMaxDurability(ArmorTier armorTier) { return maxDurabilities[armorTier.ordinal()]; } @@ -185,9 +226,9 @@ public class DurabilityManager * @param armorTier The armor tier. * @return The amount of durability restored per repair step for the given armor tier. */ - private int getRepairSteps(ArmorTier armorTier) + public int getRepairAmount(ArmorTier armorTier) { - return repairSteps[armorTier.ordinal()]; + return repairAmounts[armorTier.ordinal()]; } /** @@ -207,11 +248,11 @@ public class DurabilityManager } /** - * Initializes the {@link #maxDurabilities} and {@link #repairSteps} arrays. + * Initializes the {@link #maxDurabilities} and {@link #repairAmounts} arrays. */ private void init() { - repairSteps[0] = 0; + repairAmounts[0] = 0; maxDurabilities[0] = ELYTRA_MAX_DURABILITY; final ArmorTier[] armorTiers = ArmorTier.values(); @@ -223,7 +264,7 @@ public class DurabilityManager maxDurabilities[idx] = maxDurability; final int steps = Math.max(1, config.getFullRepairItemCount(armorTier)); - repairSteps[idx] = (int) Math.ceil((float) maxDurability / steps); + repairAmounts[idx] = (int) Math.ceil((float) maxDurability / steps); } } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/AnvilHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/AnvilHandler.java index 2312632..f26ff8b 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/AnvilHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/AnvilHandler.java @@ -27,21 +27,16 @@ import java.util.logging.Level; public class AnvilHandler extends ArmoredElytraHandler implements Listener { - private final ConfigLoader configLoader; - private final INBTEditor nbtEditor; - private final DurabilityManager durabilityManager; - - public AnvilHandler(final ArmoredElytra plugin, final boolean creationEnabled) + protected AnvilHandler(ArmoredElytra plugin, boolean creationEnabled, + INBTEditor nbtEditor, DurabilityManager durabilityManager, ConfigLoader config) { - super(plugin, creationEnabled); - configLoader = plugin.getConfigLoader(); - nbtEditor = plugin.getNbtEditor(); - durabilityManager = new DurabilityManager(nbtEditor, configLoader); + super(plugin, creationEnabled, nbtEditor, durabilityManager, config); } - public AnvilHandler(final ArmoredElytra plugin) + public AnvilHandler(ArmoredElytra plugin, INBTEditor nbtEditor, + DurabilityManager durabilityManager, ConfigLoader config) { - this(plugin, true); + super(plugin, true, nbtEditor, durabilityManager, config); } // Valid inputs: @@ -74,11 +69,11 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener { // If the armored elytra is to be enchanted using an enchanted book... if (matTwo == Material.ENCHANTED_BOOK) - return configLoader.allowAddingEnchantments() ? Action.ENCHANT : Action.BLOCK; + 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 itemOne.getDurability() == 0 ? Action.BLOCK : Action.REPAIR; + return durabilityManager.getRealDurability(itemOne, tier) == 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) @@ -120,7 +115,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener final ArmorTier curTier = nbtEditor.getArmorTier(itemA); int newDurability = 0; - EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemA, plugin); + final EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemA, plugin); switch (action) { @@ -168,7 +163,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener final String name = getElytraResultName(itemA, action, newTier, event.getInventory().getRenameText()); final Color color = getItemColor(itemA, itemB); - result = nbtEditor.addArmorNBTTags(result, newTier, configLoader.unbreakable(), name, color); + result = nbtEditor.addArmorNBTTags(result, newTier, config.unbreakable(), name, color); event.setResult(result); return; @@ -186,13 +181,13 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener final ArmorTier armorTier, final String renameText) { final String tierName = plugin.getArmoredElytraName(armorTier); - if (renameText == null || !configLoader.allowRenaming()) + if (renameText == null || !config.allowRenaming()) return tierName; final ItemMeta meta = baseItem.getItemMeta(); final String currentName = meta == null ? null : meta.getDisplayName(); - // When the rename text is empty, give it the default tier-name when creating a new armored elytra + // When the renameText is empty, give it the default tier-name when creating a new armored elytra // (so it's named properly) or when the current name is already the tier name (just returning the current // name would strip the tier's color in this case). if ((action == Action.CREATE && renameText.equals("")) || diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/ArmoredElytraHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/ArmoredElytraHandler.java index 73cb30e..d7d2717 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/ArmoredElytraHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/ArmoredElytraHandler.java @@ -1,9 +1,9 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; -import nl.pim16aap2.armoredElytra.util.ArmorTier; +import nl.pim16aap2.armoredElytra.DurabilityManager; +import nl.pim16aap2.armoredElytra.nbtEditor.INBTEditor; import nl.pim16aap2.armoredElytra.util.ConfigLoader; -import nl.pim16aap2.armoredElytra.util.XMaterial; import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.Material; @@ -24,38 +24,18 @@ abstract class ArmoredElytraHandler protected final ArmoredElytra plugin; protected final boolean creationEnabled; - private final ConfigLoader config; + protected final ConfigLoader config; + protected final INBTEditor nbtEditor; + protected final DurabilityManager durabilityManager; - public ArmoredElytraHandler(final ArmoredElytra plugin, final boolean creationEnabled) + protected ArmoredElytraHandler(ArmoredElytra plugin, boolean creationEnabled, INBTEditor nbtEditor, + DurabilityManager durabilityManager, ConfigLoader config) { this.plugin = plugin; this.creationEnabled = creationEnabled; - config = plugin.getConfigLoader(); - } - - // Repair an Armored Elytra - protected short repairItem(short curDur, ItemStack repairItem) - { - final ArmorTier repairTier; - if (repairItem.getType().equals(Material.LEATHER)) - repairTier = ArmorTier.LEATHER; - else if (repairItem.getType().equals(Material.GOLD_INGOT)) - repairTier = ArmorTier.GOLD; - else if (repairItem.getType().equals(Material.IRON_INGOT)) - repairTier = ArmorTier.IRON; - else if (repairItem.getType().equals(Material.DIAMOND)) - repairTier = ArmorTier.DIAMOND; - else if (repairItem.getType().equals(XMaterial.NETHERITE_INGOT.parseMaterial())) - repairTier = ArmorTier.NETHERITE; - else - repairTier = ArmorTier.NONE; - - final int repairCount = Math.max(1, config.getFullRepairItemCount(repairTier)); - final double repairPercentage = 1f / repairCount; - - int maxDurability = Material.ELYTRA.getMaxDurability(); - int newDurability = (int) (curDur - repairItem.getAmount() * (maxDurability * repairPercentage)); - return (short) (Math.max(newDurability, 0)); + this.nbtEditor = nbtEditor; + this.durabilityManager = durabilityManager; + this.config = config; } /** @@ -83,7 +63,7 @@ abstract class ArmoredElytraHandler return null; if (itemStack.getType() == Material.ELYTRA) - return ArmoredElytra.getInstance().getNbtEditor().getColorOfArmoredElytra(itemStack); + return nbtEditor.getColorOfArmoredElytra(itemStack); if (!itemStack.hasItemMeta() || !(itemStack.getItemMeta() instanceof LeatherArmorMeta)) return null; diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java index e18b1ce..1bf165e 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java @@ -1,6 +1,8 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.DurabilityManager; +import nl.pim16aap2.armoredElytra.nbtEditor.INBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.messages.Message; import org.bukkit.Bukkit; @@ -21,11 +23,15 @@ import java.util.logging.Level; public class CommandHandler implements CommandExecutor { private final ArmoredElytra plugin; + private final INBTEditor nbtEditor; + private final DurabilityManager durabilityManager; private static Field BY_KEY_FIELD; - public CommandHandler(ArmoredElytra plugin) + public CommandHandler(ArmoredElytra plugin, INBTEditor nbtEditor, DurabilityManager durabilityManager) { this.plugin = plugin; + this.nbtEditor = nbtEditor; + this.durabilityManager = durabilityManager; } @Override @@ -80,9 +86,9 @@ public class CommandHandler implements CommandExecutor if (allowed) { plugin.elytraReceivedMessage(receiver, armorTier); - newElytra = ArmoredElytra.getInstance().getNbtEditor() - .addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, - plugin.getConfigLoader().unbreakable()); + newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, + plugin.getConfigLoader().unbreakable()); + durabilityManager.setDurability(newElytra, 0, armorTier); plugin.giveArmoredElytraToPlayer(receiver, newElytra); } else @@ -119,9 +125,10 @@ public class CommandHandler implements CommandExecutor return false; plugin.elytraReceivedMessage(player, armorTier); - newElytra = ArmoredElytra.getInstance().getNbtEditor() - .addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, - plugin.getConfigLoader().unbreakable()); + newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, + plugin.getConfigLoader().unbreakable()); + durabilityManager.setDurability(newElytra, 0, armorTier); + plugin.giveArmoredElytraToPlayer(player, newElytra); plugin.myLogger(Level.INFO, ("Giving an armored elytra of the " + ArmorTier.getArmor(armorTier) + " armor tier to player " + player.getName())); diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java index ae4fd51..1340949 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java @@ -1,10 +1,12 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.DurabilityManager; 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.INBTEditor; import nl.pim16aap2.armoredElytra.util.AllowedToWearEnum; import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.Util; @@ -14,6 +16,7 @@ import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; @@ -24,12 +27,16 @@ import java.util.Random; public class EventHandlers implements Listener { - private final ArmoredElytra plugin; private final Random random = new Random(); + private final ArmoredElytra plugin; + private final INBTEditor nbtEditor; + private final DurabilityManager durabilityManager; - public EventHandlers(ArmoredElytra plugin) + public EventHandlers(ArmoredElytra plugin, INBTEditor nbtEditor, DurabilityManager durabilityManager) { this.plugin = plugin; + this.nbtEditor = nbtEditor; + this.durabilityManager = durabilityManager; initializeArmorEquipEvent(); } @@ -39,13 +46,6 @@ public class EventHandlers implements Listener Bukkit.getPluginManager().registerEvents(new DispenserArmorListener(), plugin); } - private void moveChestplateToInventory(Player player) - { - player.getInventory().addItem(player.getInventory().getChestplate()); - player.getInventory().getChestplate().setAmount(0); - player.updateInventory(); - } - // Make sure the player has the correct permission and that the item is not // broken. private AllowedToWearEnum isAllowedToWear(ItemStack elytra, Player player, ArmorTier armorTier) @@ -60,62 +60,44 @@ public class EventHandlers implements Listener } // Handle armored elytra durability loss. - @EventHandler(ignoreCancelled = true) + @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) public void onPlayerDamage(EntityDamageEvent e) { if (!(e.getEntity() instanceof Player)) return; + final Player p = (Player) e.getEntity(); - if (plugin.getConfigLoader().unbreakable()) + final ItemStack elytra = p.getInventory().getChestplate(); + if (elytra == null) return; - Player p = (Player) e.getEntity(); - // If the player didn't die from the damage. - if ((p.getHealth() - e.getFinalDamage()) > 0) + final ArmorTier armorTier = nbtEditor.getArmorTier(elytra); + if (armorTier == ArmorTier.NONE) + return; + + final DamageCause cause = e.getCause(); + // The elytra doesn't receive any damage for these causes: + if (cause == DamageCause.DROWNING || cause == DamageCause.STARVATION || cause == DamageCause.SUFFOCATION || + cause == DamageCause.SUICIDE || cause == DamageCause.FLY_INTO_WALL || cause == DamageCause.POISON) + return; + + final boolean removeDurability; + if (elytra.containsEnchantment(Enchantment.DURABILITY)) { - if (p.getInventory().getChestplate() == null) - return; - - if (ArmoredElytra.getInstance().getNbtEditor().getArmorTier(p.getInventory().getChestplate()) == - ArmorTier.NONE) - return; - - ItemStack elytra = p.getInventory().getChestplate(); - DamageCause cause = e.getCause(); - - // The elytra doesn't receive any damage for these causes: - if (cause != DamageCause.DROWNING && cause != DamageCause.STARVATION && cause != DamageCause.SUFFOCATION && - cause != DamageCause.SUICIDE && cause != DamageCause.FLY_INTO_WALL && cause != DamageCause.POISON) - { - int durability = p.getInventory().getChestplate().getDurability(); - int maxDurability = p.getInventory().getChestplate().getType().getMaxDurability(); - int newDurability = durability + ((int) (e.getDamage() / 4) > 1 ? (int) (e.getDamage() / 4) : 1); - - // If the elytra has the durability enchantment, we calculate the durability - // loss ourselves. - if (p.getInventory().getChestplate().containsEnchantment(Enchantment.DURABILITY)) - { - // Get a random int between 0 and 100 to use in deciding if the durability - // enchantment will take effect. - int randomInt = random.nextInt(101); - int enchantLevel = p.getInventory().getChestplate().getEnchantmentLevel(Enchantment.DURABILITY); - int durabilityDelta = (100 / (enchantLevel + 1)) < randomInt ? 0 : 1; - // If the durability equals/exceeds maxDurability, it's broken (0 = full item - // durability). - if (durability >= maxDurability) - moveChestplateToInventory(p); - else - newDurability = durability + durabilityDelta; - } - // If the item should be broken, make sure it really is broken and unequip it. - if (newDurability >= maxDurability) - { - newDurability = maxDurability; - moveChestplateToInventory(p); - } - elytra.setDurability((short) (newDurability)); - } + final int randomInt = random.nextInt(101); + final int enchantLevel = elytra.getEnchantmentLevel(Enchantment.DURABILITY); + // Formula taken from: https://minecraft.fandom.com/wiki/Unbreaking#Usage + final float removeDurabilityChance = 60 + 40f / (enchantLevel + 1); + removeDurability = randomInt <= removeDurabilityChance; } + else + removeDurability = true; + + // Even when we don't subtract durability, we still want to update the durability, so just subtract 0. + final int durabilityLoss = removeDurability ? (int) Math.max(1, e.getDamage() / 4) : 0; + final int newDurability = durabilityManager.removeDurability(elytra, durabilityLoss, armorTier); + if (newDurability >= durabilityManager.getMaxDurability(armorTier)) + Util.moveChestplateToInventory(p); } @EventHandler @@ -130,8 +112,8 @@ public class EventHandlers implements Listener !e.getNewArmorPiece().getType().equals(Material.ELYTRA)) return; - ArmorTier armorTier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(e.getNewArmorPiece()); - AllowedToWearEnum allowed = isAllowedToWear(e.getNewArmorPiece(), e.getPlayer(), armorTier); + final ArmorTier armorTier = nbtEditor.getArmorTier(e.getNewArmorPiece()); + final AllowedToWearEnum allowed = isAllowedToWear(e.getNewArmorPiece(), e.getPlayer(), armorTier); switch (allowed) { case ALLOWED: diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java index 79fe0f8..250fbd0 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java @@ -1,21 +1,30 @@ package nl.pim16aap2.armoredElytra.handlers; -import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.DurabilityManager; +import nl.pim16aap2.armoredElytra.nbtEditor.INBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; +import nl.pim16aap2.armoredElytra.util.Util; import org.bukkit.Material; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerItemDamageEvent; public class FlyDurabilityHandler implements Listener { - public FlyDurabilityHandler() + private final boolean disableDurability; + private final INBTEditor nbtEditor; + private final DurabilityManager durabilityManager; + + public FlyDurabilityHandler(boolean disableDurability, INBTEditor nbtEditor, DurabilityManager durabilityManager) { + this.disableDurability = disableDurability; + this.nbtEditor = nbtEditor; + this.durabilityManager = durabilityManager; } - // Do not decrease elytra durability while flying. This also cancels durability decrease when - // it should (i.e. getting hit) while flying, but I don't really care. - @EventHandler + // Do not decrease elytra durability while flying. + @EventHandler(priority = EventPriority.LOWEST) public void onItemDamage(PlayerItemDamageEvent e) { if (e.getItem().getType() != Material.ELYTRA) @@ -24,7 +33,18 @@ public class FlyDurabilityHandler implements Listener if (!e.getPlayer().isGliding()) return; - if (ArmoredElytra.getInstance().getNbtEditor().getArmorTier(e.getItem()) != ArmorTier.NONE) - e.setCancelled(true); + final ArmorTier armorTier = nbtEditor.getArmorTier(e.getItem()); + if (armorTier == ArmorTier.NONE) + return; + + // This also cancels durability decrease when it should (i.e. getting hit) while flying, + // but that is likely to be rare enough for it to not matter. + e.setCancelled(true); + if (disableDurability) + return; + + final int newDurability = durabilityManager.removeDurability(e.getItem(), e.getDamage(), armorTier); + if (newDurability >= durabilityManager.getMaxDurability(armorTier)) + Util.moveChestplateToInventory(e.getPlayer()); } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/ItemDropListener.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/ItemDropListener.java index 617a7d2..acb0be4 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/ItemDropListener.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/ItemDropListener.java @@ -1,6 +1,6 @@ package nl.pim16aap2.armoredElytra.handlers; -import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.nbtEditor.INBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; import org.bukkit.Material; import org.bukkit.event.EventHandler; @@ -13,11 +13,11 @@ import org.bukkit.inventory.ItemStack; public class ItemDropListener implements Listener { - protected final ArmoredElytra plugin; + private final INBTEditor nbtEditor; - public ItemDropListener(final ArmoredElytra plugin) + public ItemDropListener(INBTEditor nbtEditor) { - this.plugin = plugin; + this.nbtEditor = nbtEditor; } /** @@ -32,10 +32,10 @@ public class ItemDropListener implements Listener private ItemStack getNewDrop(final ItemStack itemStack) { if (itemStack == null || itemStack.getType() != Material.ELYTRA || - plugin.getNbtEditor().getArmorTier(itemStack) != ArmorTier.NETHERITE) + nbtEditor.getArmorTier(itemStack) != ArmorTier.NETHERITE) return null; - ItemStack newDrop = new ItemStack(Material.NETHERITE_CHESTPLATE, 1); + final ItemStack newDrop = new ItemStack(Material.NETHERITE_CHESTPLATE, 1); newDrop.setItemMeta(itemStack.getItemMeta()); return newDrop; @@ -53,10 +53,10 @@ public class ItemDropListener implements Listener private ItemStack getNewPickup(final ItemStack itemStack) { if (itemStack == null || itemStack.getType() != Material.NETHERITE_CHESTPLATE || - plugin.getNbtEditor().getArmorTier(itemStack) != ArmorTier.NETHERITE) + nbtEditor.getArmorTier(itemStack) != ArmorTier.NETHERITE) return null; - ItemStack newDrop = new ItemStack(Material.ELYTRA, 1); + final ItemStack newDrop = new ItemStack(Material.ELYTRA, 1); newDrop.setItemMeta(itemStack.getItemMeta()); return newDrop; diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/NetheriteUpgradeListener.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/NetheriteUpgradeListener.java index 0c011f4..bfbd6b7 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/NetheriteUpgradeListener.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/NetheriteUpgradeListener.java @@ -1,7 +1,10 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.DurabilityManager; +import nl.pim16aap2.armoredElytra.nbtEditor.INBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; +import nl.pim16aap2.armoredElytra.util.ConfigLoader; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -12,12 +15,13 @@ import org.bukkit.inventory.SmithingInventory; public class NetheriteUpgradeListener extends SmithingTableListener { - public NetheriteUpgradeListener(final ArmoredElytra plugin) + public NetheriteUpgradeListener(final ArmoredElytra plugin, INBTEditor nbtEditor, + DurabilityManager durabilityManager, ConfigLoader config) { - super(plugin); + super(plugin, false, nbtEditor, durabilityManager, config); } - @EventHandler(ignoreCancelled = true) + @Override @EventHandler(ignoreCancelled = true) public void onSmithingTableUsage(final PrepareSmithingEvent event) { super.onSmithingTableUsage(event); diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableCraftHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableCraftHandler.java index 46153cb..ec470ea 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableCraftHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableCraftHandler.java @@ -1,7 +1,10 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.DurabilityManager; +import nl.pim16aap2.armoredElytra.nbtEditor.INBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; +import nl.pim16aap2.armoredElytra.util.ConfigLoader; import nl.pim16aap2.armoredElytra.util.Util; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -14,13 +17,16 @@ import org.bukkit.inventory.SmithingInventory; public class SmithingTableCraftHandler extends SmithingTableListener { - public SmithingTableCraftHandler(final ArmoredElytra plugin) + public SmithingTableCraftHandler(final ArmoredElytra plugin, INBTEditor nbtEditor, + DurabilityManager durabilityManager, ConfigLoader config) { - super(plugin, true); + super(plugin, true, nbtEditor, durabilityManager, config); // Register the anvil handler with creation disabled so AEs can still be repaired and stuff. - Bukkit.getPluginManager().registerEvents(new AnvilHandler(plugin, false), plugin); + Bukkit.getPluginManager() + .registerEvents(new AnvilHandler(plugin, false, nbtEditor, durabilityManager, config), plugin); } + @Override @EventHandler(ignoreCancelled = true) public void onSmithingTableUsage(final PrepareSmithingEvent event) { @@ -42,7 +48,7 @@ public class SmithingTableCraftHandler extends SmithingTableListener { if (!isAESmithingTableEvent(e)) return; - SmithingInventory smithingInventory = (SmithingInventory) e.getInventory(); + final SmithingInventory smithingInventory = (SmithingInventory) e.getInventory(); final ItemStack result = smithingInventory.getItem(2); // This cast may look unchecked, but it was checked by isSmithingTableEvent already. diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableListener.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableListener.java index c205b58..dabd73b 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableListener.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/SmithingTableListener.java @@ -1,7 +1,10 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.DurabilityManager; +import nl.pim16aap2.armoredElytra.nbtEditor.INBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; +import nl.pim16aap2.armoredElytra.util.ConfigLoader; import nl.pim16aap2.armoredElytra.util.EnchantmentContainer; import org.bukkit.Color; import org.bukkit.Material; @@ -17,15 +20,10 @@ import java.util.logging.Level; abstract class SmithingTableListener extends ArmoredElytraHandler implements Listener { - protected SmithingTableListener(ArmoredElytra plugin, boolean creationEnabled) + protected SmithingTableListener(ArmoredElytra plugin, boolean creationEnabled, + INBTEditor nbtEditor, DurabilityManager durabilityManager, ConfigLoader config) { - super(plugin, creationEnabled); - - } - - protected SmithingTableListener(ArmoredElytra plugin) - { - this(plugin, false); + super(plugin, creationEnabled, nbtEditor, durabilityManager, config); } public void onSmithingTableUsage(final PrepareSmithingEvent event) @@ -42,17 +40,17 @@ abstract class SmithingTableListener extends ArmoredElytraHandler implements Lis final Player player = (Player) event.getView().getPlayer(); - final ItemStack result; if (plugin.playerHasCraftPerm(player, newTier)) { - - EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemStackA, plugin); + final EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemStackA, plugin); enchantments.merge(EnchantmentContainer.getEnchantments(itemStackB, plugin)); final Color color = getItemColor(itemStackA, itemStackB); - result = ArmoredElytra.getInstance().getNbtEditor() - .addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), newTier, - plugin.getConfigLoader().unbreakable(), color); + 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); } @@ -82,7 +80,7 @@ abstract class SmithingTableListener extends ArmoredElytraHandler implements Lis return false; // Check if the event was a player who interacted with a smithing table. - Player player = (Player) event.getWhoClicked(); + final Player player = (Player) event.getWhoClicked(); if (event.getView().getType() != InventoryType.SMITHING) return false; @@ -110,9 +108,8 @@ abstract class SmithingTableListener extends ArmoredElytraHandler implements Lis final ItemStack result = smithingInventory.getItem(2); if (result == null || result.getType() != Material.ELYTRA || - ArmoredElytra.getInstance().getNbtEditor().getArmorTier(result) == ArmorTier.NONE) + nbtEditor.getArmorTier(result) == ArmorTier.NONE) return false; - return true; } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/Uninstaller.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/Uninstaller.java index b745f58..fadf2d9 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/Uninstaller.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/Uninstaller.java @@ -1,6 +1,7 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.nbtEditor.INBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -17,10 +18,12 @@ import org.bukkit.scheduler.BukkitRunnable; public class Uninstaller implements Listener { private final ArmoredElytra plugin; + private final INBTEditor nbtEditor; - public Uninstaller(ArmoredElytra plugin) + public Uninstaller(ArmoredElytra plugin, INBTEditor nbtEditor) { this.plugin = plugin; + this.nbtEditor = nbtEditor; } public int removeArmoredElytras(Inventory inv) @@ -28,7 +31,7 @@ public class Uninstaller implements Listener int count = 0; for (ItemStack is : inv) if (is != null && is.getType() == Material.ELYTRA && - ArmoredElytra.getInstance().getNbtEditor().getArmorTier(is) != ArmorTier.NONE) + nbtEditor.getArmorTier(is) != ArmorTier.NONE) { inv.remove(is); ++count; diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/INBTEditor.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/INBTEditor.java index 6c1449b..0d436df 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/INBTEditor.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/INBTEditor.java @@ -130,12 +130,4 @@ public interface INBTEditor * @return The real durability of the itemstack if the itemstack has the AE durability attribute, or -1 otherwise. */ int getRealDurability(ItemStack itemStack, @Nullable ArmorTier armorTier); - - /** - * See {@link #getRealDurability(ItemStack, ArmorTier)}. - */ - default int getRealDurability(ItemStack itemStack) - { - return getRealDurability(itemStack, null); - } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java b/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java index 6c0ab2e..025e837 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 boolean uninstallMode; private boolean checkForUpdates; private boolean noFlightDurability; + private boolean useTierDurability; private boolean dropNetheriteAsChestplate; private LinkedHashSet allowedEnchantments; private boolean allowMultipleProtectionEnchantments; @@ -70,6 +71,12 @@ public class ConfigLoader "Setting this to true will cause armored elytras to not lose any durability while flying.", "This is not a permanent option and will affect ALL elytras." }; + String[] useTierDurabilityComment = + { + "Use the maximum durability of the armor tier of armored elytras.", + "For example, when this is true, a diamond armored elytra would have a durability of 528.", + "When this is false, all armored elytras have the maximum durability of a regular elytra." + }; String[] repairComment = { "Amount of items it takes to fully repair an armored elytra", @@ -156,7 +163,6 @@ public class ConfigLoader "When true, only enchantments from the allowed list can be added." }; - // Set default list of allowed enchantments. List defaultAllowedEnchantments = new ArrayList<>( Arrays.asList("minecraft:unbreaking", "minecraft:fire_protection", "minecraft:blast_protection", @@ -166,8 +172,10 @@ public class ConfigLoader FileConfiguration config = plugin.getConfig(); + unbreakable = addNewConfigOption(config, "unbreakable", false, unbreakableComment); noFlightDurability = addNewConfigOption(config, "noFlightDurability", false, flyDurabilityComment); + useTierDurability = addNewConfigOption(config, "useTierDurability", true, useTierDurabilityComment); final ArmorTier[] armorTiers = ArmorTier.values(); for (int idx = 1; idx < armorTiers.length; ++idx) @@ -384,7 +392,6 @@ public class ConfigLoader public boolean useTierDurability() { - // TODO: Implement this option. - return true; + return useTierDurability; } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java b/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java index 8e15057..c8667ee 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java @@ -2,8 +2,11 @@ package nl.pim16aap2.armoredElytra.util; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import javax.annotation.Nullable; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Locale; @@ -138,6 +141,18 @@ public class Util return ret; } + public static void moveChestplateToInventory(Player player) + { + final PlayerInventory inventory = player.getInventory(); + inventory.addItem(inventory.getChestplate()); + + final @Nullable ItemStack chestplate = inventory.getChestplate(); + if (chestplate != null) + chestplate.setAmount(0); + + player.updateInventory(); + } + /** * Ensures that a given value does not exceed the provided upper and lower bounds. *