From 51854fa1500621300c559502c2b123d499128d58 Mon Sep 17 00:00:00 2001 From: Pim van der Loos Date: Sun, 19 Apr 2020 12:09:48 +0200 Subject: [PATCH] Update NBT system to support recent Paper builds - Overhauled the way armor values are retrieved so that this plugin is compatible with Paper 178+. This new method should also be a bit more robust against future changes. - Reformatted the code some. - Fixed FlyDurabilityHandler. It used to check Player#isFlying. This checks if the player if flying using creative flight, not using an elytra. Player#isGliding actually checks if the player is flying using an elytra. --- pom.xml | 30 +- .../armoredElytra/ArmoredElytra.java | 138 +++--- .../handlers/CommandHandler.java | 31 +- .../armoredElytra/handlers/EventHandlers.java | 201 ++++----- .../handlers/FlyDurabilityHandler.java | 15 +- .../armoredElytra/handlers/Uninstaller.java | 21 +- .../nbtEditor/GetArmorValue.java | 6 - .../nbtEditor/GetArmorValueNew.java | 33 -- .../nbtEditor/GetArmorValueOld.java | 26 -- .../armoredElytra/nbtEditor/NBTEditor.java | 416 +++++++++++------- 10 files changed, 495 insertions(+), 422 deletions(-) delete mode 100644 src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValue.java delete mode 100644 src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValueNew.java delete mode 100644 src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValueOld.java diff --git a/pom.xml b/pom.xml index 8c9e4aa..8c407f5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 nl.pim16aap2 ArmoredElytra @@ -11,10 +11,14 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + CodeMC - https://repo.codemc.org/repository/maven-public + https://repo.codemc.org/repository/maven-public/ + + jitpack.io https://jitpack.io @@ -22,17 +26,19 @@ + org.spigotmc - spigot - 1.14.2-R0.1-SNAPSHOT + spigot-api + 1.15.1-R0.1-SNAPSHOT provided + - com.github.tr7zw - Item-NBT-API - master-SNAPSHOT + org.spigotmc + spigot + 1.15.1-R0.1-SNAPSHOT provided @@ -43,7 +49,7 @@ 1.5 compile - + @@ -124,7 +126,7 @@ - + diff --git a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java index ae077b9..4f9c3e4 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java @@ -1,19 +1,5 @@ package nl.pim16aap2.armoredElytra; -import java.util.EnumMap; -import java.util.Map; -import java.util.Objects; -import java.util.logging.Level; -import java.util.regex.Pattern; - -import org.bstats.bukkit.Metrics; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; -import org.bukkit.event.Listener; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.java.JavaPlugin; - import nl.pim16aap2.armoredElytra.handlers.CommandHandler; import nl.pim16aap2.armoredElytra.handlers.EventHandlers; import nl.pim16aap2.armoredElytra.handlers.FlyDurabilityHandler; @@ -25,6 +11,19 @@ import nl.pim16aap2.armoredElytra.util.ArmorTierName; import nl.pim16aap2.armoredElytra.util.ConfigLoader; import nl.pim16aap2.armoredElytra.util.Messages; import nl.pim16aap2.armoredElytra.util.Update; +import org.bstats.bukkit.Metrics; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.EnumMap; +import java.util.Map; +import java.util.Objects; +import java.util.logging.Level; +import java.util.regex.Pattern; // TODO: Use this for NBT stuff: https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/ // TODO: Figure out if the config really does read the list of enchantments accurately. A bug report with a customized config seemed to load the default settings... @@ -33,11 +32,11 @@ import nl.pim16aap2.armoredElytra.util.Update; public class ArmoredElytra extends JavaPlugin implements Listener { - private NBTEditor nbtEditor; + private static ArmoredElytra instance; private Messages messages; private ConfigLoader config; -// private String leatherName, ironName, goldName, chainName, diamondName; + // private String leatherName, ironName, goldName, chainName, diamondName; private final Map armorTierNames = new EnumMap(ArmorTier.class); private String elytraReceivedMessage; private String usageDeniedMessage; @@ -48,6 +47,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener @Override public void onEnable() { + instance = this; config = new ConfigLoader(this); messages = new Messages(this); readMessages(); @@ -56,60 +56,68 @@ public class ArmoredElytra extends JavaPlugin implements Listener if (config.checkForUpdates()) { // Check for updates in a new thread, so the server won't hang when it cannot contact the update servers. - final Thread thread = new Thread(() -> - { - final ArmoredElytra plugin = getPlugin(); - final Update update = new Update(278437, plugin); - final String latestVersion = update.getLatestVersion(); - - if (latestVersion == null) - plugin.myLogger(Level.WARNING, "Encountered problem contacting update servers! Please check manually! The error above does not affect the plugin!"); - else + final Thread thread = new Thread( + () -> { - final String thisVersion = plugin.getDescription().getVersion(); - // Check if this is the latest version or not. - final int updateStatus = update.versionCompare(latestVersion, thisVersion); + final ArmoredElytra plugin = getPlugin(); + final Update update = new Update(278437, plugin); + final String latestVersion = update.getLatestVersion(); - if (updateStatus > 0) - { - // Load the loginHandler to show messages to the user when they join. - Bukkit.getPluginManager().registerEvents(new LoginHandler(plugin, "The Armored Elytra plugin is out of date!"), plugin); - plugin.myLogger(Level.INFO, "Plugin out of date! You are using version " + thisVersion + " but the latest version is version " + latestVersion + "!"); - plugin.setUpToDate(false); - } + if (latestVersion == null) + plugin.myLogger(Level.WARNING, + "Encountered problem contacting update servers! Please check manually! The error above does not affect the plugin!"); else { - plugin.setUpToDate(true); - plugin.myLogger(Level.INFO, "You seem to be using the latest version of this plugin!"); + final String thisVersion = plugin.getDescription().getVersion(); + // Check if this is the latest version or not. + final int updateStatus = update.versionCompare(latestVersion, thisVersion); + + if (updateStatus > 0) + { + // Load the loginHandler to show messages to the user when they join. + Bukkit.getPluginManager() + .registerEvents(new LoginHandler(plugin, "The Armored Elytra plugin is out of date!"), + plugin); + plugin.myLogger(Level.INFO, "Plugin out of date! You are using version " + thisVersion + + " but the latest version is version " + latestVersion + "!"); + plugin.setUpToDate(false); + } + else + { + plugin.setUpToDate(true); + plugin.myLogger(Level.INFO, "You seem to be using the latest version of this plugin!"); + } } - } - }); + }); thread.start(); } else - myLogger(Level.INFO, "Plugin update checking not enabled! You will not receive any messages about new updates for this plugin. Please consider turning this on in the config."); + myLogger(Level.INFO, + "Plugin update checking not enabled! You will not receive any messages about new updates for this plugin. Please consider turning this on in the config."); if (config.allowStats()) { myLogger(Level.INFO, "Enabling stats! Thanks, it really helps!"); - @SuppressWarnings("unused") - final - Metrics metrics = new Metrics(this); + @SuppressWarnings("unused") final Metrics metrics = new Metrics(this); } else // Y u do dis? :( - myLogger(Level.INFO, "Stats disabled, not loading stats :(... Please consider enabling it! I am a simple man, seeing higher user numbers helps me stay motivated!"); + myLogger(Level.INFO, + "Stats disabled, not loading stats :(... Please consider enabling it! I am a simple man, seeing higher user numbers helps me stay motivated!"); // Load the files for the correct version of Minecraft. if (compatibleMCVer()) { - Bukkit.getPluginManager().registerEvents(new EventHandlers(this, nbtEditor, is1_9), this); - getCommand("ArmoredElytra").setExecutor(new CommandHandler(this, nbtEditor)); + Bukkit.getPluginManager().registerEvents(new EventHandlers(this, is1_9), this); + getCommand("ArmoredElytra").setExecutor(new CommandHandler(this)); } else { - Bukkit.getPluginManager().registerEvents(new LoginHandler(this, "The Armored Elytra plugin failed to start correctly! Please send the startup log to pim16aap2!"), this); - myLogger(Level.WARNING, "Plugin failed to load! Either your version isn't supported or something went horribly wrong! Please contact pim16aap2!"); + Bukkit.getPluginManager().registerEvents(new LoginHandler(this, + "The Armored Elytra plugin failed to start correctly! Please send the startup log to pim16aap2!"), + this); + myLogger(Level.WARNING, + "Plugin failed to load! Either your version isn't supported or something went horribly wrong! Please contact pim16aap2!"); return; } @@ -119,11 +127,11 @@ public class ArmoredElytra extends JavaPlugin implements Listener // Check if the user wants to disable durability penalty for flying with an armored elytra. if (config.noFlightDurability()) { - Bukkit.getPluginManager().registerEvents(new FlyDurabilityHandler(nbtEditor), this); - myLogger(Level.INFO, "Durability penalty for flying enabled!"); + Bukkit.getPluginManager().registerEvents(new FlyDurabilityHandler(), this); + myLogger(Level.INFO, "Durability penalty for flying disabled!"); } else - myLogger(Level.INFO, "Durability penalty for flying disabled!"); + myLogger(Level.INFO, "Durability penalty for flying enabled!"); // Log all allowed enchantments. myLogger(Level.INFO, ("Allowed enchantments:")); @@ -133,7 +141,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener else { myLogger(Level.WARNING, "Plugin in uninstall mode!"); - Bukkit.getPluginManager().registerEvents(new Uninstaller(this, nbtEditor), this); + Bukkit.getPluginManager().registerEvents(new Uninstaller(this), this); } } @@ -167,19 +175,22 @@ public class ArmoredElytra extends JavaPlugin implements Listener getColorCodedStringFromConfig("TIER.SHORT.Diamond"))); // Change the string to null if it says "NONE". - usageDeniedMessage = (Objects.equals(usageDeniedMessage, new String("NONE")) ? null : usageDeniedMessage ); - elytraReceivedMessage = (Objects.equals(elytraReceivedMessage, new String("NONE")) ? null : elytraReceivedMessage); - elytraLore = (Objects.equals(elytraLore, new String("NONE")) ? null : elytraLore ); + usageDeniedMessage = (Objects.equals(usageDeniedMessage, new String("NONE")) ? null : usageDeniedMessage); + elytraReceivedMessage = (Objects.equals(elytraReceivedMessage, new String("NONE")) ? null : + elytraReceivedMessage); + elytraLore = (Objects.equals(elytraLore, new String("NONE")) ? null : elytraLore); } public boolean playerHasCraftPerm(Player player, ArmorTier armorTier) { - return getConfigLoader().bypassCraftPerm() || player.hasPermission("armoredelytra.craft." + ArmorTier.getName(armorTier)); + return getConfigLoader().bypassCraftPerm() || + player.hasPermission("armoredelytra.craft." + ArmorTier.getName(armorTier)); } public boolean playerHasWearPerm(Player player, ArmorTier armorTier) { - return getConfigLoader().bypassWearPerm() || player.hasPermission("armoredelytra.wear." + ArmorTier.getName(armorTier)); + return getConfigLoader().bypassWearPerm() || + player.hasPermission("armoredelytra.wear." + ArmorTier.getName(armorTier)); } // Returns true if this is the latest version of this plugin. @@ -244,7 +255,8 @@ public class ArmoredElytra extends JavaPlugin implements Listener return string; } final ArmorTierName tierName = armorTierNames.get(armorTier); - return ARMOR_TIER_SHORT.matcher(ARMOR_TIER.matcher(string).replaceAll(ChatColor.stripColor(tierName.getLongName()))) + return ARMOR_TIER_SHORT + .matcher(ARMOR_TIER.matcher(string).replaceAll(ChatColor.stripColor(tierName.getLongName()))) .replaceAll(ChatColor.stripColor(tierName.getShortName())); } @@ -271,8 +283,12 @@ public class ArmoredElytra extends JavaPlugin implements Listener // Check + initialize for the correct version of Minecraft. public boolean compatibleMCVer() { - nbtEditor = new NBTEditor(this); - return nbtEditor.succes(); + return NBTEditor.success(); + } + + public static ArmoredElytra getInstance() + { + return instance; } public String getElytraLore() @@ -294,4 +310,4 @@ public class ArmoredElytra extends JavaPlugin implements Listener { this.upToDate = upToDate; } -} \ No newline at end of file +} diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java index 437fa1e..6839111 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java @@ -1,7 +1,8 @@ package nl.pim16aap2.armoredElytra.handlers; -import java.util.logging.Level; - +import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; +import nl.pim16aap2.armoredElytra.util.ArmorTier; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -11,19 +12,15 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import nl.pim16aap2.armoredElytra.ArmoredElytra; -import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; -import nl.pim16aap2.armoredElytra.util.ArmorTier; +import java.util.logging.Level; public class CommandHandler implements CommandExecutor { private final ArmoredElytra plugin; - private final NBTEditor nbtEditor; - public CommandHandler(ArmoredElytra plugin, NBTEditor nbtEditor) + public CommandHandler(ArmoredElytra plugin) { - this.plugin = plugin; - this.nbtEditor = nbtEditor; + this.plugin = plugin; } @Override @@ -52,7 +49,7 @@ public class CommandHandler implements CommandExecutor if (args.length == 1) { receiver = player; - tier = args[0]; + tier = args[0]; } else { @@ -77,11 +74,13 @@ public class CommandHandler implements CommandExecutor if (allowed) { plugin.elytraReceivedMessage(receiver, armorTier); - newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, plugin.getConfigLoader().unbreakable()); + newElytra = NBTEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, + plugin.getConfigLoader().unbreakable()); plugin.giveArmoredElytraToPlayer(receiver, newElytra); } else - plugin.messagePlayer(player, plugin.fillInArmorTierInStringNoColor(plugin.getMyMessages().getString("MESSAGES.NoGivePermission"), armorTier)); + plugin.messagePlayer(player, plugin.fillInArmorTierInStringNoColor( + plugin.getMyMessages().getString("MESSAGES.NoGivePermission"), armorTier)); return true; } } @@ -96,7 +95,7 @@ public class CommandHandler implements CommandExecutor if (args.length == 2) { ItemStack newElytra = null; - String tier = args[1]; + final String tier = args[1]; if (Bukkit.getPlayer(args[0]) != null) { player = Bukkit.getPlayer(args[0]); @@ -106,9 +105,11 @@ public class CommandHandler implements CommandExecutor return false; plugin.elytraReceivedMessage(player, armorTier); - newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, plugin.getConfigLoader().unbreakable()); + newElytra = NBTEditor.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())); + plugin.myLogger(Level.INFO, ("Giving an armored elytra of the " + ArmorTier.getArmor(armorTier) + + " armor tier to player " + player.getName())); return true; } plugin.myLogger(Level.INFO, ("Player " + args[1] + " not found!")); diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java index 8faf18f..b1ebf54 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java @@ -1,12 +1,16 @@ package nl.pim16aap2.armoredElytra.handlers; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; -import java.util.function.Consumer; -import java.util.logging.Level; - +import com.codingforcookies.armorequip.ArmorEquipEvent; +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; +import nl.pim16aap2.armoredElytra.util.Util; +import nl.pim16aap2.armoredElytra.util.XMaterial; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; @@ -22,31 +26,23 @@ import org.bukkit.inventory.AnvilInventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.EnchantmentStorageMeta; -import com.codingforcookies.armorequip.ArmorEquipEvent; -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; -import nl.pim16aap2.armoredElytra.util.Util; -import nl.pim16aap2.armoredElytra.util.XMaterial; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.function.Consumer; +import java.util.logging.Level; public class EventHandlers implements Listener { - private final NBTEditor nbtEditor; private final ArmoredElytra plugin; private final Consumer cleanAnvilInventory; private final Consumer moveChestplateToInventory; - public EventHandlers(ArmoredElytra plugin, NBTEditor nbtEditor, boolean is1_9) + public EventHandlers(ArmoredElytra plugin, boolean is1_9) { this.plugin = plugin; - this.nbtEditor = nbtEditor; initializeArmorEquipEvent(); if (is1_9) { @@ -164,21 +160,21 @@ public class EventHandlers implements Listener if (protVal0 != 0 && protVal1 != 0 && protVal0 != protVal1) switch (protVal0) { - case 1: - combined.remove(Enchantment.PROTECTION_ENVIRONMENTAL); - break; - case 2: - combined.remove(Enchantment.PROTECTION_EXPLOSIONS); - break; - case 4: - combined.remove(Enchantment.PROTECTION_FALL); - break; - case 8: - combined.remove(Enchantment.PROTECTION_FIRE); - break; - case 16: - combined.remove(Enchantment.PROTECTION_PROJECTILE); - break; + case 1: + combined.remove(Enchantment.PROTECTION_ENVIRONMENTAL); + break; + case 2: + combined.remove(Enchantment.PROTECTION_EXPLOSIONS); + break; + case 4: + combined.remove(Enchantment.PROTECTION_FALL); + break; + case 8: + combined.remove(Enchantment.PROTECTION_FIRE); + break; + case 16: + combined.remove(Enchantment.PROTECTION_PROJECTILE); + break; } } return combined; @@ -258,7 +254,7 @@ public class EventHandlers implements Listener if (Util.isChestPlate(matTwo)) return Action.CREATE; - ArmorTier tier = nbtEditor.getArmorTier(itemOne); + ArmorTier tier = NBTEditor.getArmorTier(itemOne); if (tier != ArmorTier.NONE) { @@ -272,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 (NBTEditor.getArmorTier(itemTwo) == tier) return Action.COMBINE; // If the armored elytra is not of the leather tier, but itemTwo is leather, @@ -309,47 +305,47 @@ public class EventHandlers implements Listener { Action action = isValidInput(itemA, itemB); ArmorTier newTier = ArmorTier.NONE; - ArmorTier curTier = nbtEditor.getArmorTier(itemA); + ArmorTier curTier = NBTEditor.getArmorTier(itemA); short durability = 0; Map enchantments = itemA.getEnchantments(); enchantments = fixEnchantments(enchantments); switch (action) { - case REPAIR: - newTier = curTier; - durability = repairItem(itemA.getDurability(), itemB); - break; - case COMBINE: - newTier = curTier; - durability = (short) (-itemA.getType().getMaxDurability() - itemA.getDurability() - - itemB.getDurability()); - durability = durability < 0 ? 0 : durability; - enchantments = combineEnchantments(enchantments, itemB.getEnchantments()); - break; - case CREATE: - newTier = Util.armorToTier(itemB.getType()); - durability = 0; - enchantments = combineEnchantments(enchantments, itemB.getEnchantments()); - break; - case ENCHANT: - EnchantmentStorageMeta meta = (EnchantmentStorageMeta) itemB.getItemMeta(); - newTier = curTier; - durability = itemA.getDurability(); - // If there aren't any illegal enchantments on the book, continue as normal. - // Otherwise... Block. - if (verifyEnchantments(meta.getStoredEnchants()) != meta.getStoredEnchants().size()) - { - enchantments = combineEnchantments(enchantments, meta.getStoredEnchants()); + case REPAIR: + newTier = curTier; + durability = repairItem(itemA.getDurability(), itemB); break; - } - //$FALL-THROUGH$ - case BLOCK: - event.setResult(null); - player.updateInventory(); - //$FALL-THROUGH$ - case NONE: - return; + case COMBINE: + newTier = curTier; + durability = (short) (-itemA.getType().getMaxDurability() - itemA.getDurability() + - itemB.getDurability()); + durability = durability < 0 ? 0 : durability; + enchantments = combineEnchantments(enchantments, itemB.getEnchantments()); + break; + case CREATE: + newTier = Util.armorToTier(itemB.getType()); + durability = 0; + enchantments = combineEnchantments(enchantments, itemB.getEnchantments()); + break; + case ENCHANT: + EnchantmentStorageMeta meta = (EnchantmentStorageMeta) itemB.getItemMeta(); + newTier = curTier; + durability = itemA.getDurability(); + // If there aren't any illegal enchantments on the book, continue as normal. + // Otherwise... Block. + if (verifyEnchantments(meta.getStoredEnchants()) != meta.getStoredEnchants().size()) + { + enchantments = combineEnchantments(enchantments, meta.getStoredEnchants()); + break; + } + //$FALL-THROUGH$ + case BLOCK: + event.setResult(null); + player.updateInventory(); + //$FALL-THROUGH$ + case NONE: + return; } if (plugin.playerHasCraftPerm(player, newTier)) @@ -359,14 +355,14 @@ public class EventHandlers implements Listener result.addUnsafeEnchantments(enchantments); result.setDurability(durability); - result = nbtEditor.addArmorNBTTags(result, newTier, plugin.getConfigLoader().unbreakable()); + result = NBTEditor.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) + NBTEditor.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); @@ -386,7 +382,6 @@ public class EventHandlers implements Listener return; AnvilInventory anvilInventory; - // Try to cast inventory being used in the event to an anvil inventory. // This will throw a ClassCastException when a CraftInventoryCustom is used. try @@ -399,6 +394,7 @@ public class EventHandlers implements Listener // custom inventories as they are usually used for GUI's). plugin.debugMsg(Level.WARNING, "Could not cast inventory to anvilInventory for player " + player.getName() + "! Armored Elytras cannot be crafted!"); + exception.printStackTrace(); return; } @@ -407,7 +403,8 @@ 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 = NBTEditor.getArmorTier(anvilInventory.getItem(2)); + // If there's an armored elytra in the final slot... if (armortier != ArmorTier.NONE && plugin.playerHasCraftPerm(player, armortier)) { @@ -415,8 +412,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, + ItemStack result = NBTEditor.addArmorNBTTags(anvilInventory.getItem(2), armortier, plugin.getConfigLoader().unbreakable()); + // Give the result to the player and clear the anvil's inventory. if (e.isShiftClick()) { @@ -427,6 +425,7 @@ public class EventHandlers implements Listener } else player.setItemOnCursor(result); + // Clean the anvil's inventory after transferring the items. cleanAnvilInventory.accept(anvilInventory); player.updateInventory(); @@ -465,15 +464,15 @@ public class EventHandlers implements Listener if (p.getInventory().getChestplate() == null) return; - if (nbtEditor.getArmorTier(p.getInventory().getChestplate()) == ArmorTier.NONE) + if (NBTEditor.getArmorTier(p.getInventory().getChestplate()) == ArmorTier.NONE) return; ItemStack elytra = p.getInventory().getChestplate(); DamageCause cause = e.getCause(); // The elytra doesn't receive any damage for these causes: - if (cause != DamageCause.DROWNING && cause != DamageCause.STARVATION && cause != DamageCause.SUFFOCATION && - cause != DamageCause.SUICIDE && cause != DamageCause.FLY_INTO_WALL && cause != DamageCause.POISON) + if (cause != DamageCause.DROWNING && cause != DamageCause.STARVATION && cause != DamageCause.SUFFOCATION && + cause != DamageCause.SUICIDE && cause != DamageCause.FLY_INTO_WALL && cause != DamageCause.POISON) { int durability = p.getInventory().getChestplate().getDurability(); int maxDurability = p.getInventory().getChestplate().getType().getMaxDurability(); @@ -510,27 +509,31 @@ public class EventHandlers implements Listener @EventHandler public void onEquip(ArmorEquipEvent e) { - if (!e.getType().equals(ArmorType.CHESTPLATE) || - e.getNewArmorPiece() == null || - !e.getNewArmorPiece().getType().equals(Material.ELYTRA) ) + if (e.getMethod().equals(ArmorEquipEvent.EquipMethod.DEATH) || + e.getMethod().equals(ArmorEquipEvent.EquipMethod.BROKE)) return; - ArmorTier armorTier = nbtEditor.getArmorTier(e.getNewArmorPiece()); + if (!e.getType().equals(ArmorType.CHESTPLATE) || + e.getNewArmorPiece() == null || + !e.getNewArmorPiece().getType().equals(Material.ELYTRA)) + return; + + ArmorTier armorTier = NBTEditor.getArmorTier(e.getNewArmorPiece()); AllowedToWearEnum allowed = isAllowedToWear(e.getNewArmorPiece(), e.getPlayer(), armorTier); - switch(allowed) + switch (allowed) { - case ALLOWED: - break; - case BROKEN: - plugin.messagePlayer(e.getPlayer(), plugin.getMyMessages().getString("MESSAGES.RepairNeeded")); - e.setCancelled(true); - break; - case NOPERMISSION: - plugin.usageDeniedMessage(e.getPlayer(), armorTier); - e.setCancelled(true); - break; - default: - break; + case ALLOWED: + break; + case BROKEN: + plugin.messagePlayer(e.getPlayer(), plugin.getMyMessages().getString("MESSAGES.RepairNeeded")); + e.setCancelled(true); + break; + case NOPERMISSION: + plugin.usageDeniedMessage(e.getPlayer(), armorTier); + e.setCancelled(true); + break; + default: + break; } } -} \ No newline at end of file +} diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java index b875d5e..8f67210 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/FlyDurabilityHandler.java @@ -1,20 +1,16 @@ package nl.pim16aap2.armoredElytra.handlers; +import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; +import nl.pim16aap2.armoredElytra.util.ArmorTier; import org.bukkit.Material; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerItemDamageEvent; -import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; -import nl.pim16aap2.armoredElytra.util.ArmorTier; - public class FlyDurabilityHandler implements Listener { - private final NBTEditor nbtEditor; - - public FlyDurabilityHandler(NBTEditor nbtEditor) + public FlyDurabilityHandler() { - this.nbtEditor = nbtEditor; } // Do not decrease elytra durability while flying. This also cancels durability decrease when @@ -24,10 +20,11 @@ public class FlyDurabilityHandler implements Listener { if (e.getItem().getType() != Material.ELYTRA) return; - if (!e.getPlayer().isFlying()) + + if (!e.getPlayer().isGliding()) return; - if (nbtEditor.getArmorTier(e.getItem()) != ArmorTier.NONE) + if (NBTEditor.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 4f9fc68..ec7ec53 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/Uninstaller.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/Uninstaller.java @@ -1,5 +1,8 @@ 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; import org.bukkit.entity.Player; @@ -12,19 +15,13 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitRunnable; -import nl.pim16aap2.armoredElytra.ArmoredElytra; -import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; -import nl.pim16aap2.armoredElytra.util.ArmorTier; - public class Uninstaller implements Listener { private final ArmoredElytra plugin; - private final NBTEditor nbtEditor; - public Uninstaller(ArmoredElytra plugin, NBTEditor nbtEditor) + public Uninstaller(ArmoredElytra plugin) { - this.plugin = plugin; - this.nbtEditor = nbtEditor; + this.plugin = plugin; } public int removeArmoredElytras(Inventory inv) @@ -33,7 +30,7 @@ public class Uninstaller implements Listener for (ItemStack is : inv) if (is != null) if (is.getType() == Material.ELYTRA) - if (nbtEditor.getArmorTier(is) != ArmorTier.NONE) + if (NBTEditor.getArmorTier(is) != ArmorTier.NONE) { inv.remove(is); ++count; @@ -54,7 +51,8 @@ public class Uninstaller implements Listener Inventory inv = event.getInventory(); int removed = removeArmoredElytras(inv); if (removed != 0) - plugin.messagePlayer((Player) (event.getPlayer()), ChatColor.RED, "Removed " + removed + " armored elytras from your chest!"); + plugin.messagePlayer((Player) (event.getPlayer()), ChatColor.RED, + "Removed " + removed + " armored elytras from your chest!"); } }.runTaskLater(plugin, 20); } @@ -71,7 +69,8 @@ public class Uninstaller implements Listener Inventory inv = event.getPlayer().getInventory(); int removed = removeArmoredElytras(inv); if (removed != 0) - plugin.messagePlayer(event.getPlayer(), ChatColor.RED, "Removed " + removed + " armored elytras from your inventory!"); + plugin.messagePlayer(event.getPlayer(), ChatColor.RED, + "Removed " + removed + " armored elytras from your inventory!"); } }.runTaskLater(plugin, 20); } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValue.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValue.java deleted file mode 100644 index f54066c..0000000 --- a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValue.java +++ /dev/null @@ -1,6 +0,0 @@ -package nl.pim16aap2.armoredElytra.nbtEditor; - -public interface GetArmorValue -{ - public int armorValueFromNBTString(String nbtString); -} diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValueNew.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValueNew.java deleted file mode 100644 index 91b8bdc..0000000 --- a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValueNew.java +++ /dev/null @@ -1,33 +0,0 @@ -package nl.pim16aap2.armoredElytra.nbtEditor; - -import java.util.logging.Level; - -import nl.pim16aap2.armoredElytra.ArmoredElytra; - -public class GetArmorValueNew implements GetArmorValue -{ - private final ArmoredElytra plugin; - - public GetArmorValueNew(ArmoredElytra plugin) - { - this.plugin = plugin; - } - - @Override - public int armorValueFromNBTString(String nbtString) - { - int pos = nbtString.indexOf(",Slot:\"chest\",AttributeName:\"generic.armor\""); - if (pos > 0) - try - { - String stringAtPos = nbtString.substring(pos - 4, pos - 1); - return (int) Double.parseDouble(stringAtPos); - } - catch (Exception e) - { - plugin.myLogger(Level.INFO, "Failed to obtain armor value from NBT!"); - return 0; - } - return 0; - } -} diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValueOld.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValueOld.java deleted file mode 100644 index a2bad40..0000000 --- a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/GetArmorValueOld.java +++ /dev/null @@ -1,26 +0,0 @@ -package nl.pim16aap2.armoredElytra.nbtEditor; - -import nl.pim16aap2.armoredElytra.ArmoredElytra; - -public class GetArmorValueOld implements GetArmorValue -{ - private final ArmoredElytra plugin; - - public GetArmorValueOld(ArmoredElytra plugin) - { - this.plugin = plugin; - } - - @Override - public int armorValueFromNBTString(String nbtString) - { - int pos = nbtString.indexOf(",Slot:\"chest\",AttributeName:\"generic.armor\""); - if (pos > 0) - { - pos--; - String stringAtPos = nbtString.substring(pos, pos + 1); - return Integer.parseInt(stringAtPos); - } - return 0; - } -} diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java index 361daff..b98bf00 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java @@ -1,149 +1,132 @@ package nl.pim16aap2.armoredElytra.nbtEditor; +import nl.pim16aap2.armoredElytra.ArmoredElytra; +import nl.pim16aap2.armoredElytra.util.ArmorTier; +import org.bukkit.Bukkit; +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 org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import nl.pim16aap2.armoredElytra.ArmoredElytra; -import nl.pim16aap2.armoredElytra.util.ArmorTier; +import java.util.function.Function; +import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class NBTEditor { - private final ArmoredElytra plugin; - private final String NMSbase; - private final String CraftBase; - private Method asNMSCopy; - private Method asBukkitCopy; - private Class NMSItemStack; - private Class CraftItemStack; + 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 Class NBTTagCompound; - private Class NBTTagList; - private Class NBTBase; - private Class NBTTagString; - private Class NBTTagByte; - private Class NBTTagInt; + private static Method asNMSCopy; + private static Method asBukkitCopy; + private static Class NMSItemStack; + private static Class CraftItemStack; - private Method hasTag; - private Method getTag; + 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 Method addCompound; + private static Method hasTag; + private static Method getTag; - private Method setTag; + private static Method addCompound; - private Method setCompoundByte; - private Method setCompoundTagList; + private static Method setTag; - private Constructor NBTTagStringCtor; - private Constructor NBTTagByteCtor; - private Constructor NBTTagIntCtor; + private static Method setCompoundByte; + private static Method setCompoundTagList; - private boolean success = false; - private GetArmorValue getArmorValue; + private static Method getCompoundTagList; + private static Method getTagListSize; + private static Method getTagListAtIndex; - public NBTEditor(ArmoredElytra plugin) + 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 { - this.plugin = plugin; - final String versionString = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; - NMSbase = "net.minecraft.server." + versionString + "."; - CraftBase = "org.bukkit.craftbukkit." + versionString + "."; - - constructNMSClasses(); - getTagReadingMethod(); - } - - private void getTagReadingMethod() - { - if (!success) - return; - - String version; - try - { - version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; - } - catch (final ArrayIndexOutOfBoundsException useAVersionMentionedInTheDescriptionPleaseException) - { + if (minecraftVersion == null) success = false; - return; - } - - // Old versions use the old format. It is assumed here that all versions from - // 1.13.2 on will use the new format. - // Spigot's 1.13.1 uses the old format, but 1.13.2 uses the new format. They - // share the same version number though. - if (version.equals("v1_9_R1") || version.equals("v1_9_R2") || version.equals("v1_10_R1") || - version.equals("v1_11_R1") || version.equals("v1_12_R1") || version.equals("v1_13_R1") || - version.equals("v1_13_R2") && Bukkit.getVersion().split(" ")[2].equals("1.13.1)")) - getArmorValue = new GetArmorValueOld(plugin); else - getArmorValue = new GetArmorValueNew(plugin); - } - - public boolean succes() - { - return success; - } - - private void constructNMSClasses() - { - try - { - 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"); - // Starting in 1.14, you also need to provide an int value when adding nbt tags. try { - addCompound = NBTTagList.getMethod("add", NBTBase); + // 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 (Exception e) + catch (NoSuchMethodException | SecurityException | ClassNotFoundException e) { - addCompound = NBTTagList.getMethod("add", int.class, NBTBase); + e.printStackTrace(); + success = false; } - - setCompoundTagList = NBTTagCompound.getMethod("set", String.class, NBTBase); - setCompoundByte = NBTTagCompound.getMethod("set", String.class, NBTBase); - - success = true; - } - catch (NoSuchMethodException | SecurityException | ClassNotFoundException e) - { - e.printStackTrace(); - success = false; - } } - private void addCompound(Object instance, Object nbtbase) + private static void addCompound(Object instance, Object nbtbase) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (addCompound.getParameterCount() == 2) @@ -153,7 +136,7 @@ public class NBTEditor } // Add armor to the supplied item, based on the armorTier. - public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable) + public static ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable) { try { @@ -161,15 +144,17 @@ public class NBTEditor int armorProtection = ArmorTier.getArmor(armorTier); int armorToughness = ArmorTier.getToughness(armorTier); - itemmeta.setDisplayName(plugin.getArmoredElytraName(armorTier)); - if (plugin.getElytraLore() != null) + itemmeta.setDisplayName(ArmoredElytra.getInstance().getArmoredElytraName(armorTier)); + if (ArmoredElytra.getInstance().getElytraLore() != null) itemmeta - .setLore(Arrays.asList(plugin.fillInArmorTierInStringNoColor(plugin.getElytraLore(), armorTier))); + .setLore(Arrays.asList(ArmoredElytra.getInstance().fillInArmorTierInStringNoColor( + ArmoredElytra.getInstance().getElytraLore(), armorTier))); + item.setItemMeta(itemmeta); Object nmsStack = asNMSCopy.invoke(null, item); Object compound = ((boolean) hasTag.invoke(nmsStack) ? getTag.invoke(nmsStack) : - NBTTagCompound.newInstance()); + 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")); @@ -196,60 +181,195 @@ public class NBTEditor setCompoundTagList.invoke(compound, "AttributeModifiers", modifiers); item = (ItemStack) asBukkitCopy.invoke(null, nmsStack); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) { - // TODO: Log this or something. Pretty serious issue for a plugin based entirely - // on this code. e.printStackTrace(); } return item; } - // Get the armor tier of the supplied item. - public ArmorTier getArmorTier(ItemStack 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. + */ + 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 { - if (item == null) - return ArmorTier.NONE; - if (item.getType() != Material.ELYTRA) - return ArmorTier.NONE; + return (int) Double.parseDouble(getArmorAmount(string, pattern_findAmount_double, pattern_getDouble)); + } + catch (NumberFormatException e) + { + e.printStackTrace(); + } + return 0; + } - // Get the NBT tags from the item. + /** + * 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; - switch (getArmorValue.armorValueFromNBTString(compound.toString())) + Object modifiers = getCompoundTagList.invoke(compound, "AttributeModifiers", 10); // Number 10 = Compound. + int size = (int) getTagListSize.invoke(modifiers); + + + for (int idx = 0; idx < size; ++idx) { - case 3: - return ArmorTier.LEATHER; - case 5: - return ArmorTier.GOLD; - case 6: - return ArmorTier.IRON; - case 8: - return ArmorTier.DIAMOND; - default: - return ArmorTier.NONE; +// 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; + } } + return ArmorTier.NONE; } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); - return null; + return ArmorTier.NONE; } } - private Class getNMSClass(String name) throws ClassNotFoundException + private static Class getNMSClass(String name) + throws ClassNotFoundException { return Class.forName(NMSbase + name); } - private Class getCraftClass(String name) throws ClassNotFoundException + 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) + { + 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; + } + + 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; + } + } }