diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/ChestCommands.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/ChestCommands.java index 7a01775..77edf61 100644 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/ChestCommands.java +++ b/ChestCommands/src/com/gmail/filoghost/chestcommands/ChestCommands.java @@ -30,7 +30,6 @@ import com.gmail.filoghost.chestcommands.listener.InventoryListener; import com.gmail.filoghost.chestcommands.listener.JoinListener; import com.gmail.filoghost.chestcommands.listener.SignListener; import com.gmail.filoghost.chestcommands.nms.AttributeRemover; -import com.gmail.filoghost.chestcommands.nms.Fallback; import com.gmail.filoghost.chestcommands.serializer.CommandSerializer; import com.gmail.filoghost.chestcommands.serializer.MenuSerializer; import com.gmail.filoghost.chestcommands.task.ErrorLoggerTask; @@ -84,15 +83,8 @@ public class ChestCommands extends JavaPlugin { getLogger().info("Hooked PlayerPoints"); } - String version = Utils.getBukkitVersion(); - try { - Class clazz = Class.forName("com.gmail.filoghost.chestcommands.nms." + version); - attributeRemover = (AttributeRemover) clazz.newInstance(); - } catch (Exception e) { - attributeRemover = new Fallback(); - getLogger().info("Could not find a compatible Attribute Remover for this server version. Attributes will show up on items."); - } - + AttributeRemover.setup(); + if (settings.update_notifications) { new SimpleUpdater(this, 56919).checkForUpdates(new ResponseHandler() { diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/api/IconMenu.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/api/IconMenu.java index d3e7c24..4f4cd0d 100644 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/api/IconMenu.java +++ b/ChestCommands/src/com/gmail/filoghost/chestcommands/api/IconMenu.java @@ -6,8 +6,8 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; -import com.gmail.filoghost.chestcommands.ChestCommands; import com.gmail.filoghost.chestcommands.internal.MenuInventoryHolder; +import com.gmail.filoghost.chestcommands.nms.AttributeRemover; import com.gmail.filoghost.chestcommands.util.Utils; import com.gmail.filoghost.chestcommands.util.Validate; @@ -79,7 +79,7 @@ public class IconMenu { for (int i = 0; i < icons.length; i++) { if (icons[i] != null) { - inventory.setItem(i, ChestCommands.getAttributeRemover().removeAttributes(icons[i].createItemstack(player))); + inventory.setItem(i, AttributeRemover.hideAttributes(icons[i].createItemstack(player))); } } diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/internal/CachedGetters.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/internal/CachedGetters.java index 26443b9..e9700a3 100644 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/internal/CachedGetters.java +++ b/ChestCommands/src/com/gmail/filoghost/chestcommands/internal/CachedGetters.java @@ -1,21 +1,46 @@ package com.gmail.filoghost.chestcommands.internal; +import java.lang.reflect.Method; +import java.util.Collection; + import org.bukkit.Bukkit; public class CachedGetters { private static long lastOnlinePlayersRefresh; private static int onlinePlayers; + private static Method getOnlinePlayersMethod; + + static { + try { + getOnlinePlayersMethod = Bukkit.class.getMethod("getOnlinePlayers"); + } catch (Exception ex) { } + } public static int getOnlinePlayers() { long now = System.currentTimeMillis(); if (lastOnlinePlayersRefresh == 0 || now - lastOnlinePlayersRefresh > 1000) { // getOnlinePlayers() could be expensive if called frequently lastOnlinePlayersRefresh = now; - onlinePlayers = Bukkit.getOnlinePlayers().length; + + try { + onlinePlayers = count(getOnlinePlayersMethod.invoke(null)); + } catch (Exception e) { + onlinePlayers = -1; + } } return onlinePlayers; } + private static int count(Object o) { + if (o.getClass().isArray()) { + return ((Object[]) o).length; + } else if (o instanceof Collection) { + return ((Collection) o).size(); + } else { + return -1; + } + } + } diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/internal/ExtendedIconMenu.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/internal/ExtendedIconMenu.java index 6c7a45f..f49ef3e 100644 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/internal/ExtendedIconMenu.java +++ b/ChestCommands/src/com/gmail/filoghost/chestcommands/internal/ExtendedIconMenu.java @@ -15,6 +15,7 @@ import com.gmail.filoghost.chestcommands.Permissions; import com.gmail.filoghost.chestcommands.api.IconMenu; import com.gmail.filoghost.chestcommands.internal.icon.ExtendedIcon; import com.gmail.filoghost.chestcommands.internal.icon.IconCommand; +import com.gmail.filoghost.chestcommands.nms.AttributeRemover; public class ExtendedIconMenu extends IconMenu { @@ -72,7 +73,7 @@ public class ExtendedIconMenu extends IconMenu { continue; } - inventory.setItem(i, ChestCommands.getAttributeRemover().removeAttributes(icons[i].createItemstack(player))); + inventory.setItem(i, AttributeRemover.hideAttributes(icons[i].createItemstack(player))); } } @@ -96,12 +97,12 @@ public class ExtendedIconMenu extends IconMenu { if (extIcon.canViewIcon(player)) { if (inventory.getItem(i) == null) { - ItemStack updatedIcon = ChestCommands.getAttributeRemover().removeAttributes(extIcon.createItemstack(player)); + ItemStack updatedIcon = extIcon.createItemstack(player); inventory.setItem(i, updatedIcon); } // Performance, only update name and lore. - ItemStack inventoryItem = inventory.getItem(i); + ItemStack inventoryItem = AttributeRemover.hideAttributes(inventory.getItem(i)); ItemMeta meta = inventoryItem.getItemMeta(); meta.setDisplayName(extIcon.calculateName(player)); meta.setLore(extIcon.calculateLore(player)); diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/AttributeRemover.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/AttributeRemover.java index b7702af..8736797 100644 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/AttributeRemover.java +++ b/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/AttributeRemover.java @@ -1,9 +1,122 @@ package com.gmail.filoghost.chestcommands.nms; +import java.lang.reflect.Method; +import java.util.Collection; + +import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; -public interface AttributeRemover { +import com.gmail.filoghost.chestcommands.util.Utils; - public ItemStack removeAttributes(ItemStack item); +public class AttributeRemover { + + private static boolean useItemFlags; + private static boolean useReflection; + + // Reflection stuff + private static Class nbtTagCompoundClass; + private static Class nbtTagListClass; + private static Class nmsItemstackClass; + private static Method asNmsCopyMethod; // static + private static Method asCraftMirrorMethod; // static + private static Method hasTagMethod; + private static Method getTagMethod; + private static Method setTagMethod; + private static Method nbtSetMethod; + + + public static boolean setup() { + + if (Utils.isClassLoaded("org.bukkit.inventory.ItemFlag")) { + // We can use the new Bukkit API (1.8.3+) + useItemFlags = true; + + } else { + + try { + // Try to get the NMS methods and classes + nbtTagCompoundClass = getNmsClass("NBTTagCompound"); + nbtTagListClass = getNmsClass("NBTTagList"); + nmsItemstackClass = getNmsClass("ItemStack"); + + asNmsCopyMethod = getObcClass("inventory.CraftItemStack").getMethod("asNMSCopy", ItemStack.class); + asCraftMirrorMethod = getObcClass("inventory.CraftItemStack").getMethod("asCraftMirror", nmsItemstackClass); + + hasTagMethod = nmsItemstackClass.getMethod("hasTag"); + getTagMethod = nmsItemstackClass.getMethod("getTag"); + setTagMethod = nmsItemstackClass.getMethod("setTag", nbtTagCompoundClass); + + nbtSetMethod = nbtTagCompoundClass.getMethod("set", String.class, getNmsClass("NBTBase")); + + useReflection = true; + + } catch (Exception e) { + + e.printStackTrace(); + + } + } + + return true; + } + + + private static Class getNmsClass(String name) throws ClassNotFoundException { + return Class.forName("net.minecraft.server." + Utils.getBukkitVersion() + "." + name); + } + + private static Class getObcClass(String name) throws ClassNotFoundException { + return Class.forName("org.bukkit.craftbukkit." + Utils.getBukkitVersion() + "." + name); + } + + public static ItemStack hideAttributes(ItemStack item) { + if (item == null) { + return null; + } + + if (useItemFlags) { + ItemMeta meta = item.getItemMeta(); + if (isNullOrEmpty(meta.getItemFlags())) { + // Add them only if necessary + meta.addItemFlags(ItemFlag.values()); + item.setItemMeta(meta); + } + return item; + + } else if (useReflection) { + try { + + Object nmsItemstack = asNmsCopyMethod.invoke(null, item); + if (nmsItemstack == null) { + return item; + } + + Object nbtCompound; + if ((Boolean) hasTagMethod.invoke(nmsItemstack)) { + nbtCompound = getTagMethod.invoke(nmsItemstack); + } else { + nbtCompound = nbtTagCompoundClass.newInstance(); + setTagMethod.invoke(nmsItemstack, nbtCompound); + } + + if (nbtCompound == null) { + return item; + } + + Object nbtList = nbtTagListClass.newInstance(); + nbtSetMethod.invoke(nbtCompound, "AttributeModifiers", nbtList); + return (ItemStack) asCraftMirrorMethod.invoke(null, nmsItemstack); + + } catch (Exception e) { } + } + + // On failure + return item; + } + + private static boolean isNullOrEmpty(Collection coll) { + return coll == null || coll.isEmpty(); + } } diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/Fallback.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/Fallback.java deleted file mode 100644 index 15fed92..0000000 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/Fallback.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.gmail.filoghost.chestcommands.nms; - -import org.bukkit.inventory.ItemStack; - -public class Fallback implements AttributeRemover { - - @Override - public ItemStack removeAttributes(ItemStack item) { - return item; - } - -} diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_6_R2.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_6_R2.java deleted file mode 100644 index 3151d1f..0000000 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_6_R2.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gmail.filoghost.chestcommands.nms; - -import net.minecraft.server.v1_6_R2.NBTTagCompound; -import net.minecraft.server.v1_6_R2.NBTTagList; - -import org.bukkit.craftbukkit.v1_6_R2.inventory.CraftItemStack; -import org.bukkit.inventory.ItemStack; - -public class v1_6_R2 implements AttributeRemover { - - @Override - public ItemStack removeAttributes(ItemStack item) { - - if(item == null) { - return item; - } - - net.minecraft.server.v1_6_R2.ItemStack nmsStack = CraftItemStack.asNMSCopy(item); - - if (nmsStack == null) return item; - - NBTTagCompound tag; - if (!nmsStack.hasTag()){ - tag = new NBTTagCompound(); - nmsStack.setTag(tag); - } - else { - tag = nmsStack.getTag(); - } - NBTTagList am = new NBTTagList(); - tag.set("AttributeModifiers", am); - nmsStack.setTag(tag); - return CraftItemStack.asCraftMirror(nmsStack); - - } - -} diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_6_R3.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_6_R3.java deleted file mode 100644 index c1d1883..0000000 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_6_R3.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gmail.filoghost.chestcommands.nms; - -import net.minecraft.server.v1_6_R3.NBTTagCompound; -import net.minecraft.server.v1_6_R3.NBTTagList; - -import org.bukkit.craftbukkit.v1_6_R3.inventory.CraftItemStack; -import org.bukkit.inventory.ItemStack; - -public class v1_6_R3 implements AttributeRemover { - - @Override - public ItemStack removeAttributes(ItemStack item) { - - if(item == null) { - return item; - } - - net.minecraft.server.v1_6_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(item); - - if (nmsStack == null) return item; - - NBTTagCompound tag; - if (!nmsStack.hasTag()){ - tag = new NBTTagCompound(); - nmsStack.setTag(tag); - } - else { - tag = nmsStack.getTag(); - } - NBTTagList am = new NBTTagList(); - tag.set("AttributeModifiers", am); - nmsStack.setTag(tag); - return CraftItemStack.asCraftMirror(nmsStack); - - } - -} diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R1.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R1.java deleted file mode 100644 index ef7b48a..0000000 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R1.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gmail.filoghost.chestcommands.nms; - -import net.minecraft.server.v1_7_R1.NBTTagCompound; -import net.minecraft.server.v1_7_R1.NBTTagList; - -import org.bukkit.craftbukkit.v1_7_R1.inventory.CraftItemStack; -import org.bukkit.inventory.ItemStack; - -public class v1_7_R1 implements AttributeRemover { - - @Override - public ItemStack removeAttributes(ItemStack item) { - - if(item == null) { - return item; - } - - net.minecraft.server.v1_7_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(item); - - if (nmsStack == null) return item; - - NBTTagCompound tag; - if (!nmsStack.hasTag()){ - tag = new NBTTagCompound(); - nmsStack.setTag(tag); - } - else { - tag = nmsStack.getTag(); - } - NBTTagList am = new NBTTagList(); - tag.set("AttributeModifiers", am); - nmsStack.setTag(tag); - return CraftItemStack.asCraftMirror(nmsStack); - - } - -} diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R2.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R2.java deleted file mode 100644 index 2de03b0..0000000 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R2.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gmail.filoghost.chestcommands.nms; - -import net.minecraft.server.v1_7_R2.NBTTagCompound; -import net.minecraft.server.v1_7_R2.NBTTagList; - -import org.bukkit.craftbukkit.v1_7_R2.inventory.CraftItemStack; -import org.bukkit.inventory.ItemStack; - -public class v1_7_R2 implements AttributeRemover { - - @Override - public ItemStack removeAttributes(ItemStack item) { - - if(item == null) { - return item; - } - - net.minecraft.server.v1_7_R2.ItemStack nmsStack = CraftItemStack.asNMSCopy(item); - - if (nmsStack == null) return item; - - NBTTagCompound tag; - if (!nmsStack.hasTag()){ - tag = new NBTTagCompound(); - nmsStack.setTag(tag); - } - else { - tag = nmsStack.getTag(); - } - NBTTagList am = new NBTTagList(); - tag.set("AttributeModifiers", am); - nmsStack.setTag(tag); - return CraftItemStack.asCraftMirror(nmsStack); - - } - -} diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R3.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R3.java deleted file mode 100644 index b6d3601..0000000 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R3.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gmail.filoghost.chestcommands.nms; - -import net.minecraft.server.v1_7_R3.NBTTagCompound; -import net.minecraft.server.v1_7_R3.NBTTagList; - -import org.bukkit.craftbukkit.v1_7_R3.inventory.CraftItemStack; -import org.bukkit.inventory.ItemStack; - -public class v1_7_R3 implements AttributeRemover { - - @Override - public ItemStack removeAttributes(ItemStack item) { - - if(item == null) { - return item; - } - - net.minecraft.server.v1_7_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(item); - - if (nmsStack == null) return item; - - NBTTagCompound tag; - if (!nmsStack.hasTag()){ - tag = new NBTTagCompound(); - nmsStack.setTag(tag); - } - else { - tag = nmsStack.getTag(); - } - NBTTagList am = new NBTTagList(); - tag.set("AttributeModifiers", am); - nmsStack.setTag(tag); - return CraftItemStack.asCraftMirror(nmsStack); - - } - -} diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R4.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R4.java deleted file mode 100644 index 6b982fc..0000000 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_7_R4.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gmail.filoghost.chestcommands.nms; - -import net.minecraft.server.v1_7_R4.NBTTagCompound; -import net.minecraft.server.v1_7_R4.NBTTagList; - -import org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack; -import org.bukkit.inventory.ItemStack; - -public class v1_7_R4 implements AttributeRemover { - - @Override - public ItemStack removeAttributes(ItemStack item) { - - if(item == null) { - return item; - } - - net.minecraft.server.v1_7_R4.ItemStack nmsStack = CraftItemStack.asNMSCopy(item); - - if (nmsStack == null) return item; - - NBTTagCompound tag; - if (!nmsStack.hasTag()){ - tag = new NBTTagCompound(); - nmsStack.setTag(tag); - } - else { - tag = nmsStack.getTag(); - } - NBTTagList am = new NBTTagList(); - tag.set("AttributeModifiers", am); - nmsStack.setTag(tag); - return CraftItemStack.asCraftMirror(nmsStack); - - } - -} diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_8_R1.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_8_R1.java deleted file mode 100644 index 54137a7..0000000 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/nms/v1_8_R1.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gmail.filoghost.chestcommands.nms; - -import net.minecraft.server.v1_8_R1.NBTTagCompound; -import net.minecraft.server.v1_8_R1.NBTTagInt; -import org.bukkit.craftbukkit.v1_8_R1.inventory.CraftItemStack; -import org.bukkit.inventory.ItemStack; - -public class v1_8_R1 implements AttributeRemover { - - @Override - public ItemStack removeAttributes(ItemStack item) { - - if(item == null) { - return item; - } - - net.minecraft.server.v1_8_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(item); - - if (nmsStack == null) return item; - - NBTTagCompound tag; - if (!nmsStack.hasTag()) { - tag = new NBTTagCompound(); - nmsStack.setTag(tag); - } else { - tag = nmsStack.getTag(); - } - - tag.set("HideFlags", new NBTTagInt(Integer.MAX_VALUE)); - nmsStack.setTag(tag); - return CraftItemStack.asCraftMirror(nmsStack); - } - -} \ No newline at end of file diff --git a/ChestCommands/src/com/gmail/filoghost/chestcommands/util/Utils.java b/ChestCommands/src/com/gmail/filoghost/chestcommands/util/Utils.java index 6cb4dc8..885c079 100644 --- a/ChestCommands/src/com/gmail/filoghost/chestcommands/util/Utils.java +++ b/ChestCommands/src/com/gmail/filoghost/chestcommands/util/Utils.java @@ -34,6 +34,7 @@ public class Utils { // Default material names are ugly. private static Map materialMap = newHashMap(); + static { for (Material mat : Material.values()) { materialMap.put(StringUtils.stripChars(mat.toString(), "_").toLowerCase(), mat); @@ -98,9 +99,15 @@ public class Utils { } } + private static String bukkitVersion; + public static String getBukkitVersion() { - String packageName = Bukkit.getServer().getClass().getPackage().getName(); - return packageName.substring(packageName.lastIndexOf('.') + 1); + if (bukkitVersion == null) { + String packageName = Bukkit.getServer().getClass().getPackage().getName(); + bukkitVersion = packageName.substring(packageName.lastIndexOf('.') + 1); + } + + return bukkitVersion; } public static String colorizeName(String input) { @@ -326,4 +333,13 @@ public class Utils { return builder.toString(); } + + public static boolean isClassLoaded(String name) { + try { + Class.forName(name); + return true; + } catch (Exception e) { + return false; + } + } }