diff --git a/src/main/java/com/codingforcookies/armorequip/ArmorEquipEvent.java b/src/main/java/com/codingforcookies/armorequip/ArmorEquipEvent.java
new file mode 100644
index 0000000..30720ba
--- /dev/null
+++ b/src/main/java/com/codingforcookies/armorequip/ArmorEquipEvent.java
@@ -0,0 +1,163 @@
+package com.codingforcookies.armorequip;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * @author Arnah
+ * @since Jul 30, 2015
+ */
+public final class ArmorEquipEvent extends PlayerEvent implements Cancellable
+{
+ private static final HandlerList handlers = new HandlerList();
+ private boolean cancel = false;
+ private final EquipMethod equipType;
+ private final ArmorType type;
+ private ItemStack oldArmorPiece, newArmorPiece;
+
+ /**
+ * Constructor for the ArmorEquipEvent.
+ *
+ * @param player The player who put on / removed the armor.
+ * @param type The ArmorType of the armor added
+ * @param oldArmorPiece The ItemStack of the armor removed.
+ * @param newArmorPiece The ItemStack of the armor added.
+ */
+ public ArmorEquipEvent(final Player player, final EquipMethod equipType, final ArmorType type,
+ final ItemStack oldArmorPiece, final ItemStack newArmorPiece)
+ {
+ super(player);
+ this.equipType = equipType;
+ this.type = type;
+ this.oldArmorPiece = oldArmorPiece;
+ this.newArmorPiece = newArmorPiece;
+ }
+
+ /**
+ * Gets a list of handlers handling this event.
+ *
+ * @return A list of handlers handling this event.
+ */
+ public final static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+
+ /**
+ * Gets a list of handlers handling this event.
+ *
+ * @return A list of handlers handling this event.
+ */
+ @Override
+ public final HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ /**
+ * Sets if this event should be cancelled.
+ *
+ * @param cancel If this event should be cancelled.
+ */
+ @Override
+ public final void setCancelled(final boolean cancel)
+ {
+ this.cancel = cancel;
+ }
+
+ /**
+ * Gets if this event is cancelled.
+ *
+ * @return If this event is cancelled
+ */
+ @Override
+ public final boolean isCancelled()
+ {
+ return cancel;
+ }
+
+ public final ArmorType getType()
+ {
+ return type;
+ }
+
+ /**
+ * Returns the last equipped armor piece, could be a piece of armor,
+ * {@link Material#Air}, or null.
+ */
+ public final ItemStack getOldArmorPiece()
+ {
+ return oldArmorPiece;
+ }
+
+ public final void setOldArmorPiece(final ItemStack oldArmorPiece)
+ {
+ this.oldArmorPiece = oldArmorPiece;
+ }
+
+ /**
+ * Returns the newly equipped armor, could be a piece of armor,
+ * {@link Material#Air}, or null.
+ */
+ public final ItemStack getNewArmorPiece()
+ {
+ return newArmorPiece;
+ }
+
+ public final void setNewArmorPiece(final ItemStack newArmorPiece)
+ {
+ this.newArmorPiece = newArmorPiece;
+ }
+
+ /**
+ * Gets the method used to either equip or unequip an armor piece.
+ */
+ public EquipMethod getMethod()
+ {
+ return equipType;
+ }
+
+ public enum EquipMethod
+ {// These have got to be the worst documentations ever.
+ /**
+ * When you shift click an armor piece to equip or unequip
+ */
+ SHIFT_CLICK,
+ /**
+ * When you drag and drop the item to equip or unequip
+ */
+ DRAG,
+ /**
+ * When you manually equip or unequip the item. Use to be DRAG
+ */
+ PICK_DROP,
+ /**
+ * When you right click an armor piece in the hotbar without the inventory open
+ * to equip.
+ */
+ HOTBAR,
+ /**
+ * When you press the hotbar slot number while hovering over the armor slot to
+ * equip or unequip
+ */
+ HOTBAR_SWAP,
+ /**
+ * When in range of a dispenser that shoots an armor piece to equip.
+ * Requires the spigot version to have
+ * {@link org.bukkit.event.block.BlockDispenseArmorEvent} implemented.
+ */
+ DISPENSER,
+ /**
+ * When an armor piece is removed due to it losing all durability.
+ */
+ BROKE,
+ /**
+ * When you die causing all armor to unequip
+ */
+ DEATH,;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/codingforcookies/armorequip/ArmorListener.java b/src/main/java/com/codingforcookies/armorequip/ArmorListener.java
new file mode 100644
index 0000000..f37eda3
--- /dev/null
+++ b/src/main/java/com/codingforcookies/armorequip/ArmorListener.java
@@ -0,0 +1,265 @@
+package com.codingforcookies.armorequip;
+
+import java.util.List;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event.Result;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.entity.PlayerDeathEvent;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryDragEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.event.inventory.InventoryType.SlotType;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.event.player.PlayerItemBreakEvent;
+import org.bukkit.inventory.ItemStack;
+
+import com.codingforcookies.armorequip.ArmorEquipEvent.EquipMethod;
+
+/**
+ * @author Arnah
+ * @since Jul 30, 2015
+ */
+public class ArmorListener implements Listener
+{
+ private final List blockedMaterials;
+
+ public ArmorListener(List blockedMaterials)
+ {
+ this.blockedMaterials = blockedMaterials;
+ }
+
+ @EventHandler
+ public final void inventoryClick(final InventoryClickEvent e)
+ {
+ boolean shift = false, numberkey = false;
+ if (e.isCancelled())
+ return;
+ if (e.getAction() == InventoryAction.NOTHING)
+ return;// Why does this get called if nothing happens??
+ if (e.getClick().equals(ClickType.SHIFT_LEFT) || e.getClick().equals(ClickType.SHIFT_RIGHT))
+ shift = true;
+ if (e.getClick().equals(ClickType.NUMBER_KEY))
+ numberkey = true;
+ if (e.getSlotType() != SlotType.ARMOR && e.getSlotType() != SlotType.QUICKBAR &&
+ e.getSlotType() != SlotType.CONTAINER)
+ return;
+ if (e.getClickedInventory() != null && !e.getClickedInventory().getType().equals(InventoryType.PLAYER))
+ return;
+ if (!e.getInventory().getType().equals(InventoryType.CRAFTING) &&
+ !e.getInventory().getType().equals(InventoryType.PLAYER))
+ return;
+ if (!(e.getWhoClicked() instanceof Player))
+ return;
+ ArmorType newArmorType = ArmorType.matchType(shift ? e.getCurrentItem() : e.getCursor());
+ if (!shift && newArmorType != null && e.getRawSlot() != newArmorType.getSlot())
+ // Used for drag and drop checking to make sure you aren't trying to place a
+ // helmet in the boots slot.
+ return;
+ if (shift)
+ {
+ newArmorType = ArmorType.matchType(e.getCurrentItem());
+ if (newArmorType != null)
+ {
+ boolean equipping = true;
+ if (e.getRawSlot() == newArmorType.getSlot())
+ equipping = false;
+ if (newArmorType.equals(ArmorType.HELMET) &&
+ (equipping ? isAirOrNull(e.getWhoClicked().getInventory().getHelmet()) :
+ !isAirOrNull(e.getWhoClicked().getInventory().getHelmet())) ||
+ newArmorType.equals(ArmorType.CHESTPLATE) && (equipping ?
+ isAirOrNull(e.getWhoClicked().getInventory().getChestplate()) :
+ !isAirOrNull(e.getWhoClicked().getInventory().getChestplate())) ||
+ newArmorType.equals(ArmorType.LEGGINGS) && (equipping ?
+ isAirOrNull(e.getWhoClicked().getInventory().getLeggings()) :
+ !isAirOrNull(e.getWhoClicked().getInventory().getLeggings())) ||
+ newArmorType.equals(ArmorType.BOOTS) && (equipping ?
+ isAirOrNull(e.getWhoClicked().getInventory().getBoots()) :
+ !isAirOrNull(e.getWhoClicked().getInventory().getBoots())))
+ {
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(),
+ EquipMethod.SHIFT_CLICK, newArmorType,
+ equipping ? null : e.getCurrentItem(),
+ equipping ? e.getCurrentItem() : null);
+ Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled())
+ e.setCancelled(true);
+ }
+ }
+ }
+ else
+ {
+ ItemStack newArmorPiece = e.getCursor();
+ ItemStack oldArmorPiece = e.getCurrentItem();
+ if (numberkey)
+ if (e.getClickedInventory().getType().equals(InventoryType.PLAYER))
+ { // Prevents shit in the 2by2 crafting
+ // e.getClickedInventory() == The players inventory
+ // e.getHotBarButton() == key people are pressing to equip or unequip the item
+ // to or from.
+ // e.getRawSlot() == The slot the item is going to.
+ // e.getSlot() == Armor slot, can't use e.getRawSlot() as that gives a hotbar
+ // slot ;-;
+ ItemStack hotbarItem = e.getClickedInventory().getItem(e.getHotbarButton());
+ if (!isAirOrNull(hotbarItem))
+ { // Equipping
+ newArmorType = ArmorType.matchType(hotbarItem);
+ newArmorPiece = hotbarItem;
+ oldArmorPiece = e.getClickedInventory().getItem(e.getSlot());
+ }
+ else
+ // Unequipping
+ newArmorType = ArmorType
+ .matchType(!isAirOrNull(e.getCurrentItem()) ? e.getCurrentItem() : e.getCursor());
+ }
+ else
+ {
+ if (isAirOrNull(e.getCursor()) && !isAirOrNull(e.getCurrentItem()))
+ // unequip with no new item going into the slot.
+ newArmorType = ArmorType.matchType(e.getCurrentItem());
+ // e.getCurrentItem() == Unequip
+ // e.getCursor() == Equip
+ // newArmorType = ArmorType.matchType(!isAirOrNull(e.getCurrentItem()) ?
+ // e.getCurrentItem() : e.getCursor());
+ }
+ if (newArmorType != null && e.getRawSlot() == newArmorType.getSlot())
+ {
+ EquipMethod method = EquipMethod.PICK_DROP;
+ if (e.getAction().equals(InventoryAction.HOTBAR_SWAP) || numberkey)
+ method = EquipMethod.HOTBAR_SWAP;
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(), method, newArmorType,
+ oldArmorPiece, newArmorPiece);
+ Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled())
+ e.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler
+ public void playerInteractEvent(PlayerInteractEvent e)
+ {
+ if (e.getAction() == Action.PHYSICAL)
+ return;
+ if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK)
+ {
+ final Player player = e.getPlayer();
+ if (e.getClickedBlock() != null && e.getAction() == Action.RIGHT_CLICK_BLOCK)
+ { // Having both of these checks is useless, might as well do it though.
+ // Some blocks have actions when you right click them which stops the client
+ // from equipping the armor in hand.
+ Material mat = e.getClickedBlock().getType();
+ for (String s : blockedMaterials)
+ if (mat.name().equalsIgnoreCase(s))
+ return;
+ }
+ ArmorType newArmorType = ArmorType.matchType(e.getItem());
+ if (newArmorType != null)
+ {
+ if (newArmorType.equals(ArmorType.HELMET) && isAirOrNull(e.getPlayer().getInventory().getHelmet()) ||
+ newArmorType
+ .equals(ArmorType.CHESTPLATE) && isAirOrNull(e.getPlayer().getInventory().getChestplate()) ||
+ newArmorType
+ .equals(ArmorType.LEGGINGS) && isAirOrNull(e.getPlayer().getInventory().getLeggings()) ||
+ newArmorType.equals(ArmorType.BOOTS) && isAirOrNull(e.getPlayer().getInventory().getBoots()))
+ {
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(e.getPlayer(), EquipMethod.HOTBAR,
+ ArmorType.matchType(e.getItem()), null,
+ e.getItem());
+ Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled())
+ {
+ e.setCancelled(true);
+ player.updateInventory();
+ }
+ }
+ }
+ }
+ }
+
+ @EventHandler
+ public void inventoryDrag(InventoryDragEvent event)
+ {
+ // getType() seems to always be even.
+ // Old Cursor gives the item you are equipping
+ // Raw slot is the ArmorType slot
+ // Can't replace armor using this method making getCursor() useless.
+ ArmorType type = ArmorType.matchType(event.getOldCursor());
+ if (event.getRawSlots().isEmpty())
+ return;// Idk if this will ever happen
+ if (type != null && type.getSlot() == event.getRawSlots().stream().findFirst().orElse(0))
+ {
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) event.getWhoClicked(), EquipMethod.DRAG,
+ type, null, event.getOldCursor());
+ Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled())
+ {
+ event.setResult(Result.DENY);
+ event.setCancelled(true);
+ }
+ }
+ // Debug shit
+ /*
+ * System.out.println("Slots: " + event.getInventorySlots().toString());
+ * System.out.println("Raw Slots: " + event.getRawSlots().toString());
+ * if(event.getCursor() != null){ System.out.println("Cursor: " +
+ * event.getCursor().getType().name()); } if(event.getOldCursor() != null){
+ * System.out.println("OldCursor: " + event.getOldCursor().getType().name()); }
+ * System.out.println("Type: " + event.getType().name());
+ */
+ }
+
+ @EventHandler
+ public void itemBreakEvent(PlayerItemBreakEvent e)
+ {
+ ArmorType type = ArmorType.matchType(e.getBrokenItem());
+ if (type != null)
+ {
+ Player p = e.getPlayer();
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, EquipMethod.BROKE, type, e.getBrokenItem(), null);
+ Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled())
+ {
+ ItemStack i = e.getBrokenItem().clone();
+ i.setAmount(1);
+ i.setDurability((short) (i.getDurability() - 1));
+ if (type.equals(ArmorType.HELMET))
+ p.getInventory().setHelmet(i);
+ else if (type.equals(ArmorType.CHESTPLATE))
+ p.getInventory().setChestplate(i);
+ else if (type.equals(ArmorType.LEGGINGS))
+ p.getInventory().setLeggings(i);
+ else if (type.equals(ArmorType.BOOTS))
+ p.getInventory().setBoots(i);
+ }
+ }
+ }
+
+ @EventHandler
+ public void playerDeathEvent(PlayerDeathEvent e)
+ {
+ Player p = e.getEntity();
+ for (ItemStack oldArmor : p.getInventory().getArmorContents())
+ if (!isAirOrNull(oldArmor))
+ {
+ ArmorType type = ArmorType.matchType(oldArmor);
+ Bukkit.getServer().getPluginManager().callEvent(new ArmorEquipEvent(p, EquipMethod.DEATH,
+ type, oldArmor, null));
+ // No way to cancel a death event.
+ }
+ }
+
+ /**
+ * A utility method to support versions that use null or air ItemStacks.
+ */
+ private boolean isAirOrNull(ItemStack item)
+ {
+ return item == null || item.getType().equals(Material.AIR);
+ }
+}
diff --git a/src/main/java/com/codingforcookies/armorequip/ArmorType.java b/src/main/java/com/codingforcookies/armorequip/ArmorType.java
new file mode 100644
index 0000000..99d7653
--- /dev/null
+++ b/src/main/java/com/codingforcookies/armorequip/ArmorType.java
@@ -0,0 +1,53 @@
+package com.codingforcookies.armorequip;
+
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * @author Arnah
+ * @since Jul 30, 2015
+ */
+public enum ArmorType
+{
+ HELMET (5),
+ CHESTPLATE (6),
+ LEGGINGS (7),
+ BOOTS (8);
+
+ private final int slot;
+
+ ArmorType(int slot)
+ {
+ this.slot = slot;
+ }
+
+ /**
+ * Attempts to match the ArmorType for the specified ItemStack.
+ *
+ * @param itemStack The ItemStack to parse the type of.
+ * @return The parsed ArmorType. (null if none were found.)
+ */
+ public final static ArmorType matchType(final ItemStack itemStack)
+ {
+ if (itemStack == null || itemStack.getType().equals(Material.AIR))
+ return null;
+ if (itemStack.getType().equals(Material.ELYTRA))
+ return CHESTPLATE;
+ String type = itemStack.getType().name();
+ if (type.endsWith("_HELMET") || type.endsWith("_SKULL"))
+ return HELMET;
+ else if (type.endsWith("_CHESTPLATE"))
+ return CHESTPLATE;
+ else if (type.endsWith("_LEGGINGS"))
+ return LEGGINGS;
+ else if (type.endsWith("_BOOTS"))
+ return BOOTS;
+ else
+ return null;
+ }
+
+ public int getSlot()
+ {
+ return slot;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/codingforcookies/armorequip/DispenserArmorListener.java b/src/main/java/com/codingforcookies/armorequip/DispenserArmorListener.java
new file mode 100644
index 0000000..587c8f1
--- /dev/null
+++ b/src/main/java/com/codingforcookies/armorequip/DispenserArmorListener.java
@@ -0,0 +1,30 @@
+package com.codingforcookies.armorequip;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockDispenseArmorEvent;
+
+/**
+ * @author Arnah
+ * @since Feb 08, 2019
+ */
+public class DispenserArmorListener implements Listener
+{
+ @EventHandler
+ public void dispenseArmorEvent(BlockDispenseArmorEvent event)
+ {
+ ArmorType type = ArmorType.matchType(event.getItem());
+ if (type != null)
+ if (event.getTargetEntity() instanceof Player)
+ {
+ Player p = (Player) event.getTargetEntity();
+ ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, ArmorEquipEvent.EquipMethod.DISPENSER, type,
+ null, event.getItem());
+ Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
+ if (armorEquipEvent.isCancelled())
+ event.setCancelled(true);
+ }
+ }
+}
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java
index e03a3fd..ae077b9 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java
@@ -1,7 +1,10 @@
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;
@@ -18,6 +21,7 @@ import nl.pim16aap2.armoredElytra.handlers.LoginHandler;
import nl.pim16aap2.armoredElytra.handlers.Uninstaller;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
+import nl.pim16aap2.armoredElytra.util.ArmorTierName;
import nl.pim16aap2.armoredElytra.util.ConfigLoader;
import nl.pim16aap2.armoredElytra.util.Messages;
import nl.pim16aap2.armoredElytra.util.Update;
@@ -33,7 +37,8 @@ public class ArmoredElytra extends JavaPlugin implements Listener
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;
private String elytraLore;
@@ -137,18 +142,29 @@ public class ArmoredElytra extends JavaPlugin implements Listener
return messages;
}
+ private final String getColorCodedStringFromConfig(final String configEntry)
+ {
+ return getMyMessages().getString(configEntry).replaceAll("&((?i)[0-9a-fk-or])", "\u00A7$1");
+ }
+
private void readMessages()
{
// Replace color codes by the corresponding colors.
- usageDeniedMessage = getMyMessages().getString("MESSAGES.UsageDenied" ).replaceAll("&((?i)[0-9a-fk-or])", "\u00A7$1");
- elytraReceivedMessage = getMyMessages().getString("MESSAGES.ElytraReceived").replaceAll("&((?i)[0-9a-fk-or])", "\u00A7$1");
- elytraLore = getMyMessages().getString("MESSAGES.Lore" ).replaceAll("&((?i)[0-9a-fk-or])", "\u00A7$1");
+ usageDeniedMessage = getColorCodedStringFromConfig("MESSAGES.UsageDenied");
+ elytraReceivedMessage = getColorCodedStringFromConfig("MESSAGES.ElytraReceived");
+ elytraLore = getColorCodedStringFromConfig("MESSAGES.Lore");
- leatherName = getMyMessages().getString("TIER.Leather" ).replaceAll("&((?i)[0-9a-fk-or])", "\u00A7$1");
- goldName = getMyMessages().getString("TIER.Gold" ).replaceAll("&((?i)[0-9a-fk-or])", "\u00A7$1");
- chainName = getMyMessages().getString("TIER.Chain" ).replaceAll("&((?i)[0-9a-fk-or])", "\u00A7$1");
- ironName = getMyMessages().getString("TIER.Iron" ).replaceAll("&((?i)[0-9a-fk-or])", "\u00A7$1");
- diamondName = getMyMessages().getString("TIER.Diamond" ).replaceAll("&((?i)[0-9a-fk-or])", "\u00A7$1");
+ armorTierNames.put(ArmorTier.NONE, new ArmorTierName("NONE", "NONE")); // Shouldn't be used.
+ armorTierNames.put(ArmorTier.LEATHER, new ArmorTierName(getColorCodedStringFromConfig("TIER.Leather"),
+ getColorCodedStringFromConfig("TIER.SHORT.Leather")));
+ armorTierNames.put(ArmorTier.GOLD, new ArmorTierName(getColorCodedStringFromConfig("TIER.Gold"),
+ getColorCodedStringFromConfig("TIER.SHORT.Gold")));
+ armorTierNames.put(ArmorTier.CHAIN, new ArmorTierName(getColorCodedStringFromConfig("TIER.Chain"),
+ getColorCodedStringFromConfig("TIER.SHORT.Chain")));
+ armorTierNames.put(ArmorTier.IRON, new ArmorTierName(getColorCodedStringFromConfig("TIER.Iron"),
+ getColorCodedStringFromConfig("TIER.SHORT.Iron")));
+ armorTierNames.put(ArmorTier.DIAMOND, new ArmorTierName(getColorCodedStringFromConfig("TIER.Diamond"),
+ getColorCodedStringFromConfig("TIER.SHORT.Diamond")));
// Change the string to null if it says "NONE".
usageDeniedMessage = (Objects.equals(usageDeniedMessage, new String("NONE")) ? null : usageDeniedMessage );
@@ -216,10 +232,20 @@ public class ArmoredElytra extends JavaPlugin implements Listener
}
}
+ private static final Pattern ARMOR_TIER = Pattern.compile("%ARMOR_TIER%");
+ private static final Pattern ARMOR_TIER_SHORT = Pattern.compile("%ARMOR_TIER_SHORT%");
+
// Replace %ARMOR_TIER% by the name of that armor tier in a string, but strip %ARMOR_TIER% of its color.
public String fillInArmorTierInStringNoColor(String string, ArmorTier armorTier)
{
- return string.replace("%ARMOR_TIER%", ChatColor.stripColor(getArmoredElytrName(armorTier)));
+ if (armorTier == null)
+ {
+ getLogger().log(Level.INFO, "ArmorTier was null! Failed to obtain proper string!");
+ return string;
+ }
+ final ArmorTierName tierName = armorTierNames.get(armorTier);
+ return ARMOR_TIER_SHORT.matcher(ARMOR_TIER.matcher(string).replaceAll(ChatColor.stripColor(tierName.getLongName())))
+ .replaceAll(ChatColor.stripColor(tierName.getShortName()));
}
// Print a string to the log.
@@ -254,30 +280,14 @@ public class ArmoredElytra extends JavaPlugin implements Listener
return elytraLore;
}
- public String getArmoredElytrName(ArmorTier tier)
+ public String getArmoredElytraName(ArmorTier tier)
{
- String ret;
- switch(tier)
+ if (tier == null)
{
- case LEATHER:
- ret = leatherName;
- break;
- case GOLD:
- ret = goldName;
- break;
- case CHAIN:
- ret = chainName;
- break;
- case IRON:
- ret = ironName;
- break;
- case DIAMOND:
- ret = diamondName;
- break;
- default:
- ret = "NONE";
+ getLogger().log(Level.INFO, "ArmorTier was null! Failed to obtain proper string!");
+ return "NULL";
}
- return ret;
+ return armorTierNames.get(tier).getLongName();
}
public void setUpToDate(boolean upToDate)
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java
index 02b4b6e..437fa1e 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java
@@ -48,6 +48,7 @@ public class CommandHandler implements CommandExecutor
String tier = null;
Player receiver;
boolean allowed = false;
+
if (args.length == 1)
{
receiver = player;
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java
index c7f38bb..fd04ad4 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java
@@ -277,8 +277,9 @@ 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).
- // Also block Armored Elytra + Elytra.
- if (tier != ArmorTier.LEATHER && matTwo == Material.LEATHER || matTwo == Material.ELYTRA)
+ // Also block Armored Elytra + Elytra and Elytra + Membrane
+ if (tier != ArmorTier.LEATHER && matTwo == Material.LEATHER || matTwo == Material.ELYTRA ||
+ matTwo.equals(XMaterial.PHANTOM_MEMBRANE.parseMaterial()))
return Action.BLOCK;
}
return Action.NONE;
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java
index e69617e..361daff 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java
@@ -66,7 +66,7 @@ public class NBTEditor
String version;
try
{
- version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
+ version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
}
catch (final ArrayIndexOutOfBoundsException useAVersionMentionedInTheDescriptionPleaseException)
{
@@ -74,9 +74,11 @@ public class NBTEditor
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") ||
+ // 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);
@@ -98,24 +100,27 @@ public class NBTEditor
getTag = NMSItemStack.getMethod("getTag");
CraftItemStack = getCraftClass("inventory.CraftItemStack");
- asNMSCopy = CraftItemStack.getMethod("asNMSCopy", ItemStack.class);
- asBukkitCopy = CraftItemStack.getMethod("asBukkitCopy", NMSItemStack);
+ asNMSCopy = CraftItemStack.getMethod("asNMSCopy", ItemStack.class);
+ asBukkitCopy = CraftItemStack.getMethod("asBukkitCopy", NMSItemStack);
NBTBase = getNMSClass("NBTBase");
- NBTTagString = getNMSClass("NBTTagString");
- NBTTagStringCtor = NBTTagString.getConstructor(String.class);
+ NBTTagString = getNMSClass("NBTTagString");
+ NBTTagStringCtor = NBTTagString.getDeclaredConstructor(String.class);
+ NBTTagStringCtor.setAccessible(true);
- NBTTagByte = getNMSClass("NBTTagByte");
- NBTTagByteCtor = NBTTagByte.getConstructor(byte.class);
+ NBTTagByte = getNMSClass("NBTTagByte");
+ NBTTagByteCtor = NBTTagByte.getDeclaredConstructor(byte.class);
+ NBTTagByteCtor.setAccessible(true);
- NBTTagInt = getNMSClass("NBTTagInt");
- NBTTagIntCtor = NBTTagInt.getConstructor(int.class);
+ NBTTagInt = getNMSClass("NBTTagInt");
+ NBTTagIntCtor = NBTTagInt.getDeclaredConstructor(int.class);
+ NBTTagIntCtor.setAccessible(true);
NBTTagCompound = getNMSClass("NBTTagCompound");
- setTag = NBTTagCompound.getMethod("set", String.class, NBTBase);
+ setTag = NBTTagCompound.getMethod("set", String.class, NBTBase);
- NBTTagList = getNMSClass("NBTTagList");
+ NBTTagList = getNMSClass("NBTTagList");
// Starting in 1.14, you also need to provide an int value when adding nbt tags.
try
{
@@ -127,7 +132,7 @@ public class NBTEditor
}
setCompoundTagList = NBTTagCompound.getMethod("set", String.class, NBTBase);
- setCompoundByte = NBTTagCompound.getMethod("set", String.class, NBTBase);
+ setCompoundByte = NBTTagCompound.getMethod("set", String.class, NBTBase);
success = true;
}
@@ -138,7 +143,8 @@ public class NBTEditor
}
}
- private void addCompound(Object instance, Object nbtbase) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
+ private void addCompound(Object instance, Object nbtbase)
+ throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
if (addCompound.getParameterCount() == 2)
addCompound.invoke(instance, 0, nbtbase);
@@ -151,36 +157,38 @@ public class NBTEditor
{
try
{
- ItemMeta itemmeta = item.getItemMeta();
+ ItemMeta itemmeta = item.getItemMeta();
int armorProtection = ArmorTier.getArmor(armorTier);
- int armorToughness = ArmorTier.getToughness(armorTier);
+ int armorToughness = ArmorTier.getToughness(armorTier);
- itemmeta.setDisplayName(plugin.getArmoredElytrName(armorTier));
+ itemmeta.setDisplayName(plugin.getArmoredElytraName(armorTier));
if (plugin.getElytraLore() != null)
- itemmeta.setLore(Arrays.asList(plugin.fillInArmorTierInStringNoColor(plugin.getElytraLore(), armorTier)));
+ itemmeta
+ .setLore(Arrays.asList(plugin.fillInArmorTierInStringNoColor(plugin.getElytraLore(), armorTier)));
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"));
+ 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"));
+ 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)
@@ -192,7 +200,8 @@ public class NBTEditor
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e)
{
- // TODO: Log this or something. Pretty serious issue for a plugin based entirely on this code.
+ // TODO: Log this or something. Pretty serious issue for a plugin based entirely
+ // on this code.
e.printStackTrace();
}
return item;
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/ArmorTierName.java b/src/main/java/nl/pim16aap2/armoredElytra/util/ArmorTierName.java
new file mode 100644
index 0000000..ea397f9
--- /dev/null
+++ b/src/main/java/nl/pim16aap2/armoredElytra/util/ArmorTierName.java
@@ -0,0 +1,39 @@
+/**
+ *
+ */
+package nl.pim16aap2.armoredElytra.util;
+
+/**
+ *
+ * @author Pim
+ */
+public class ArmorTierName
+{
+ private String longName, shortName;
+
+ public ArmorTierName(final String longName, final String shortName)
+ {
+ this.longName = longName;
+ this.shortName = shortName;
+ }
+
+ public String getLongName()
+ {
+ return longName;
+ }
+
+ public String getShortName()
+ {
+ return shortName;
+ }
+
+ public void setLongName(final String longName)
+ {
+ this.longName = longName;
+ }
+
+ public void setShortName(final String shortName)
+ {
+ this.shortName = shortName;
+ }
+}
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/Messages.java b/src/main/java/nl/pim16aap2/armoredElytra/util/Messages.java
index de05f30..df4188f 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/util/Messages.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/util/Messages.java
@@ -56,7 +56,7 @@ public class Messages
while ((sCurrentLine = br.readLine()) != null)
{
// Ignore comments.
- if (sCurrentLine.startsWith("#"))
+ if (sCurrentLine.startsWith("#") || sCurrentLine.isEmpty())
continue;
String key, value;
String[] parts = sCurrentLine.split("=", 2);
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/XMaterial.java b/src/main/java/nl/pim16aap2/armoredElytra/util/XMaterial.java
index 42b25a4..09354c2 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/util/XMaterial.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/util/XMaterial.java
@@ -62,6 +62,7 @@ public enum XMaterial
GOLDEN_CHESTPLATE(0, "GOLD_CHESTPLATE"),
IRON_CHESTPLATE(0, ""),
LEATHER_CHESTPLATE(0, ""),
+ PHANTOM_MEMBRANE(0, "1.13"),
AIR(0, ""),
;
diff --git a/src/main/resources/en_US.txt b/src/main/resources/en_US.txt
index d616474..1761d36 100644
--- a/src/main/resources/en_US.txt
+++ b/src/main/resources/en_US.txt
@@ -4,15 +4,25 @@
# The format is "key=value" (without quotation marks). You can modify the values, but not the keys.
# Order doesn't matter and you can use comments if you so desire.
# Please do note that white space does matter! (so spaces at the end of lines, for example).
+# The long names (without 'SHORT') are the names the elytras will have.
TIER.Leather=&2Leather Armored Elytra
TIER.Gold=&EGolden Armored Elytra
TIER.Chain=&8Chain Armored Elytra
TIER.Iron=&7Iron Armored Elytra
TIER.Diamond=&BDiamond Armored Elytra
-MESSAGES.Lore=Elytra with %ARMOR_TIER% level protection
-MESSAGES.UsageDenied=You do not have the required permissions to wear %ARMOR_TIER%!
-MESSAGES.ElytraReceived=&2A(n) %ARMOR_TIER% has been bestowed upon you!
+TIER.SHORT.Leather=&2Leather
+TIER.SHORT.Gold=&EGold
+TIER.SHORT.Chain=&8Chain
+TIER.SHORT.Iron=&7Iron
+TIER.SHORT.Diamond=&BDiamond
MESSAGES.UninstallMode=&cPlugin in uninstall mode! New Armored Elytras are not allowed!
MESSAGES.UnsupportedTier=&cNot a supported armor tier! Try one of these: leather, gold, chain, iron, diamond.
-MESSAGES.NoGivePermission=&cYou do not have the required permission node to give %ARMOR_TIER%s.
-MESSAGES.RepairNeeded=&cYou cannot equip this elytra! Please repair it in an anvil first.
\ No newline at end of file
+MESSAGES.RepairNeeded=&cYou cannot equip this elytra! Please repair it in an anvil first.
+
+# The following messages support the following variables:
+# - %ARMOR_TIER% (refers to TIER.X (e.g. TIER.Leather))
+# - %ARMOR_TIER_SHORT% (refers to TIER.SHORT.X (e.g. TIER.SHORT.Leather)).
+MESSAGES.Lore=Elytra with %ARMOR_TIER_SHORT% level protection.
+MESSAGES.NoGivePermission=&cYou do not have the required permission node to give a(n) %ARMOR_TIER%s.
+MESSAGES.UsageDenied=You do not have the required permissions to wear a(n) %ARMOR_TIER%!
+MESSAGES.ElytraReceived=&2A(n) %ARMOR_TIER% has been bestowed upon you!
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 389dc4d..7eaac6f 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -2,6 +2,7 @@ name: ArmoredElytra
main: nl.pim16aap2.armoredElytra.ArmoredElytra
version: ${project.version}
author: pim16aap2
+api-version: 1.13
commands:
ArmoredElytra:
description: Give an armored elytra of the specified tier.