diff --git a/pom.xml b/pom.xml
index 03b6623..9004cc2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
nl.pim16aap2
ArmoredElytra
- 2.4.13
+ 2.4.14
@@ -30,7 +30,7 @@
org.spigotmc
spigot-api
- 1.15.1-R0.1-SNAPSHOT
+ 1.16.1-R0.1-SNAPSHOT
provided
@@ -38,7 +38,7 @@
org.spigotmc
spigot
- 1.15.1-R0.1-SNAPSHOT
+ 1.16.1-R0.1-SNAPSHOT
provided
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java
index 7361b69..6c03aa5 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java
@@ -5,10 +5,13 @@ import nl.pim16aap2.armoredElytra.handlers.EventHandlers;
import nl.pim16aap2.armoredElytra.handlers.FlyDurabilityHandler;
import nl.pim16aap2.armoredElytra.handlers.LoginHandler;
import nl.pim16aap2.armoredElytra.handlers.Uninstaller;
+import nl.pim16aap2.armoredElytra.nbtEditor.INBTEditor;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
+import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor_legacy;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.ArmorTierName;
import nl.pim16aap2.armoredElytra.util.ConfigLoader;
+import nl.pim16aap2.armoredElytra.util.MinecraftVersion;
import nl.pim16aap2.armoredElytra.util.UpdateManager;
import nl.pim16aap2.armoredElytra.util.messages.Message;
import nl.pim16aap2.armoredElytra.util.messages.Messages;
@@ -31,6 +34,9 @@ import java.util.logging.Level;
public class ArmoredElytra extends JavaPlugin implements Listener
{
+ private static final MinecraftVersion minecraftVersion = MinecraftVersion
+ .get(Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]);
+
private static ArmoredElytra instance;
private Messages messages;
private ConfigLoader config;
@@ -40,10 +46,20 @@ public class ArmoredElytra extends JavaPlugin implements Listener
private boolean is1_9;
private UpdateManager updateManager;
+ private INBTEditor nbtEditor;
+
@Override
public void onEnable()
{
instance = this;
+ if (minecraftVersion.isOlderThan(MinecraftVersion.v1_8))
+ {
+ myLogger(Level.SEVERE, "Trying to run this plugin on an unsupported version... ABORT!");
+ return;
+ }
+
+ nbtEditor = minecraftVersion.isNewerThan(MinecraftVersion.v1_15) ? new NBTEditor() : new NBTEditor_legacy();
+
config = new ConfigLoader(this);
messages = new Messages(this);
readMessages();
@@ -108,6 +124,11 @@ public class ArmoredElytra extends JavaPlugin implements Listener
return messages;
}
+ public INBTEditor getNbtEditor()
+ {
+ return nbtEditor;
+ }
+
private void readMessages()
{
armorTierNames.put(ArmorTier.NONE, new ArmorTierName("NONE", "NONE")); // Shouldn't be used.
@@ -129,6 +150,11 @@ public class ArmoredElytra extends JavaPlugin implements Listener
player.hasPermission("armoredelytra.craft." + ArmorTier.getName(armorTier));
}
+ public static MinecraftVersion getMinecraftVersion()
+ {
+ return minecraftVersion;
+ }
+
public boolean playerHasWearPerm(Player player, ArmorTier armorTier)
{
return getConfigLoader().bypassWearPerm() ||
@@ -229,7 +255,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener
// Check + initialize for the correct version of Minecraft.
public boolean compatibleMCVer()
{
- return NBTEditor.success();
+ return minecraftVersion.isNewerThan(MinecraftVersion.v1_8);
}
public static ArmoredElytra getInstance()
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java
index f75f3d2..37cc248 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java
@@ -1,7 +1,6 @@
package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
-import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.messages.Message;
import org.bukkit.Bukkit;
@@ -76,8 +75,9 @@ public class CommandHandler implements CommandExecutor
if (allowed)
{
plugin.elytraReceivedMessage(receiver, armorTier);
- newElytra = NBTEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier,
- plugin.getConfigLoader().unbreakable());
+ newElytra = ArmoredElytra.getInstance().getNbtEditor()
+ .addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier,
+ plugin.getConfigLoader().unbreakable());
plugin.giveArmoredElytraToPlayer(receiver, newElytra);
}
else
@@ -106,8 +106,9 @@ public class CommandHandler implements CommandExecutor
return false;
plugin.elytraReceivedMessage(player, armorTier);
- newElytra = NBTEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier,
- plugin.getConfigLoader().unbreakable());
+ newElytra = ArmoredElytra.getInstance().getNbtEditor()
+ .addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier,
+ plugin.getConfigLoader().unbreakable());
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 cb56134..4c94b88 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java
@@ -5,7 +5,6 @@ import com.codingforcookies.armorequip.ArmorListener;
import com.codingforcookies.armorequip.ArmorType;
import com.codingforcookies.armorequip.DispenserArmorListener;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
-import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.Action;
import nl.pim16aap2.armoredElytra.util.AllowedToWearEnum;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
@@ -131,13 +130,13 @@ public class EventHandlers implements Listener
Integer enchantLevel = enchantments0.get(entry.getKey());
if (enchantLevel != null)
{
- if (entry.getValue() == enchantLevel && entry.getValue() < entry.getKey().getMaxLevel())
+ if (entry.getValue().equals(enchantLevel) && entry.getValue() < entry.getKey().getMaxLevel())
enchantLevel = entry.getValue() + 1;
else if (entry.getValue() > enchantLevel)
enchantLevel = entry.getValue();
// If the enchantment level has changed,
- if (enchantLevel != enchantments0.get(entry.getKey()))
+ if (!enchantLevel.equals(enchantments0.get(entry.getKey())))
{
combined.remove(entry.getKey());
combined.put(entry.getKey(), enchantLevel);
@@ -255,7 +254,7 @@ public class EventHandlers implements Listener
if (Util.isChestPlate(matTwo))
return Action.CREATE;
- ArmorTier tier = NBTEditor.getArmorTier(itemOne);
+ ArmorTier tier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemOne);
if (tier != ArmorTier.NONE)
{
@@ -269,7 +268,7 @@ public class EventHandlers implements Listener
// If the armored elytra is to be combined with another armored elytra of the
// same tier...
- if (NBTEditor.getArmorTier(itemTwo) == tier)
+ if (ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemTwo) == tier)
return Action.COMBINE;
// If the armored elytra is not of the leather tier, but itemTwo is leather,
@@ -306,7 +305,7 @@ public class EventHandlers implements Listener
{
Action action = isValidInput(itemA, itemB);
ArmorTier newTier = ArmorTier.NONE;
- ArmorTier curTier = NBTEditor.getArmorTier(itemA);
+ ArmorTier curTier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemA);
short durability = 0;
Map enchantments = itemA.getEnchantments();
enchantments = fixEnchantments(enchantments);
@@ -356,14 +355,15 @@ public class EventHandlers implements Listener
result.addUnsafeEnchantments(enchantments);
result.setDurability(durability);
- result = NBTEditor.addArmorNBTTags(result, newTier, plugin.getConfigLoader().unbreakable());
+ result = ArmoredElytra.getInstance().getNbtEditor()
+ .addArmorNBTTags(result, newTier, plugin.getConfigLoader().unbreakable());
event.setResult(result);
}
}
// Check if either itemA or itemB is unoccupied.
if ((itemA == null || itemB == null) &&
- NBTEditor.getArmorTier(event.getInventory().getItem(2)) != ArmorTier.NONE)
+ ArmoredElytra.getInstance().getNbtEditor().getArmorTier(event.getInventory().getItem(2)) != ArmorTier.NONE)
// If Item2 is occupied despite itemA or itemB not being occupied. (only for
// armored elytra)/
event.setResult(null);
@@ -404,7 +404,7 @@ public class EventHandlers implements Listener
if (slot == 2 && anvilInventory.getItem(0) != null && anvilInventory.getItem(1) != null &&
anvilInventory.getItem(2) != null)
{
- ArmorTier armortier = NBTEditor.getArmorTier(anvilInventory.getItem(2));
+ ArmorTier armortier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(anvilInventory.getItem(2));
// If there's an armored elytra in the final slot...
if (armortier != ArmorTier.NONE && plugin.playerHasCraftPerm(player, armortier))
@@ -413,8 +413,9 @@ public class EventHandlers implements Listener
// result.
// This is done because after putting item0 in AFTER item1, the first letter of
// the color code shows up, this gets rid of that problem.
- ItemStack result = NBTEditor.addArmorNBTTags(anvilInventory.getItem(2), armortier,
- plugin.getConfigLoader().unbreakable());
+ ItemStack result = ArmoredElytra.getInstance().getNbtEditor()
+ .addArmorNBTTags(anvilInventory.getItem(2), armortier,
+ plugin.getConfigLoader().unbreakable());
// Give the result to the player and clear the anvil's inventory.
if (e.isShiftClick())
@@ -465,7 +466,8 @@ public class EventHandlers implements Listener
if (p.getInventory().getChestplate() == null)
return;
- if (NBTEditor.getArmorTier(p.getInventory().getChestplate()) == ArmorTier.NONE)
+ if (ArmoredElytra.getInstance().getNbtEditor().getArmorTier(p.getInventory().getChestplate()) ==
+ ArmorTier.NONE)
return;
ItemStack elytra = p.getInventory().getChestplate();
@@ -519,7 +521,7 @@ public class EventHandlers implements Listener
!e.getNewArmorPiece().getType().equals(Material.ELYTRA))
return;
- ArmorTier armorTier = NBTEditor.getArmorTier(e.getNewArmorPiece());
+ ArmorTier armorTier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(e.getNewArmorPiece());
AllowedToWearEnum allowed = isAllowedToWear(e.getNewArmorPiece(), e.getPlayer(), armorTier);
switch (allowed)
{
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java
index 8f67210..79fe0f8 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java
@@ -1,6 +1,6 @@
package nl.pim16aap2.armoredElytra.handlers;
-import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
+import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
@@ -24,7 +24,7 @@ public class FlyDurabilityHandler implements Listener
if (!e.getPlayer().isGliding())
return;
- if (NBTEditor.getArmorTier(e.getItem()) != ArmorTier.NONE)
+ if (ArmoredElytra.getInstance().getNbtEditor().getArmorTier(e.getItem()) != ArmorTier.NONE)
e.setCancelled(true);
}
}
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/Uninstaller.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/Uninstaller.java
index ec7ec53..b745f58 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/Uninstaller.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/Uninstaller.java
@@ -1,7 +1,6 @@
package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
-import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import org.bukkit.ChatColor;
import org.bukkit.Material;
@@ -28,13 +27,12 @@ public class Uninstaller implements Listener
{
int count = 0;
for (ItemStack is : inv)
- if (is != null)
- if (is.getType() == Material.ELYTRA)
- if (NBTEditor.getArmorTier(is) != ArmorTier.NONE)
- {
- inv.remove(is);
- ++count;
- }
+ if (is != null && is.getType() == Material.ELYTRA &&
+ ArmoredElytra.getInstance().getNbtEditor().getArmorTier(is) != ArmorTier.NONE)
+ {
+ inv.remove(is);
+ ++count;
+ }
return count;
}
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/INBTEditor.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/INBTEditor.java
new file mode 100644
index 0000000..3b91929
--- /dev/null
+++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/INBTEditor.java
@@ -0,0 +1,25 @@
+package nl.pim16aap2.armoredElytra.nbtEditor;
+
+import nl.pim16aap2.armoredElytra.util.ArmorTier;
+import org.bukkit.inventory.ItemStack;
+
+public interface INBTEditor
+{
+ /**
+ * Adds a given {@link ArmorTier} to an item. The item will be cloned.
+ *
+ * @param item The item.
+ * @param armorTier The {@link ArmorTier} that will be added to it.
+ * @param unbreakable Whether the resulting item should be unbreakable.
+ * @return The NEW item.
+ */
+ ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable);
+
+ /**
+ * Checks which {@link ArmorTier} is on an item.
+ *
+ * @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);
+}
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java
index dab6f46..eef9402 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java
@@ -3,373 +3,79 @@ package nl.pim16aap2.armoredElytra.nbtEditor;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
+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.ItemMeta;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.function.Function;
-import java.util.logging.Level;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.util.Collection;
+import java.util.UUID;
-public class NBTEditor
+public class NBTEditor implements INBTEditor
{
- private static final String versionString = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
- private static final MinecraftVersion minecraftVersion = MinecraftVersion.get(versionString);
- private static final String NMSbase = "net.minecraft.server." + versionString + ".";
- private static final String CraftBase = "org.bukkit.craftbukkit." + versionString + ".";
-
- private static Method asNMSCopy;
- private static Method asBukkitCopy;
- private static Class> NMSItemStack;
- private static Class> CraftItemStack;
-
- private static Class> NBTTagCompound;
- private static Class> NBTTagList;
- private static Class> NBTBase;
- private static Class> NBTTagString;
- private static Class> NBTTagByte;
- private static Class> NBTTagInt;
-
- private static Method hasTag;
- private static Method getTag;
-
- private static Method addCompound;
-
- private static Method setTag;
-
- private static Method setCompoundByte;
- private static Method setCompoundTagList;
-
- private static Method getCompoundTagList;
- private static Method getTagListSize;
- private static Method getTagListAtIndex;
-
- private static Constructor> NBTTagStringCtor;
- private static Constructor> NBTTagByteCtor;
- private static Constructor> NBTTagIntCtor;
-
- private static boolean success;
-
- private static Function getArmorValue;
-
-
- private static final Pattern pattern_findAmount_double = Pattern.compile("Amount:[0-9]+.[0-9]+d[,}]*");
- private static final Pattern pattern_findAmount_int = Pattern.compile("Amount:[0-9]+[,}]*");
- private static final Pattern pattern_getDouble = Pattern.compile("[0-9]+.[0-9]+");
- private static final Pattern pattern_getInt = Pattern.compile("[0-9]+");
- private static final Pattern pattern_isArmor = Pattern.compile("\"generic.armor\"");
-
-
- static
+ public NBTEditor()
{
- if (minecraftVersion == null)
- success = false;
- else
- try
- {
- // 1.13 and lower use integer armor values while 1.14 and newer use double armor values.
- getArmorValue = minecraftVersion.isNewerThan(MinecraftVersion.v1_13) ?
- NBTEditor::getArmorValueDouble : NBTEditor::getArmorValueInt;
-
- NMSItemStack = getNMSClass("ItemStack");
- hasTag = NMSItemStack.getMethod("hasTag");
- getTag = NMSItemStack.getMethod("getTag");
-
- CraftItemStack = getCraftClass("inventory.CraftItemStack");
- asNMSCopy = CraftItemStack.getMethod("asNMSCopy", ItemStack.class);
- asBukkitCopy = CraftItemStack.getMethod("asBukkitCopy", NMSItemStack);
-
- NBTBase = getNMSClass("NBTBase");
-
- NBTTagString = getNMSClass("NBTTagString");
- NBTTagStringCtor = NBTTagString.getDeclaredConstructor(String.class);
- NBTTagStringCtor.setAccessible(true);
-
- NBTTagByte = getNMSClass("NBTTagByte");
- NBTTagByteCtor = NBTTagByte.getDeclaredConstructor(byte.class);
- NBTTagByteCtor.setAccessible(true);
-
- NBTTagInt = getNMSClass("NBTTagInt");
- NBTTagIntCtor = NBTTagInt.getDeclaredConstructor(int.class);
- NBTTagIntCtor.setAccessible(true);
-
- NBTTagCompound = getNMSClass("NBTTagCompound");
- setTag = NBTTagCompound.getMethod("set", String.class, NBTBase);
-
- NBTTagList = getNMSClass("NBTTagList");
- getTagListSize = NBTTagList.getMethod("size");
- getTagListAtIndex = NBTTagList.getMethod("get", int.class);
- // Starting in 1.14, you also need to provide an int value when adding nbt tags.
- try
- {
- addCompound = NBTTagList.getMethod("add", NBTBase);
- }
- catch (Exception e)
- {
- addCompound = NBTTagList.getMethod("add", int.class, NBTBase);
- }
-
- setCompoundTagList = NBTTagCompound.getMethod("set", String.class, NBTBase);
- setCompoundByte = NBTTagCompound.getMethod("set", String.class, NBTBase);
- getCompoundTagList = NBTTagCompound.getMethod("getList", String.class, int.class);
-
- success = true;
- }
- catch (NoSuchMethodException | SecurityException | ClassNotFoundException e)
- {
- e.printStackTrace();
- success = false;
- }
- }
-
- private static void addCompound(Object instance, Object nbtbase)
- throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
- {
- if (addCompound.getParameterCount() == 2)
- addCompound.invoke(instance, 0, nbtbase);
- else
- addCompound.invoke(instance, nbtbase);
- }
-
- // Add armor to the supplied item, based on the armorTier.
- public static ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable)
- {
- try
- {
- ItemMeta itemmeta = item.getItemMeta();
- int armorProtection = ArmorTier.getArmor(armorTier);
- int armorToughness = ArmorTier.getToughness(armorTier);
-
- itemmeta.setDisplayName(ArmoredElytra.getInstance().getArmoredElytraName(armorTier));
- final String message = ChatColor.stripColor(ArmoredElytra.getInstance().getElytraLore(armorTier));
- if (message != null)
- itemmeta.setLore(Arrays.asList(message));
-
- item.setItemMeta(itemmeta);
-
- Object nmsStack = asNMSCopy.invoke(null, item);
- Object compound = ((boolean) hasTag.invoke(nmsStack) ? getTag.invoke(nmsStack) :
- NBTTagCompound.newInstance());
- Object modifiers = NBTTagList.newInstance();
- Object armor = NBTTagCompound.newInstance(); // I should be able to simply add custom tags here!
- setTag.invoke(armor, "AttributeName", NBTTagStringCtor.newInstance("generic.armor"));
- setTag.invoke(armor, "Name", NBTTagStringCtor.newInstance("generic.armor"));
- setTag.invoke(armor, "Amount", NBTTagIntCtor.newInstance(armorProtection));
- setTag.invoke(armor, "Operation", NBTTagIntCtor.newInstance(0));
- setTag.invoke(armor, "UUIDLeast", NBTTagIntCtor.newInstance(894654));
- setTag.invoke(armor, "UUIDMost", NBTTagIntCtor.newInstance(2872));
- setTag.invoke(armor, "Slot", NBTTagStringCtor.newInstance("chest"));
- addCompound(modifiers, armor);
-
- Object armorTough = NBTTagCompound.newInstance();
- setTag.invoke(armorTough, "AttributeName", NBTTagStringCtor.newInstance("generic.armorToughness"));
- setTag.invoke(armorTough, "Name", NBTTagStringCtor.newInstance("generic.armorToughness"));
- setTag.invoke(armorTough, "Amount", NBTTagIntCtor.newInstance(armorToughness));
- setTag.invoke(armorTough, "Operation", NBTTagIntCtor.newInstance(0));
- setTag.invoke(armorTough, "UUIDLeast", NBTTagIntCtor.newInstance(894654));
- setTag.invoke(armorTough, "UUIDMost", NBTTagIntCtor.newInstance(2872));
- setTag.invoke(armorTough, "Slot", NBTTagStringCtor.newInstance("chest"));
- addCompound(modifiers, armorTough);
-
- if (unbreakable)
- setCompoundByte.invoke(compound, "Unbreakable", NBTTagByteCtor.newInstance((byte) 1));
-
- setCompoundTagList.invoke(compound, "AttributeModifiers", modifiers);
- item = (ItemStack) asBukkitCopy.invoke(null, nmsStack);
- }
- catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e)
- {
- e.printStackTrace();
- }
- return item;
}
/**
- * Gets the armor amount from an NBT attribute.
- *
- * @param string The NBT attribute as a String.
- * @param findAmount The {@link Pattern} that finds the amount in a String.
- * @param parseAmount The {@link Pattern} that extracts the amount from the String found by "findAmount".
- * @return The String containing the armor value. This can either be an integer or a double value.
+ * {@inheritDoc}
*/
- private static String getArmorAmount(final String string, final Pattern findAmount, final Pattern parseAmount)
+ @Override
+ public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable)
{
- final Matcher amountMatcher = findAmount.matcher(string);
- if (!amountMatcher.find())
- {
- ArmoredElytra.getInstance()
- .myLogger(Level.SEVERE,
- "Failed to obtain armor value from NBT! No armor amount found: " + string);
- return "0";
- }
+ 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);
- final String amountName = amountMatcher.group();
- final Matcher amountString = parseAmount.matcher(amountName);
- if (!amountString.find())
- {
- ArmoredElytra.getInstance()
- .myLogger(Level.SEVERE,
- "Failed to obtain armor value from NBT! Could not parse value: " + amountName);
- return "0";
- }
- return amountString.group();
+ overwriteNBTValue(meta, Attribute.GENERIC_ARMOR, ArmorTier.getArmor(armorTier), "generic.armor");
+
+ if (ArmorTier.getToughness(armorTier) > 0)
+ overwriteNBTValue(meta, Attribute.GENERIC_ARMOR_TOUGHNESS, ArmorTier.getToughness(armorTier),
+ "generic.armorToughness");
+
+ meta.setUnbreakable(unbreakable);
+ meta.setDisplayName(ArmoredElytra.getInstance().getArmoredElytraName(armorTier));
+
+ ret.setItemMeta(meta);
+ return ret;
+ }
+
+ private void overwriteNBTValue(ItemMeta meta, Attribute attribute, double value, String modifierName)
+ {
+ if (meta.hasAttributeModifiers())
+ meta.removeAttributeModifier(attribute);
+
+ AttributeModifier attributeModifier = new AttributeModifier(UUID.randomUUID(), modifierName, value,
+ AttributeModifier.Operation.ADD_NUMBER, EquipmentSlot.CHEST);
+ meta.addAttributeModifier(attribute, attributeModifier);
}
/**
- * Gets the amount of an attribute in the format of: "something something, amount:2.0d,". The amount is cast to and
- * returned as an integer value.
- *
- * @param string The nbt attribute as String.
- * @return The integer value of the amount.
+ * {@inheritDoc}
*/
- private static int getArmorValueDouble(final String string)
+ @Override
+ public ArmorTier getArmorTier(ItemStack item)
{
- try
- {
- return (int) Double.parseDouble(getArmorAmount(string, pattern_findAmount_double, pattern_getDouble));
- }
- catch (NumberFormatException e)
- {
- e.printStackTrace();
- }
- return 0;
- }
-
- /**
- * Gets the amount of an attribute in the format of: "something something, amount:2.0d,". The amount is cast to and
- * returned as an integer value.
- *
- * @param string The nbt attribute as String.
- * @return The integer value of the amount.
- */
- private static int getArmorValueInt(final String string)
- {
- try
- {
- return Integer.parseInt(getArmorAmount(string, pattern_findAmount_int, pattern_getInt));
- }
- catch (NumberFormatException e)
- {
- e.printStackTrace();
- }
- return 0;
- }
-
- public static ArmorTier getArmorTier(ItemStack item)
- {
-// {
-// double armorValue_2 = 0;
-// net.minecraft.server.v1_15_R1.ItemStack nmsStack_2 = org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack
-// .asNMSCopy(item);
-//
-// net.minecraft.server.v1_15_R1.NBTTagCompound compound_2 =
-// nmsStack_2.hasTag() ? nmsStack_2.getTag() : new net.minecraft.server.v1_15_R1.NBTTagCompound();
-//
-// net.minecraft.server.v1_15_R1.NBTTagList modifiers_2 = compound_2.getList("AttributeModifiers", 10);
-// }
-
- try
- {
- Object compound = getTag.invoke(asNMSCopy.invoke(null, item));
- if (compound == null)
- return ArmorTier.NONE;
-
- Object modifiers = getCompoundTagList.invoke(compound, "AttributeModifiers", 10); // Number 10 = Compound.
- int size = (int) getTagListSize.invoke(modifiers);
-
-
- for (int idx = 0; idx < size; ++idx)
- {
-// final String result = modifiers.get(idx).asString();
- final String result = getTagListAtIndex.invoke(modifiers, idx).toString();
-
- if (!pattern_isArmor.matcher(result).find())
- continue;
-
- int armorValue = getArmorValue.apply(result);
- switch (armorValue)
- {
- case 3:
- return ArmorTier.LEATHER;
- case 5:
- return ArmorTier.GOLD;
- case 6:
- return ArmorTier.IRON;
- case 8:
- return ArmorTier.DIAMOND;
- default:
- return ArmorTier.NONE;
- }
- }
+ if (item == null)
return ArmorTier.NONE;
- }
- catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
- {
- e.printStackTrace();
+
+ ItemMeta meta = item.getItemMeta();
+ if (meta == null)
return ArmorTier.NONE;
- }
- }
- private static Class> getNMSClass(String name)
- throws ClassNotFoundException
- {
- return Class.forName(NMSbase + name);
- }
+ Collection attributeModifiers = meta.getAttributeModifiers(Attribute.GENERIC_ARMOR);
+ if (attributeModifiers == null)
+ return ArmorTier.NONE;
- private static Class> getCraftClass(String name)
- throws ClassNotFoundException
- {
- return Class.forName(CraftBase + name);
- }
-
- public static boolean success()
- {
- return success;
- }
-
- private enum MinecraftVersion
- {
- v1_9("1_9", 0),
- v1_10("1_10", 1),
- v1_11("1_11", 2),
- v1_12("1_12", 3),
- v1_13("1_13", 4),
- v1_14("1_14", 5),
- v1_15("1_15", 6);
-
- private int index;
- private String name;
-
- MinecraftVersion(String name, int index)
+ for (final AttributeModifier attributeModifier : attributeModifiers)
{
- this.name = name;
- this.index = index;
+ ArmorTier armorTier = ArmorTier.getArmorTier((int) attributeModifier.getAmount());
+ if (armorTier != ArmorTier.NONE)
+ return armorTier;
}
- /**
- * Checks if this version is newer than the other version.
- *
- * @param other The other version to check against.
- * @return True if this version is newer than the other version.
- */
- public boolean isNewerThan(final MinecraftVersion other)
- {
- return this.index > other.index;
- }
-
- public static MinecraftVersion get(final String versionName)
- {
- if (versionName == null)
- return null;
- for (final MinecraftVersion mcVersion : MinecraftVersion.values())
- if (versionName.contains(mcVersion.name))
- return mcVersion;
- return null;
- }
+ return ArmorTier.NONE;
}
}
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor_legacy.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor_legacy.java
new file mode 100644
index 0000000..1d40d72
--- /dev/null
+++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor_legacy.java
@@ -0,0 +1,330 @@
+package nl.pim16aap2.armoredElytra.nbtEditor;
+
+import nl.pim16aap2.armoredElytra.ArmoredElytra;
+import nl.pim16aap2.armoredElytra.util.ArmorTier;
+import nl.pim16aap2.armoredElytra.util.MinecraftVersion;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.function.Function;
+import java.util.logging.Level;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class NBTEditor_legacy implements INBTEditor
+{
+ private static final String versionString = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
+ private static final MinecraftVersion minecraftVersion = ArmoredElytra.getMinecraftVersion();
+ private static final String NMSbase = "net.minecraft.server." + versionString + ".";
+ private static final String CraftBase = "org.bukkit.craftbukkit." + versionString + ".";
+
+ private static Method asNMSCopy;
+ private static Method asBukkitCopy;
+ private static Class> NMSItemStack;
+ private static Class> CraftItemStack;
+
+ private static Class> NBTTagCompound;
+ private static Class> NBTTagList;
+ private static Class> NBTBase;
+ private static Class> NBTTagString;
+ private static Class> NBTTagByte;
+ private static Class> NBTTagInt;
+
+ private static Method hasTag;
+ private static Method getTag;
+
+ private static Method addCompound;
+
+ private static Method setTag;
+
+ private static Method setCompoundByte;
+ private static Method setCompoundTagList;
+
+ private static Method getCompoundTagList;
+ private static Method getTagListSize;
+ private static Method getTagListAtIndex;
+
+ private static Constructor> NBTTagStringCtor;
+ private static Constructor> NBTTagByteCtor;
+ private static Constructor> NBTTagIntCtor;
+
+ private static boolean success;
+
+ private static Function getArmorValue;
+
+
+ private static final Pattern pattern_findAmount_double = Pattern.compile("Amount:[0-9]+.[0-9]+d[,}]*");
+ private static final Pattern pattern_findAmount_int = Pattern.compile("Amount:[0-9]+[,}]*");
+ private static final Pattern pattern_getDouble = Pattern.compile("[0-9]+.[0-9]+");
+ private static final Pattern pattern_getInt = Pattern.compile("[0-9]+");
+ private static final Pattern pattern_isArmor = Pattern.compile("\"generic.armor\"");
+
+
+ static
+ {
+ if (minecraftVersion == null)
+ success = false;
+ else
+ try
+ {
+ // 1.13 and lower use integer armor values while 1.14 and newer use double armor values.
+ getArmorValue = minecraftVersion.isNewerThan(MinecraftVersion.v1_13) ?
+ NBTEditor_legacy::getArmorValueDouble : NBTEditor_legacy::getArmorValueInt;
+
+ NMSItemStack = getNMSClass("ItemStack");
+ hasTag = NMSItemStack.getMethod("hasTag");
+ getTag = NMSItemStack.getMethod("getTag");
+
+ CraftItemStack = getCraftClass("inventory.CraftItemStack");
+ asNMSCopy = CraftItemStack.getMethod("asNMSCopy", ItemStack.class);
+ asBukkitCopy = CraftItemStack.getMethod("asBukkitCopy", NMSItemStack);
+
+ NBTBase = getNMSClass("NBTBase");
+
+ NBTTagString = getNMSClass("NBTTagString");
+ NBTTagStringCtor = NBTTagString.getDeclaredConstructor(String.class);
+ NBTTagStringCtor.setAccessible(true);
+
+ NBTTagByte = getNMSClass("NBTTagByte");
+ NBTTagByteCtor = NBTTagByte.getDeclaredConstructor(byte.class);
+ NBTTagByteCtor.setAccessible(true);
+
+ NBTTagInt = getNMSClass("NBTTagInt");
+ NBTTagIntCtor = NBTTagInt.getDeclaredConstructor(int.class);
+ NBTTagIntCtor.setAccessible(true);
+
+ NBTTagCompound = getNMSClass("NBTTagCompound");
+ setTag = NBTTagCompound.getMethod("set", String.class, NBTBase);
+
+ NBTTagList = getNMSClass("NBTTagList");
+ getTagListSize = NBTTagList.getMethod("size");
+ getTagListAtIndex = NBTTagList.getMethod("get", int.class);
+ // Starting in 1.14, you also need to provide an int value when adding nbt tags.
+ try
+ {
+ addCompound = NBTTagList.getMethod("add", NBTBase);
+ }
+ catch (Exception e)
+ {
+ addCompound = NBTTagList.getMethod("add", int.class, NBTBase);
+ }
+
+ setCompoundTagList = NBTTagCompound.getMethod("set", String.class, NBTBase);
+ setCompoundByte = NBTTagCompound.getMethod("set", String.class, NBTBase);
+ getCompoundTagList = NBTTagCompound.getMethod("getList", String.class, int.class);
+
+ success = true;
+ }
+ catch (NoSuchMethodException | SecurityException | ClassNotFoundException e)
+ {
+ e.printStackTrace();
+ success = false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ArmorTier getArmorTier(ItemStack item)
+ {
+ try
+ {
+ Object compound = getTag.invoke(asNMSCopy.invoke(null, item));
+ if (compound == null)
+ return ArmorTier.NONE;
+
+ Object modifiers = getCompoundTagList.invoke(compound, "AttributeModifiers", 10); // Number 10 = Compound.
+ int size = (int) getTagListSize.invoke(modifiers);
+
+
+ for (int idx = 0; idx < size; ++idx)
+ {
+ final String result = getTagListAtIndex.invoke(modifiers, idx).toString();
+
+ if (!pattern_isArmor.matcher(result).find())
+ continue;
+
+ int armorValue = getArmorValue.apply(result);
+ switch (armorValue)
+ {
+ case 3:
+ return ArmorTier.LEATHER;
+ case 5:
+ return ArmorTier.GOLD;
+ case 6:
+ return ArmorTier.IRON;
+ case 8:
+ return ArmorTier.DIAMOND;
+ default:
+ return ArmorTier.NONE;
+ }
+ }
+ return ArmorTier.NONE;
+ }
+ catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
+ {
+ e.printStackTrace();
+ return ArmorTier.NONE;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable)
+ {
+ try
+ {
+ ItemMeta itemmeta = item.getItemMeta();
+ int armorProtection = ArmorTier.getArmor(armorTier);
+ int armorToughness = ArmorTier.getToughness(armorTier);
+
+ itemmeta.setDisplayName(ArmoredElytra.getInstance().getArmoredElytraName(armorTier));
+ final String message = ChatColor.stripColor(ArmoredElytra.getInstance().getElytraLore(armorTier));
+ if (message != null)
+ itemmeta.setLore(Arrays.asList(message));
+
+ item.setItemMeta(itemmeta);
+
+ Object nmsStack = asNMSCopy.invoke(null, item);
+ Object compound = ((boolean) hasTag.invoke(nmsStack) ? getTag.invoke(nmsStack) :
+ NBTTagCompound.newInstance());
+ Object modifiers = NBTTagList.newInstance();
+ Object armor = NBTTagCompound.newInstance(); // I should be able to simply add custom tags here!
+ setTag.invoke(armor, "AttributeName", NBTTagStringCtor.newInstance("generic.armor"));
+ setTag.invoke(armor, "Name", NBTTagStringCtor.newInstance("generic.armor"));
+ setTag.invoke(armor, "Amount", NBTTagIntCtor.newInstance(armorProtection));
+ setTag.invoke(armor, "Operation", NBTTagIntCtor.newInstance(0));
+ setTag.invoke(armor, "UUIDLeast", NBTTagIntCtor.newInstance(894654));
+ setTag.invoke(armor, "UUIDMost", NBTTagIntCtor.newInstance(2872));
+ setTag.invoke(armor, "Slot", NBTTagStringCtor.newInstance("chest"));
+ addCompound(modifiers, armor);
+
+ Object armorTough = NBTTagCompound.newInstance();
+ setTag.invoke(armorTough, "AttributeName", NBTTagStringCtor.newInstance("generic.armorToughness"));
+ setTag.invoke(armorTough, "Name", NBTTagStringCtor.newInstance("generic.armorToughness"));
+ setTag.invoke(armorTough, "Amount", NBTTagIntCtor.newInstance(armorToughness));
+ setTag.invoke(armorTough, "Operation", NBTTagIntCtor.newInstance(0));
+ setTag.invoke(armorTough, "UUIDLeast", NBTTagIntCtor.newInstance(894654));
+ setTag.invoke(armorTough, "UUIDMost", NBTTagIntCtor.newInstance(2872));
+ setTag.invoke(armorTough, "Slot", NBTTagStringCtor.newInstance("chest"));
+ addCompound(modifiers, armorTough);
+
+ if (unbreakable)
+ setCompoundByte.invoke(compound, "Unbreakable", NBTTagByteCtor.newInstance((byte) 1));
+
+ setCompoundTagList.invoke(compound, "AttributeModifiers", modifiers);
+ item = (ItemStack) asBukkitCopy.invoke(null, nmsStack);
+ }
+ catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e)
+ {
+ e.printStackTrace();
+ }
+ return item;
+ }
+
+ private static void addCompound(Object instance, Object nbtbase)
+ throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
+ {
+ if (addCompound.getParameterCount() == 2)
+ addCompound.invoke(instance, 0, nbtbase);
+ else
+ addCompound.invoke(instance, nbtbase);
+ }
+
+ /**
+ * Gets the armor amount from an NBT attribute.
+ *
+ * @param string The NBT attribute as a String.
+ * @param findAmount The {@link Pattern} that finds the amount in a String.
+ * @param parseAmount The {@link Pattern} that extracts the amount from the String found by "findAmount".
+ * @return The String containing the armor value. This can either be an integer or a double value.
+ */
+ private static String getArmorAmount(final String string, final Pattern findAmount, final Pattern parseAmount)
+ {
+ final Matcher amountMatcher = findAmount.matcher(string);
+ if (!amountMatcher.find())
+ {
+ ArmoredElytra.getInstance()
+ .myLogger(Level.SEVERE,
+ "Failed to obtain armor value from NBT! No armor amount found: " + string);
+ return "0";
+ }
+
+ final String amountName = amountMatcher.group();
+ final Matcher amountString = parseAmount.matcher(amountName);
+ if (!amountString.find())
+ {
+ ArmoredElytra.getInstance()
+ .myLogger(Level.SEVERE,
+ "Failed to obtain armor value from NBT! Could not parse value: " + amountName);
+ return "0";
+ }
+ return amountString.group();
+ }
+
+ /**
+ * Gets the amount of an attribute in the format of: "something something, amount:2.0d,". The amount is cast to and
+ * returned as an integer value.
+ *
+ * @param string The nbt attribute as String.
+ * @return The integer value of the amount.
+ */
+ private static int getArmorValueDouble(final String string)
+ {
+ try
+ {
+ return (int) Double.parseDouble(getArmorAmount(string, pattern_findAmount_double, pattern_getDouble));
+ }
+ catch (NumberFormatException e)
+ {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ /**
+ * Gets the amount of an attribute in the format of: "something something, amount:2.0d,". The amount is cast to and
+ * returned as an integer value.
+ *
+ * @param string The nbt attribute as String.
+ * @return The integer value of the amount.
+ */
+ private static int getArmorValueInt(final String string)
+ {
+ try
+ {
+ return Integer.parseInt(getArmorAmount(string, pattern_findAmount_int, pattern_getInt));
+ }
+ catch (NumberFormatException e)
+ {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ private static Class> getNMSClass(String name)
+ throws ClassNotFoundException
+ {
+ return Class.forName(NMSbase + name);
+ }
+
+ private static Class> getCraftClass(String name)
+ throws ClassNotFoundException
+ {
+ return Class.forName(CraftBase + name);
+ }
+
+ public static boolean success()
+ {
+ return success;
+ }
+}
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/ArmorTier.java b/src/main/java/nl/pim16aap2/armoredElytra/util/ArmorTier.java
index 8b0dfe4..042a2a0 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/util/ArmorTier.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/util/ArmorTier.java
@@ -1,10 +1,10 @@
package nl.pim16aap2.armoredElytra.util;
+import org.bukkit.Material;
+
import java.util.HashMap;
import java.util.Map;
-import org.bukkit.Material;
-
public enum ArmorTier
{
// Tier: armor-value, armor-toughness, repair
@@ -19,7 +19,8 @@ public enum ArmorTier
private final int toughness;
private final Material repair;
private final String name;
- private static Map map = new HashMap<>();
+ private static Map map = new HashMap<>();
+ private static Map armorValueMap = new HashMap<>();
private ArmorTier (int armor, int toughness, Material repair, String name)
{
@@ -42,9 +43,18 @@ public enum ArmorTier
public static ArmorTier valueOfName (String name) { return map.get(name); }
+ public static ArmorTier getArmorTier(int armor)
+ {
+ ArmorTier tier = armorValueMap.get(armor);
+ return tier == null ? ArmorTier.NONE : tier;
+ }
+
static
{
for (ArmorTier tier : ArmorTier.values())
+ {
map.put(tier.name, tier);
+ armorValueMap.put(tier.armor, tier);
+ }
}
}
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/MinecraftVersion.java b/src/main/java/nl/pim16aap2/armoredElytra/util/MinecraftVersion.java
new file mode 100644
index 0000000..fff4e0b
--- /dev/null
+++ b/src/main/java/nl/pim16aap2/armoredElytra/util/MinecraftVersion.java
@@ -0,0 +1,61 @@
+package nl.pim16aap2.armoredElytra.util;
+
+public enum MinecraftVersion
+{
+ v1_6("1_6", 0),
+ v1_7("1_7", 1),
+ v1_8("1_8", 2),
+ v1_9("1_9", 3),
+ v1_10("1_10", 4),
+ v1_11("1_11", 5),
+ v1_12("1_12", 6),
+ v1_13("1_13", 7),
+ v1_14("1_14", 8),
+ v1_15("1_15", 9),
+ v1_16("1_16", 10),
+ v1_17("1_17", 11),
+ v1_18("1_18", 12),
+ UNKNOWN("UNKNOWN", 99999),
+ ;
+
+ private int index;
+ private String name;
+
+ MinecraftVersion(String name, int index)
+ {
+ this.name = name;
+ this.index = index;
+ }
+
+ /**
+ * Checks if this version is newer than the other version.
+ *
+ * @param other The other version to check against.
+ * @return True if this version is newer than the other version.
+ */
+ public boolean isNewerThan(final MinecraftVersion other)
+ {
+ return this.index > other.index;
+ }
+
+ /**
+ * Checks if this version is older than the other version.
+ *
+ * @param other The other version to check against.
+ * @return True if this version is older than the other version.
+ */
+ public boolean isOlderThan(final MinecraftVersion other)
+ {
+ return this.index < other.index;
+ }
+
+ public static MinecraftVersion get(final String versionName)
+ {
+ if (versionName == null)
+ return null;
+ for (final MinecraftVersion mcVersion : MinecraftVersion.values())
+ if (versionName.contains(mcVersion.name))
+ return mcVersion;
+ return MinecraftVersion.UNKNOWN;
+ }
+}