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