From 8eb6f094c84675c4b37a772d083719c3b6673ec5 Mon Sep 17 00:00:00 2001 From: Pim van der Loos Date: Sat, 20 Jan 2018 22:04:53 +0100 Subject: [PATCH] - Fixed "fake" enchantments being allowed on armored elytras (only 1 kind of protection enchantment can be active at the same time, now only 1 can be put on an AE). - Fixed invalid Armored Elytras showing up in the result slot. --- pom.xml | 2 +- .../armoredElytra/handlers/EventHandlers.java | 299 ++++++++++-------- .../armoredElytra/nms/NBTEditor_V1_10_R1.java | 6 +- .../armoredElytra/nms/NBTEditor_V1_11_R1.java | 6 +- .../armoredElytra/nms/NBTEditor_V1_12_R1.java | 6 +- .../armoredElytra/util/ConfigLoader.java | 18 +- src/main/resources/config.yml | 15 + src/main/resources/plugin.yml | 2 +- 8 files changed, 191 insertions(+), 163 deletions(-) diff --git a/pom.xml b/pom.xml index 8153d53..5238cb9 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 nl.pim16aap2 ArmoredElytra - 2.1-SNAPSHOT + 2.1.9-SNAPSHOT diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java index d8a04c7..38c4856 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java @@ -1,13 +1,17 @@ package nl.pim16aap2.armoredElytra.handlers; +import java.lang.reflect.Field; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.logging.Level; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_10_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_12_R1.inventory.CraftInventoryAnvil; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -17,12 +21,16 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryType; +import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.AnvilInventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.EnchantmentStorageMeta; import org.bukkit.scheduler.BukkitRunnable; +import net.minecraft.server.v1_12_R1.ContainerAnvil; +import net.minecraft.server.v1_12_R1.Container; +import net.minecraft.server.v1_12_R1.ContainerDispenser; import nl.pim16aap2.armoredElytra.ArmoredElytra; import nl.pim16aap2.armoredElytra.nms.NBTEditor; import nl.pim16aap2.armoredElytra.util.Action; @@ -65,12 +73,6 @@ public class EventHandlers implements Listener anvilInventory.getItem(2).setAmount(0); } - // Accessor for this.plugin - public ArmoredElytra getPlugin() - { - return this.plugin; - } - // Check if the enchantment is allowed on elytras. public boolean isAllowedEnchantment(Enchantment enchant) { @@ -93,12 +95,12 @@ public class EventHandlers implements Listener // Combine 2 maps of enchantments (and remove any invalid ones). public Map combineEnchantments(Map enchantments0, Map enchantments1) { - fixEnchantments(enchantments0); - Map combined = new HashMap(enchantments0); + enchantments0 = fixEnchantments(enchantments0); + Map combined = new HashMap(fixEnchantments(enchantments0)); if (enchantments1 != null) { - fixEnchantments(enchantments1); + enchantments1 = fixEnchantments(enchantments1); // Loop through the enchantments of item1. for (Map.Entry entry : enchantments1.entrySet()) { @@ -124,10 +126,54 @@ public class EventHandlers implements Listener else if (enchantLevel == null) combined.put(entry.getKey(), entry.getValue()); } + + // Get the protection enchantment rating for both enchantment sets. + int protVal0 = getProtectionEnchantmentsVal(enchantments0); + int protVal1 = getProtectionEnchantmentsVal(enchantments1); + + // If they have different + 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; + } + } } return combined; } + // Function that returns which/how many protection enchantments there are. + public int getProtectionEnchantmentsVal(Map enchantments) + { + int ret = 0; + if (enchantments.containsKey(Enchantment.PROTECTION_ENVIRONMENTAL)) + ret += 1; + if ( enchantments.containsKey(Enchantment.PROTECTION_EXPLOSIONS)) + ret += 2; + if ( enchantments.containsKey(Enchantment.PROTECTION_FALL)) + ret += 4; + if ( enchantments.containsKey(Enchantment.PROTECTION_FIRE)) + ret += 8; + if ( enchantments.containsKey(Enchantment.PROTECTION_PROJECTILE)) + ret += 16; + return ret; + } + // Repair an Armored Elytra public short repairItem(short curDur, ItemStack repairItem) { @@ -149,40 +195,26 @@ public class EventHandlers implements Listener int newDurability = (int) (curDur - (maxDurability * mult)); return (short) (newDurability <= 0 ? 0 : newDurability); } - - // Check if there aren't any disallowed enchantments / curses in the map. - public boolean verifyEnchants(Map enchantments) - { - for (Map.Entry entry : enchantments.entrySet()) - { - // If it's a cursed enchantment, while it's not allowed, it's false. - if (isCursedEnchantment(entry.getKey()) && !cursesAllowed) - return false; - // If the enchantment is not allowed, it's false. - else if (!isAllowedEnchantment(entry.getKey())) - return false; - } - return true; - } - + // Remove any disallowed enchantments / curses in the map. public Map fixEnchantments(Map enchantments) { Map ret = new HashMap(enchantments); for (Map.Entry entry : enchantments.entrySet()) - if (isAllowedEnchantment(entry.getKey()) == false && (cursesAllowed && isCursedEnchantment(entry.getKey())) == false) + // If it is not an allowed enchantment OR a curse while it's not allowed + if (!isAllowedEnchantment(entry.getKey()) || (!cursesAllowed && isCursedEnchantment(entry.getKey()))) ret.remove(entry.getKey()); return ret; } - - // Fix enchantments on an item. - public ItemStack fixEnchantments(ItemStack item) + + // Verify there aren't any disallowed enchantments / curses in the map. + public boolean verifyEnchantments(Map enchantments) { - ItemStack result = item.clone(); - for (Map.Entry entry : result.getEnchantments().entrySet()) - if (isAllowedEnchantment(entry.getKey()) == false && (cursesAllowed && isCursedEnchantment(entry.getKey())) == false) - result.removeEnchantment(entry.getKey()); - return result; + for (Map.Entry entry : enchantments.entrySet()) + // If it is not an allowed enchantment OR a curse while it's not allowed + if (!isAllowedEnchantment(entry.getKey()) || (!cursesAllowed && isCursedEnchantment(entry.getKey()))) + return false; + return true; } // Get the armor tier from a chest plate. @@ -248,6 +280,9 @@ public class EventHandlers implements Listener itemTwo = tmp; } + if (itemOne.getType() != Material.ELYTRA) + return Action.NONE; + Material matTwo = itemTwo.getType(); // If the elytra is to be combined with chest armor... @@ -272,13 +307,96 @@ public class EventHandlers implements Listener // If the armored elytra is not of the leather tier, but itemTwo is leather, // Pick the block action, as that would repair the elytra by default (vanilla). - if (tier != ArmorTier.LEATHER && matTwo == Material.LEATHER) + // Also block Armored Elytra + Elytra. + if (tier != ArmorTier.LEATHER && matTwo == Material.LEATHER || matTwo == Material.ELYTRA) return Action.BLOCK; } return Action.NONE; } - // Handle the anvil related parts. + // Handle all anvil related stuff for this plugin. + @EventHandler + public void onAnvilInventoryOpen(PrepareAnvilEvent event) + { + Player p = (Player) event.getView().getPlayer(); + + ItemStack itemA = event.getInventory().getItem(0); + ItemStack itemB = event.getInventory().getItem(1); + ItemStack result = null; + + if (itemA != null && itemB != null) + { + // If itemB is the elytra, while itemA isn't, switch itemA and itemB. + if (itemB.getType() == Material.ELYTRA && itemA.getType() != Material.ELYTRA) + { + result = itemA; + itemA = itemB; + itemB = result; + result = null; + } + } + + // Check if there are items in both input slots. + if (itemA != null && itemB != null) + { + Action action = isValidInput(itemA, itemB); + ArmorTier newTier = ArmorTier.NONE; + 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 = 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())) + { + enchantments = combineEnchantments(enchantments, meta.getStoredEnchants()); + break; + } + case BLOCK: + event.setResult(null); + p.updateInventory(); + case NONE: + return; + } + + result = new ItemStack(Material.ELYTRA, 1); + if (enchantments != null) + result.addUnsafeEnchantments(enchantments); + result.setDurability(durability); + result = nbtEditor.addArmorNBTTags(result, newTier, plugin.getConfigLoader().getBool("unbreakable")); + event.setResult(result); + } + + // Check if either itemA or itemB is unoccupied. + if (itemA == null || itemB == null) + // If Item2 is occupied despite itemA or itemB not being occupied. + event.setResult(null); + p.updateInventory(); + } + + // Let the player take items out of the anvil. @EventHandler public void onInventoryClick(InventoryClickEvent e) { @@ -303,120 +421,27 @@ public class EventHandlers implements Listener return; } - int slot = e.getRawSlot(); // Get slot + int slot = e.getRawSlot(); if (slot == 2 && anvilInventory.getItem(0) != null && anvilInventory.getItem(1) != null && anvilInventory.getItem(2) != null) { + ArmorTier armortier = nbtEditor.getArmorTier(anvilInventory.getItem(2)); // If there's an armored elytra in the final slot... - if (anvilInventory.getItem(2).getType() == Material.ELYTRA && nbtEditor.getArmorTier(anvilInventory.getItem(2)) != ArmorTier.NONE) + if (armortier != ArmorTier.NONE) { - Action action = isValidInput(anvilInventory.getItem(0), anvilInventory.getItem(1)); - // If there is no action to be taken, take no action... - if (action == Action.NONE) - return; - // If the action is to block... Well, Block! (get rid of the end result!) - // Also check if there are any disallowed enchantments/curses on the result, delete the result. - if (action == Action.BLOCK) - { - // Send message to player that the recipe is invalid, as clearing the inventory doesn't work properly. - plugin.messagePlayer(p, ChatColor.RED, "Invalid recipe!"); - anvilInventory.setItem(2, null); - anvilInventory.clear(2); - p.updateInventory(); - p.updateInventory(); - p.updateInventory(); - return; - } - + // Create a new armored elytra and give that one to the player instead of the 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().getBool("unbreakable")); // Give the result to the player and clear the anvil's inventory. if (e.isShiftClick()) - p.getInventory().addItem(fixEnchantments(anvilInventory.getItem(2))); + p.getInventory().addItem(result); else - p.setItemOnCursor(fixEnchantments(anvilInventory.getItem(2))); + p.setItemOnCursor(result); // Clean the anvil's inventory after transferring the items. cleanAnvil(anvilInventory); return; } } - - new BukkitRunnable() - { - @Override - public void run() - { - ItemStack itemA = anvilInventory.getItem(0); - ItemStack itemB = anvilInventory.getItem(1); - ItemStack result = null; - if (itemA != null && itemB != null) - { - // If itemB is the elytra, while itemA isn't, switch itemA and itemB. - if (itemB.getType() == Material.ELYTRA && itemA.getType() != Material.ELYTRA) - { - result = itemA; - itemA = itemB; - itemB = result; - result = null; - } - } - - // Check if there are items in both input slots. - if (itemA != null && itemB != null) - { - Action action = isValidInput(itemA, itemB); - ArmorTier newTier = ArmorTier.NONE; - 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 ENCHANT: - EnchantmentStorageMeta meta = (EnchantmentStorageMeta) itemB.getItemMeta(); - newTier = curTier; - durability = itemA.getDurability(); - enchantments = combineEnchantments(enchantments, meta.getStoredEnchants()); - 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 = armorToTier(itemB.getType()); - durability = 0; - enchantments = combineEnchantments(enchantments, itemB.getEnchantments()); - break; - case BLOCK: - if (anvilInventory.getItem(2) != null) - anvilInventory.getItem(2).setAmount(0); - p.updateInventory(); - case NONE: - return; - } - - result = new ItemStack(Material.ELYTRA, 1); - if (enchantments != null) - result.addUnsafeEnchantments(enchantments); - result.setDurability(durability); - result = nbtEditor.addArmorNBTTags(result, newTier, plugin.getConfigLoader().getBool("unbreakable")); - anvilInventory.setItem(2, result); - } - - // Check if either itemA or itemB is unoccupied. - if (itemA == null || itemB == null) - // If Item2 is occupied despite Item1 not being occupied. - if (anvilInventory.getItem(2) != null) - // Then set the amount to 0. - anvilInventory.getItem(2).setAmount(0); - p.updateInventory(); - } - }.runTaskLater(this.plugin, 1); } } } diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_10_R1.java b/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_10_R1.java index fb43b75..5d61ed8 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_10_R1.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_10_R1.java @@ -17,9 +17,9 @@ import nl.pim16aap2.armoredElytra.util.ArmorTier; public class NBTEditor_V1_10_R1 implements NBTEditor { - String elytraName; - String elytraLore; - ArmoredElytra plugin; + private String elytraName; + private String elytraLore; + private ArmoredElytra plugin; // Get the names and lores for every tier of armor. public NBTEditor_V1_10_R1(String elytraName, String elytraLore, ArmoredElytra plugin) diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_11_R1.java b/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_11_R1.java index 31d55a3..4e367ef 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_11_R1.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_11_R1.java @@ -18,9 +18,9 @@ import nl.pim16aap2.armoredElytra.util.ArmorTier; public class NBTEditor_V1_11_R1 implements NBTEditor { - String elytraName; - String elytraLore; - ArmoredElytra plugin; + private String elytraName; + private String elytraLore; + private ArmoredElytra plugin; // Get the names and lores for every tier of armor. public NBTEditor_V1_11_R1(String elytraName, String elytraLore, ArmoredElytra plugin) diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_12_R1.java b/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_12_R1.java index 1088502..d99e43c 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_12_R1.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/nms/NBTEditor_V1_12_R1.java @@ -17,9 +17,9 @@ import nl.pim16aap2.armoredElytra.util.ArmorTier; public class NBTEditor_V1_12_R1 implements NBTEditor { - String elytraName; - String elytraLore; - ArmoredElytra plugin; + private String elytraName; + private String elytraLore; + private ArmoredElytra plugin; // Get the names and lores for every tier of armor. public NBTEditor_V1_12_R1(String elytraName, String elytraLore, ArmoredElytra plugin) diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java b/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java index 92ee12a..4543126 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/ConfigLoader.java @@ -137,14 +137,12 @@ public class ConfigLoader { File dataFolder = plugin.getDataFolder(); if (!dataFolder.exists()) - { dataFolder.mkdir(); - } + File saveTo = new File(plugin.getDataFolder(), "config.yml"); if (!saveTo.exists()) - { saveTo.createNewFile(); - } else + else { saveTo.delete(); saveTo.createNewFile(); @@ -159,7 +157,7 @@ public class ConfigLoader pw.close(); } catch (IOException e) { - Bukkit.getLogger().log(Level.SEVERE, "Could not save config.yml! Please contact the author and attach the following code:"); + Bukkit.getLogger().log(Level.SEVERE, "Could not save config.yml! Please contact pim16aap2 and show him the following code:"); e.printStackTrace(); } } @@ -167,42 +165,32 @@ public class ConfigLoader public Integer getInt(String path) { for (ConfigOption configOption : configOptionsList) - { if (configOption.getName().equals(path)) return configOption.getInt(); - } return null; } public Boolean getBool(String path) { for (ConfigOption configOption : configOptionsList) - { if (configOption.getName().equals(path)) return configOption.getBool(); - } return null; } public String getString(String path) { for (ConfigOption configOption : configOptionsList) - { if (configOption.getName().equals(path)) return configOption.getString(); - } return null; } public List getStringList(String path) { for (ConfigOption configOption : configOptionsList) - { if (configOption.getName().equals(path)) - { return configOption.getStringList(); - } - } return null; } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index c313c93..50c562d 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -9,6 +9,21 @@ goldRepair: 5 ironRepair: 4 diamondsRepair: 3 +# Name colors for every tier. +leatherColor: +goldColor: +chainColor: +ironColor: +diamondColor: + +# Name for every tier: +leather: +gold: +chain: +iron: +diamond: + + # Will curses (vanishing, binding) be transferred when creating armored elytras? allowCurses: true diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c1104d4..8f42fdf 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ArmoredElytra main: nl.pim16aap2.armoredElytra.ArmoredElytra -version: 2.1 +version: 2.1.9 author: Pim commands: ArmoredElytra: