diff --git a/src/main/java/nl/pim16aap2/armoredElytra/DurabilityManager.java b/src/main/java/nl/pim16aap2/armoredElytra/DurabilityManager.java new file mode 100644 index 0000000..604cc1c --- /dev/null +++ b/src/main/java/nl/pim16aap2/armoredElytra/DurabilityManager.java @@ -0,0 +1,229 @@ +package nl.pim16aap2.armoredElytra; + +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.Material; +import org.bukkit.inventory.ItemStack; + +import javax.annotation.Nullable; + +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[] maxDurabilities = new int[ArmorTier.values().length]; + + private final INBTEditor nbtEditor; + private final ConfigLoader config; + + public DurabilityManager(INBTEditor nbtEditor, ConfigLoader config) + { + this.nbtEditor = nbtEditor; + this.config = config; + init(); + } + + /** + * Gets durability value resulting from combining an armored elytra with some other item with durability. + * + * @param armoredElytra The 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. + * @return The new real durability value of the armored elytra if it were to be combined with the other item. + */ + public int getCombinedDurability(ItemStack armoredElytra, ItemStack other, + ArmorTier currentTier, ArmorTier targetTier) + { + final ArmorTier otherTier = nbtEditor.getArmorTier(other); + + final int currentMaxDurability = getMaxDurability(currentTier); + final int targetMaxDurability = getMaxDurability(targetTier); + final int otherMaxDurability = otherTier == ArmorTier.NONE ? + other.getType().getMaxDurability() : getMaxDurability(otherTier); + + final int otherDurability = other.getType().equals(Material.ELYTRA) ? + getRealDurability(other, null) : other.getType().getMaxDurability(); + + final int currentDurability = getRealDurability(armoredElytra, currentTier); + + return targetMaxDurability - + (otherMaxDurability - otherDurability) - + (currentMaxDurability - currentDurability); + } + + /** + * Gets the required number of repair items required to fully repair an armored elytra. + *

+ * For example, for an ArmoredElytra that is damaged for 50 durability and its repair item restores 40 durability, + * this method would return 2. + * + * @param armoredElytra The armored elytra item for which to check how many items are needed to fully repair it. + * @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 required number of repair items required to fully repair the armored elytra. + */ + public int getFullRepairItemCount(ItemStack armoredElytra, @Nullable ArmorTier providedTier) + { + 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)); + } + + /** + * Gets the new durability of an armored elytra if it were to be repaired right now. + * + * @param armoredElytra The armored elytra item for which to check what the new durability would be after repairing + * it. + * @param repairCount The number of repair items. + * @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 real durability value of the armored elytra if it were to be repaired. + */ + 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 currentDurability = getRealDurability(armoredElytra, currentTier); + return Math.max(0, currentDurability - restoredDurability); + } + + /** + * Gets the real durability of an item. + *

+ * If the item is an armored elytra, and it does not have a real durability yet, it will be upgraded. + * + * @param item The item for which to figure out the real durability. + * @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 real durability of the item. + */ + public int getRealDurability(ItemStack item, @Nullable ArmorTier providedTier) + { + final ArmorTier currentTier = providedTier == null ? nbtEditor.getArmorTier(item) : providedTier; + + if (currentTier == ArmorTier.NONE) + //noinspection deprecation + return item.getDurability(); + + final int realDurability = nbtEditor.getRealDurability(item, currentTier); + return realDurability == -1 ? upgradeArmoredElytraToDurability(item, currentTier) : realDurability; + } + + /** + * Sets the durability values (real + shown) of an armored elytra. + * + * @param item The armored elytra item for which to set the durability values. + * @param durability The real durability value. + * @param providedTier The tier of the armored elytra (if this is available). If this is null, it will be retrieved + * from the item itself. + */ + 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); + nbtEditor.updateDurability(item, durability, rawDurability); + } + + /** + * Sets the real durability NBT data for armored elytras that do not have it. + *

+ * The real durability is calculated from the current 'raw' durability. The real durability will be the same + * percentage of the max durability for the type as the raw durability is of an elytra's maximum durability. + * + * @param armoredElytra The armored elytra to upgrade to an armored elytra with durability. + * @param currentTier The current tier of the armored elytra. + * @return The real durability of the armored elytra. + */ + private int upgradeArmoredElytraToDurability(ItemStack armoredElytra, ArmorTier currentTier) + { + final int maxDurability = getMaxDurability(currentTier); + //noinspection deprecation + final int rawDurability = armoredElytra.getDurability(); + + final int realDurability = maxDurability == ELYTRA_MAX_DURABILITY ? + rawDurability : + getRemappedDurability(rawDurability, ELYTRA_MAX_DURABILITY, maxDurability); + + nbtEditor.updateDurability(armoredElytra, realDurability, rawDurability); + return realDurability; + } + + /** + * Gets the maximum durability for an armor tier. This may or may not be {@link + * ArmorTier#getMaxDurability(ArmorTier)} depending on {@link ConfigLoader#useTierDurability()}. + * + * @param armorTier The armor tier for which to figure out the maximum durability. + * @return The maximum durability of the armor tier. + */ + private int calculateMaxDurability(ArmorTier armorTier) + { + if (armorTier == ArmorTier.NONE || !config.useTierDurability()) + return ELYTRA_MAX_DURABILITY; + return ArmorTier.getMaxDurability(armorTier); + } + + /** + * Gets the maximum durability for a given armor tier. + * + * @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) + { + return maxDurabilities[armorTier.ordinal()]; + } + + /** + * Gets the amount of durability restored per repair step for a given armor tier. + * + * @param armorTier The armor tier. + * @return The amount of durability restored per repair step for the given armor tier. + */ + private int getRepairSteps(ArmorTier armorTier) + { + return repairSteps[armorTier.ordinal()]; + } + + /** + * Remaps a durability value from an old maximum value to a new maximum while maintaining the same durability + * percentage. + * + * @param durability The current durability value. + * @param oldMax The old maximum durability. + * @param newMax The new maximum durability. + * @return The new durability value after remapping it to the new maximum. The value cannot be less than 0 or more + * than newMax. + */ + private int getRemappedDurability(int durability, int oldMax, int newMax) + { + final float relativeDurability = (float) durability / oldMax; + return Util.between((int) Math.ceil(relativeDurability * newMax), 0, newMax); + } + + /** + * Initializes the {@link #maxDurabilities} and {@link #repairSteps} arrays. + */ + private void init() + { + repairSteps[0] = 0; + maxDurabilities[0] = ELYTRA_MAX_DURABILITY; + + final ArmorTier[] armorTiers = ArmorTier.values(); + for (int idx = 1; idx < armorTiers.length; ++idx) + { + final ArmorTier armorTier = armorTiers[idx]; + + final int maxDurability = calculateMaxDurability(armorTier); + maxDurabilities[idx] = maxDurability; + + final int steps = Math.max(1, config.getFullRepairItemCount(armorTier)); + repairSteps[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 41f8351..2312632 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/AnvilHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/AnvilHandler.java @@ -1,6 +1,7 @@ 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.Action; import nl.pim16aap2.armoredElytra.util.ArmorTier; @@ -28,12 +29,14 @@ 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) { super(plugin, creationEnabled); configLoader = plugin.getConfigLoader(); nbtEditor = plugin.getNbtEditor(); + durabilityManager = new DurabilityManager(nbtEditor, configLoader); } public AnvilHandler(final ArmoredElytra plugin) @@ -46,7 +49,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener // - Elytra (armored) + enchanted book -> Enchant // - Elytra (armored) + its repair item -> Repair // - Elytra (armored) + other elytra (armored) -> Combine (Enchant + Repair) - // ! Elytra (armored, !leather) + leather/membrane -> Block + // - Elytra (armored, !leather) + leather/membrane -> Block // // Ignoring: // - Elytra (not armored) + !chestplate -> None @@ -56,14 +59,6 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener if (itemOne == null || itemTwo == null) return Action.NONE; - // If itemTwo is the elytra, while itemOne isn't, switch itemOne and itemTwo. - if (itemTwo.getType() == Material.ELYTRA && itemOne.getType() != Material.ELYTRA) - { - ItemStack tmp = itemOne; - itemOne = itemTwo; - itemTwo = tmp; - } - if (itemOne.getType() != Material.ELYTRA) return Action.NONE; @@ -83,10 +78,9 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener // If the armored elytra is to be repaired using its repair item... if (ArmorTier.getRepairItem(tier) == matTwo) - return itemOne.getDurability() == 0 ? Action.NONE : Action.REPAIR; + return itemOne.getDurability() == 0 ? Action.BLOCK : Action.REPAIR; - // If the armored elytra is to be combined with another armored elytra of the - // same tier... + // If the armored elytra is to be combined with another armored elytra of the same tier... if (nbtEditor.getArmorTier(itemTwo) == tier) return creationEnabled ? Action.COMBINE : Action.NONE; @@ -101,13 +95,13 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener } // Handle all anvil related stuff for this plugin. - @EventHandler(priority = EventPriority.HIGHEST) + @EventHandler(priority = EventPriority.LOWEST) private void onAnvilInventoryOpen(PrepareAnvilEvent event) { Player player = (Player) event.getView().getPlayer(); ItemStack itemA = event.getInventory().getItem(0); ItemStack itemB = event.getInventory().getItem(1); - ItemStack result = null; + ItemStack result; if (itemA != null && itemB != null) // If itemB is the (armored) elytra, while itemA isn't, switch itemA and itemB. @@ -121,37 +115,36 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener // Check if there are items in both input slots. if (itemA != null && itemB != null) { - Action action = isValidInput(itemA, itemB); + final Action action = isValidInput(itemA, itemB); ArmorTier newTier = ArmorTier.NONE; - ArmorTier curTier = nbtEditor.getArmorTier(itemA); - short durability = 0; + final ArmorTier curTier = nbtEditor.getArmorTier(itemA); + + int newDurability = 0; EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemA, plugin); switch (action) { case REPAIR: newTier = curTier; - durability = repairItem(itemA.getDurability(), itemB); + newDurability = durabilityManager.getRepairedDurability(itemA, itemB.getAmount(), curTier); break; case COMBINE: newTier = curTier; - durability = (short) (-itemA.getType().getMaxDurability() - itemA.getDurability() - - itemB.getDurability()); - durability = durability < 0 ? 0 : durability; + newDurability = durabilityManager.getCombinedDurability(itemA, itemB, curTier, newTier); enchantments.merge(EnchantmentContainer.getEnchantments(itemB, plugin)); break; case CREATE: newTier = Util.armorToTier(itemB.getType()); - durability = 0; + newDurability = durabilityManager.getCombinedDurability(itemA, itemB, curTier, newTier); enchantments.merge(EnchantmentContainer.getEnchantments(itemB, plugin)); break; case ENCHANT: newTier = curTier; - durability = itemA.getDurability(); + newDurability = durabilityManager.getRealDurability(itemA, newTier); // If there aren't any illegal enchantments on the book, continue as normal. // Otherwise... Block. - EnchantmentContainer enchantmentsB = EnchantmentContainer.getEnchantments(itemB, plugin); + final EnchantmentContainer enchantmentsB = EnchantmentContainer.getEnchantments(itemB, plugin); if (enchantmentsB.getEnchantmentCount() > 0) { enchantments.merge(enchantmentsB); @@ -170,7 +163,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener { result = new ItemStack(Material.ELYTRA, 1); enchantments.applyEnchantments(result); - result.setDurability(durability); + durabilityManager.setDurability(result, newDurability, newTier); final String name = getElytraResultName(itemA, action, newTier, event.getInventory().getRenameText()); final Color color = getItemColor(itemA, itemB); @@ -183,7 +176,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener } // If one of the input items is null and the other an armored elytra, remove the result. - // This prevent some naming issues. + // This prevents some naming issues. if ((itemA == null ^ itemB == null) && nbtEditor.getArmorTier(itemA == null ? itemB : itemA) != ArmorTier.NONE) event.setResult(null); diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/INBTEditor.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/INBTEditor.java index 2731678..6c1449b 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/INBTEditor.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/INBTEditor.java @@ -4,6 +4,7 @@ import nl.pim16aap2.armoredElytra.ArmoredElytra; import nl.pim16aap2.armoredElytra.util.ArmorTier; import org.bukkit.Color; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; import javax.annotation.Nullable; import java.util.List; @@ -99,7 +100,7 @@ public interface INBTEditor * @param item The item to check. * @return The {@link ArmorTier} that is on the item. If none is found, {@link ArmorTier#NONE} is returned. */ - ArmorTier getArmorTier(ItemStack item); + ArmorTier getArmorTier(@Nullable ItemStack item); /** * Gets the Color of an armored elytra. @@ -107,7 +108,34 @@ public interface INBTEditor * If the provided {@link ItemStack} is not an AE, null is returned. * * @param item The armored elytra to check. - * @return The color of the armored elytra, if the input is a color armored elytra, otherwise null. + * @return The color of the armored elytra, if the input is a colored armored elytra, otherwise null. */ - Color getColorOfArmoredElytra(ItemStack item); + Color getColorOfArmoredElytra(@Nullable ItemStack item); + + /** + * Updates the durability values of an item. + * + * @param itemStack The itemstack to which the durability values will be applied. + * @param realDurability The real durability to store in NBT. + * @param displayDurability The durability value to display on the item. This is the durability value the client can + * actually see.This only works if the item's meta is an instance of {@link Damageable}. + */ + void updateDurability(ItemStack itemStack, int realDurability, int displayDurability); + + /** + * Gets the real durability value as stored in the NBT of an armored elytra. + * + * @param itemStack The item for which to retrieve the real durability. + * @param armorTier The armor tier of the armored elytra. If this is null, it will be retrieved from NBT. + * @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/nbtEditor/NBTEditor.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java index 8368a76..27eec03 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java @@ -10,6 +10,7 @@ import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; @@ -17,14 +18,48 @@ import org.bukkit.persistence.PersistentDataType; import javax.annotation.Nullable; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.UUID; public class NBTEditor implements INBTEditor { - private static final NamespacedKey armorTierKey = new NamespacedKey(ArmoredElytra.getInstance(), - "ARMOR_TIER_LEVEL"); - private static final NamespacedKey armorColorKey = new NamespacedKey(ArmoredElytra.getInstance(), - "ARMORED_ELYTRA_COLOR"); + private static final NamespacedKey ARMOR_TIER_KEY = new NamespacedKey(ArmoredElytra.getInstance(), + "ARMOR_TIER_LEVEL"); + private static final NamespacedKey ARMOR_COLOR_KEY = new NamespacedKey(ArmoredElytra.getInstance(), + "ARMORED_ELYTRA_COLOR"); + private static final NamespacedKey DURABILITY_KEY = new NamespacedKey(ArmoredElytra.getInstance(), + "ARMORED_ELYTRA_DURABILITY"); + + @Override + public int getRealDurability(ItemStack itemStack, @Nullable ArmorTier providedTier) + { + final @Nullable ItemMeta meta = itemStack.getItemMeta(); + final ArmorTier armorTier = providedTier == null ? getArmorTier(meta) : providedTier; + + if (armorTier == ArmorTier.NONE) + return -1; + + if (!(meta instanceof Damageable)) + throw new IllegalStateException("Item \"" + itemStack + "\" with meta \"" + meta + "\" is not Damageable!"); + + final @Nullable Integer realDurability = + Objects.requireNonNull(meta, "Meta cannot be null for armored elytras!") + .getPersistentDataContainer().get(DURABILITY_KEY, PersistentDataType.INTEGER); + + return realDurability == null ? -1 : realDurability; + } + + @Override + public void updateDurability(ItemStack itemStack, int realDurability, int displayDurability) + { + final ItemMeta meta = getOrCreateItemMeta(itemStack); + meta.getPersistentDataContainer().set(DURABILITY_KEY, PersistentDataType.INTEGER, realDurability); + + if (meta instanceof Damageable) + ((Damageable) meta).setDamage(displayDurability); + + itemStack.setItemMeta(meta); + } @Override public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable, String name, @@ -33,14 +68,13 @@ public class NBTEditor implements INBTEditor if (armorTier == null || armorTier == ArmorTier.NONE) return new ItemStack(item); - ItemStack ret = new ItemStack(item); - ItemMeta meta = ret.hasItemMeta() ? ret.getItemMeta() : Bukkit.getItemFactory().getItemMeta(ret.getType()); - if (meta == null) - throw new IllegalArgumentException("Tried to add armor to invalid item: " + item); - meta.getPersistentDataContainer().set(armorTierKey, PersistentDataType.INTEGER, ArmorTier.getTierID(armorTier)); + final ItemStack ret = new ItemStack(item); + final ItemMeta meta = getOrCreateItemMeta(ret); + meta.getPersistentDataContainer().set(ARMOR_TIER_KEY, PersistentDataType.INTEGER, + ArmorTier.getTierID(armorTier)); if (color != null && armorTier == ArmorTier.LEATHER) - meta.getPersistentDataContainer().set(armorColorKey, PersistentDataType.INTEGER, color.asRGB()); + meta.getPersistentDataContainer().set(ARMOR_COLOR_KEY, PersistentDataType.INTEGER, color.asRGB()); overwriteNBTValue(meta, Attribute.GENERIC_ARMOR, ArmorTier.getArmor(armorTier), "generic.armor"); if (ArmorTier.getToughness(armorTier) > 0) @@ -65,33 +99,29 @@ public class NBTEditor implements INBTEditor if (meta.hasAttributeModifiers()) meta.removeAttributeModifier(attribute); - AttributeModifier attributeModifier = new AttributeModifier(UUID.randomUUID(), modifierName, value, - AttributeModifier.Operation.ADD_NUMBER, - EquipmentSlot.CHEST); + final AttributeModifier attributeModifier = new AttributeModifier(UUID.randomUUID(), modifierName, value, + AttributeModifier.Operation.ADD_NUMBER, + EquipmentSlot.CHEST); meta.addAttributeModifier(attribute, attributeModifier); } - @Override - public ArmorTier getArmorTier(ItemStack item) + private ArmorTier getArmorTier(@Nullable ItemMeta meta) { - if (item == null) - return ArmorTier.NONE; - - ItemMeta meta = item.getItemMeta(); if (meta == null || !meta.hasAttributeModifiers()) return ArmorTier.NONE; - Integer tierID = meta.getPersistentDataContainer().get(armorTierKey, PersistentDataType.INTEGER); + final @Nullable Integer tierID = meta.getPersistentDataContainer() + .get(ARMOR_TIER_KEY, PersistentDataType.INTEGER); if (tierID != null) return ArmorTier.getArmorTierFromID(tierID); - Collection attributeModifiers = meta.getAttributeModifiers(Attribute.GENERIC_ARMOR); + final Collection attributeModifiers = meta.getAttributeModifiers(Attribute.GENERIC_ARMOR); if (attributeModifiers == null) return ArmorTier.NONE; for (final AttributeModifier attributeModifier : attributeModifiers) { - ArmorTier armorTier = ArmorTier.getArmorTierFromArmor((int) attributeModifier.getAmount()); + final ArmorTier armorTier = ArmorTier.getArmorTierFromArmor((int) attributeModifier.getAmount()); if (armorTier != ArmorTier.NONE) return armorTier; } @@ -100,7 +130,15 @@ public class NBTEditor implements INBTEditor } @Override - public Color getColorOfArmoredElytra(final ItemStack item) + public ArmorTier getArmorTier(@Nullable ItemStack item) + { + if (item == null) + return ArmorTier.NONE; + return getArmorTier(item.getItemMeta()); + } + + @Override + public Color getColorOfArmoredElytra(@Nullable ItemStack item) { if (item == null || item.getType() != Material.ELYTRA || !item.hasItemMeta()) return null; @@ -110,10 +148,20 @@ public class NBTEditor implements INBTEditor return null; final PersistentDataContainer container = meta.getPersistentDataContainer(); - if (!container.has(armorColorKey, PersistentDataType.INTEGER)) + if (!container.has(ARMOR_COLOR_KEY, PersistentDataType.INTEGER)) return null; - final Integer rgb = container.get(armorColorKey, PersistentDataType.INTEGER); + final Integer rgb = container.get(ARMOR_COLOR_KEY, PersistentDataType.INTEGER); return rgb == null ? null : Color.fromRGB(rgb); } + + private static ItemMeta getOrCreateItemMeta(ItemStack item) + { + final ItemMeta meta = item.hasItemMeta() ? + item.getItemMeta() : + Bukkit.getItemFactory().getItemMeta(item.getType()); + if (meta == null) + throw new IllegalArgumentException("Tried to add armor to invalid item: " + item); + return meta; + } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/Action.java b/src/main/java/nl/pim16aap2/armoredElytra/util/Action.java index a9bd2a4..e3bb55c 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/util/Action.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/Action.java @@ -2,5 +2,33 @@ package nl.pim16aap2.armoredElytra.util; public enum Action { - NONE, REPAIR, ENCHANT, COMBINE, CREATE, BLOCK + /** + * Take no action at all and let vanilla (or some other plugin) handle the process. + */ + NONE, + + /** + * Repair an armored elytra. + */ + REPAIR, + + /** + * Enchant an armored elytra. + */ + ENCHANT, + + /** + * Combines one armored elytra with another one of the same tier. + */ + COMBINE, + + /** + * Creates a new armored elytra. + */ + CREATE, + + /** + * Blocks an otherwise valid input. + */ + BLOCK } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/ArmorTier.java b/src/main/java/nl/pim16aap2/armoredElytra/util/ArmorTier.java index e20ac62..d3e6d62 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/util/ArmorTier.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/ArmorTier.java @@ -29,8 +29,8 @@ public enum ArmorTier private static final Map armorValueMap = new HashMap<>(); private static final Map armorIDMap = new HashMap<>(); - ArmorTier(int tierID, int armor, int toughness, double knockbackResistance, Material repair, int defaultRepairCount, - String name, int durability) + ArmorTier(int tierID, int armor, int toughness, double knockbackResistance, Material repair, + int defaultRepairCount, String name, int durability) { this.tierID = tierID; this.armor = armor; diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java b/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java index 6bbb353..6c0ab2e 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java @@ -73,7 +73,8 @@ public class ConfigLoader String[] repairComment = { "Amount of items it takes to fully repair an armored elytra", - "Repair cost for every tier of armored elytra in number of items to repair 100%." + "Repair cost for every tier of armored elytra in number of items to repair 100%.", + "Note that this value cannot be less than 1." }; String[] enchantmentsComment = { @@ -328,7 +329,7 @@ public class ConfigLoader public int getFullRepairItemCount(ArmorTier armorTier) { - return repairCounts[ArmorTier.getArmor(armorTier)]; + return repairCounts[armorTier.ordinal()]; } public boolean allowMultipleProtectionEnchantments() diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java b/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java index 7acaa57..8e15057 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/Util.java @@ -137,4 +137,17 @@ public class Util ret += 16; return ret; } + + /** + * Ensures that a given value does not exceed the provided upper and lower bounds. + * + * @param val The value to check. + * @param min The lower bound limit. + * @param max The upper bound limit. + * @return The value if it is bigger than min and larger than max, otherwise either min or max. + */ + public static int between(int val, int min, int max) + { + return Math.max(min, Math.min(max, val)); + } }