From 1ffd47ad9001a56a3020b191c35489f5df94279f Mon Sep 17 00:00:00 2001 From: EpiCanard Date: Wed, 7 Aug 2024 23:55:57 +0200 Subject: [PATCH] Remove reflection and annotation caller for nms --- .../globalmarketchest/GlobalMarketChest.java | 3 +- .../listeners/WorldListener.java | 5 +- .../utils/ItemStackUtils.java | 2 +- .../globalmarketchest/utils/Version.java | 61 -- .../utils/annotations/AnnotationCaller.java | 107 --- .../utils/annotations/Version.java | 13 - .../utils/reflection/NMSUtils.java | 43 -- .../utils/reflection/Path.java | 42 -- .../utils/reflection/ReflectionUtils.java | 17 - .../utils/reflection/VersionField.java | 113 --- .../utils/reflection/VersionSupportUtils.java | 663 ------------------ 11 files changed, 3 insertions(+), 1066 deletions(-) delete mode 100644 globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/Version.java delete mode 100644 globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/annotations/AnnotationCaller.java delete mode 100644 globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/annotations/Version.java delete mode 100644 globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/NMSUtils.java delete mode 100644 globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/Path.java delete mode 100644 globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/VersionField.java delete mode 100644 globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/VersionSupportUtils.java diff --git a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/GlobalMarketChest.java b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/GlobalMarketChest.java index bcb51f40..92d6f469 100644 --- a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/GlobalMarketChest.java +++ b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/GlobalMarketChest.java @@ -75,7 +75,6 @@ public GlobalMarketChest() { this.nms = initNms(); GlobalMarketChest.plugin = this; - Version.initVersion(Utils.getFullVersion()); } @Override @@ -90,7 +89,7 @@ public void onEnable() { try { this.configLoader.loadFiles(); } catch (CantLoadConfigException e) { - this.getLogger().log(Level.SEVERE, e.getMessage()); + LoggerUtils.error(e.getMessage()); this.disable(); return; } diff --git a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/listeners/WorldListener.java b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/listeners/WorldListener.java index 434364de..0ea12738 100644 --- a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/listeners/WorldListener.java +++ b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/listeners/WorldListener.java @@ -162,10 +162,7 @@ public void onInteract(PlayerInteractEvent event) { } public static WorldListener of() { - if (Version.isEqualsTo(Version.V1_12)) { - return new V1_12(); - } - return new V1_X(); + return Utils.getVersion().equals("1.12") ? new V1_12() : new V1_X(); } private static class V1_12 extends WorldListener { diff --git a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/ItemStackUtils.java b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/ItemStackUtils.java index f0c66b50..3b2df086 100644 --- a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/ItemStackUtils.java +++ b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/ItemStackUtils.java @@ -233,7 +233,7 @@ public Boolean isDamaged_Latest(ItemStack item) { * @return */ public Boolean isDamaged(ItemStack item) { - return Version.isEqualsTo(Version.V1_12) ? isDamaged_1_12(item) : isDamaged_Latest(item); + return Utils.getVersion().equals("1.12") ? isDamaged_1_12(item) : isDamaged_Latest(item); } /** diff --git a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/Version.java b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/Version.java deleted file mode 100644 index 86e3374e..00000000 --- a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/Version.java +++ /dev/null @@ -1,61 +0,0 @@ -package fr.epicanard.globalmarketchest.utils; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public enum Version { - CURRENT((byte)0, (byte)0), - V1_12((byte)12, (byte)-1), - V1_13((byte)13, (byte)-1), - V1_14((byte)14, (byte)-1), - V1_15((byte)15, (byte)-1), - V1_16((byte)16, (byte)-1), - V1_17((byte)17, (byte)-1), - V1_18((byte)18, (byte)-1), - V1_19((byte)19, (byte)-1), - V1_19_3((byte)19, (byte)3); - - private byte minor; - private byte patch; - - private static final Pattern versionRegex = Pattern.compile("(\\d+)[.](\\d+)(?:[.](\\d+))?"); - - Version(final byte minor, final byte patch) { - this.minor = minor; - this.patch = patch; - } - - private void updateVersion(final String strVersion) { - final Matcher matcher = versionRegex.matcher(strVersion); - - if (matcher.find() && matcher.groupCount() >= 2) { - minor = Byte.parseByte(matcher.group(2)); - String match = matcher.group(3); - patch = (match != null) ? Byte.parseByte(match) : (byte)0; - } - } - - public static void initVersion(final String strVersion) { - Version.CURRENT.updateVersion(strVersion); - } - - public static boolean isLowerThan(final Version newVersion) { - return CURRENT.minor < newVersion.minor || (CURRENT.minor == newVersion.minor && (newVersion.patch == -1 || CURRENT.patch < newVersion.patch)); - } - - public static boolean isLowerOrEqualsTo(final Version newVersion) { - return CURRENT.minor < newVersion.minor || (CURRENT.minor == newVersion.minor && (newVersion.patch == -1 || CURRENT.patch <= newVersion.patch)); - } - - public static boolean isEqualsTo(final Version newVersion) { - return CURRENT.minor == newVersion.minor && (newVersion.patch == -1 || CURRENT.patch == newVersion.patch); - } - - public static boolean isHigherOrEqualsTo(final Version newVersion) { - return CURRENT.minor > newVersion.minor || (CURRENT.minor == newVersion.minor && (newVersion.patch == -1 || CURRENT.patch >= newVersion.patch)); - } - - public static boolean isHigherThan(final Version newVersion) { - return CURRENT.minor > newVersion.minor || (CURRENT.minor == newVersion.minor && (newVersion.patch == -1 || CURRENT.patch > newVersion.patch)); - } -} diff --git a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/annotations/AnnotationCaller.java b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/annotations/AnnotationCaller.java deleted file mode 100644 index d34fe42b..00000000 --- a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/annotations/AnnotationCaller.java +++ /dev/null @@ -1,107 +0,0 @@ -package fr.epicanard.globalmarketchest.utils.annotations; - -import fr.epicanard.globalmarketchest.exceptions.MissingMethodException; -import fr.epicanard.globalmarketchest.utils.Utils; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.*; - -/** - * Class that allow to call method with annotations @Version - */ -public final class AnnotationCaller { - - /** - * Get all methods of a class with the annotation @Version.name = methodName - * And @Version.value = server version or "latest" - * - * @param methodName Name of annotation to search - * @param objectClass Class on which find the methods - * @return Return the matching method or the latest if missing - */ - private static Method getMethod(String methodName, Class objectClass) { - final List methods = Arrays.asList(objectClass.getMethods()); - Method latest = null; - - for (Method method : methods) { - final Version versionAno = method.getDeclaredAnnotation(Version.class); - if (versionAno != null && versionAno.name().equals(methodName)) { - final List versions = Arrays.asList(versionAno.versions()); - if (versions.contains(Utils.getVersion()) || versions.contains(Utils.getFullVersion())) - return method; - if (versions.contains("latest")) - latest = method; - } - } - return latest; - } - - /** - * Search a method with annotation Version.name=@param methodName - * And Version.versions=Server version or Version.versions=value - * - * This process allow to have multi version of one method tagged for each version - * - * Exemple: - *
-   * @Version(name="test", versions={"1.13"})
-   * myMethod() {}
-   *
-   * AnnotationCaller.call("test", my_obj, null)
-   * 
- * - * See: fr.epicanard.globalmarketchest.utils.annotations.Version - * - * @param Return type of called method - * @param methodName Name of the annotation to find - * @param object Object on which is declared the method - * @param args Arguments for method call - * @return Return what is return by the method called - * @throws MissingMethodException Throw when method with name (methodName) is missing with the server version and latest - */ - public static T call(String methodName, Object object, Object... args) throws MissingMethodException { - return AnnotationCaller.call(methodName, object.getClass(), object, args); - } - - /** - * Search a method with annotation Version.name=@param methodName - * And Version.versions=Server version or Version.versions=value - * - * This process allow to have multi version of one method tagged for each version - * - * Exemple: - *
-   * @Version(name="test", versions={"1.13"})
-   * myMethod() {}
-   *
-   * AnnotationCaller.call("test", my_obj, null)
-   * 
- * - * See: fr.epicanard.globalmarketchest.utils.annotations.Version - * - * @param Return type of called method - * @param methodName Name of the annotation to find - * @param objectClass Class of object - * @param object Object on which is declared the method - * @param args Arguments for method call - * @return Return what is return by the method called - * @throws MissingMethodException Throw when method with name (methodName) is missing with the server version and latest - */ - @SuppressWarnings("unchecked") - public static T call(String methodName, Class objectClass, Object object, Object... args) throws MissingMethodException { - final Method method = AnnotationCaller.getMethod(methodName, objectClass); - - if (method == null) { - throw new MissingMethodException(methodName); - } - try { - return (T) method.invoke(object, args); - } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - return null; - } - - private AnnotationCaller() {} -} diff --git a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/annotations/Version.java b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/annotations/Version.java deleted file mode 100644 index a439cb76..00000000 --- a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/annotations/Version.java +++ /dev/null @@ -1,13 +0,0 @@ -package fr.epicanard.globalmarketchest.utils.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface Version { - String name(); - String[] versions() default {"latest"}; -} diff --git a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/NMSUtils.java b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/NMSUtils.java deleted file mode 100644 index 6b48b630..00000000 --- a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/NMSUtils.java +++ /dev/null @@ -1,43 +0,0 @@ -package fr.epicanard.globalmarketchest.utils.reflection; - -import lombok.experimental.UtilityClass; -import org.bukkit.inventory.ItemStack; - -@UtilityClass -public class NMSUtils { - - /** - * Convert a spigot ItemStack to NMS ItemStack - * @param itemStack Spigot ItemStack - * @return NMS ItemStack or null - */ - Object toNmsItemstack(ItemStack itemStack) { - try { - return Path.BUKKIT - .getClass("inventory.CraftItemStack") - .getDeclaredMethod("asNMSCopy", ItemStack.class) - .invoke(null, itemStack); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - /** - * Convert a NMS ItemStack to spigot ItemStack - * @param nmsItemStack NMS ItemStack - * @return spigot ItemStack - */ - ItemStack toItemstack(Object nmsItemStack) { - try { - return (ItemStack) Path.BUKKIT - .getClass("inventory.CraftItemStack") - .getDeclaredMethod("asBukkitCopy", nmsItemStack.getClass()) - .invoke(null, nmsItemStack); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - -} diff --git a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/Path.java b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/Path.java deleted file mode 100644 index 12991d33..00000000 --- a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/Path.java +++ /dev/null @@ -1,42 +0,0 @@ -package fr.epicanard.globalmarketchest.utils.reflection; - -import org.bukkit.Bukkit; - -public enum Path { - BUKKIT("org.bukkit.craftbukkit" + version()), - MINECRAFT_SERVER("net.minecraft.server" + version()), - MINECRAFT_RESOURCES("net.minecraft.resources"), - MINECRAFT_WORLD_ITEM("net.minecraft.world.item"), - MINECRAFT_WORLD_ITEM_COMPONENT("net.minecraft.world.item.component"), - MINECRAFT_NETWORK_CHAT("net.minecraft.network.chat"), - MINECRAFT_NETWORK_GAME("net.minecraft.network.protocol.game"), - MINECRAFT_NETWORK_PROTOCOL("net.minecraft.network.protocol"), - MINECRAFT_WORLD_INVENTORY("net.minecraft.world.inventory"), - MINECRAFT_WORLD_ENTITY_PLAYER("net.minecraft.world.entity.player"), - MINECRAFT_NBT("net.minecraft.nbt"), - MINECRAFT_CORE_REGISTRIES("net.minecraft.core.registries"), - MINECRAFT_CORE_COMPONENT("net.minecraft.core.component"), - MINECRAFT_CORE("net.minecraft.core"); - - final String path; - - Path(String path) { - this.path = path; - } - - private static String version() { - try { - return "." + Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; - } catch(ArrayIndexOutOfBoundsException e) { - return ""; - } - } - - public Class getClass(String className) throws ClassNotFoundException { - return Class.forName(this.getPath(className)); - } - - public String getPath(String className) { - return this.path + "." + className; - } -} diff --git a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/ReflectionUtils.java b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/ReflectionUtils.java index 26e86df4..4154788e 100644 --- a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/ReflectionUtils.java +++ b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/ReflectionUtils.java @@ -39,22 +39,5 @@ public static Object invokeMethod(Object object, String method, Object... args) return null; } - /** - * Define if the current object has the specified method - * - * @param object the object on which call the method - * @param method the method name to calle - * @param args all the arguments that must be send to the method - * @return return a boolean - */ - public static Boolean hasMethod(Object object, String method, Object... args) { - try { - object.getClass().getMethod(method, fromObjectToClass(args)); - return true; - } catch (NoSuchMethodException e) { - return false; - } - } - private ReflectionUtils() {} } diff --git a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/VersionField.java b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/VersionField.java deleted file mode 100644 index 336ed5f5..00000000 --- a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/VersionField.java +++ /dev/null @@ -1,113 +0,0 @@ -package fr.epicanard.globalmarketchest.utils.reflection; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Optional; - -/** - * VersionField - * - * Reflection class that contains an object value - * Allow to chain the call - * - * Vanilla Java - * myObject.afield.anotherfield - * - * Reflection VersionField - * VersionField.from(myObject).get("afield").get("anotherfield").value() - */ -class VersionField { - - /** - * Field value - */ - private Object object; - private Class objectClass; - - /** - * The constructor - * - * @param obj value to assign to object - */ - VersionField(Object obj) { - this.object = obj; - this.objectClass = this.object.getClass(); - } - - VersionField(Object obj, Class objClass) { - this.object = obj; - this.objectClass = objClass; - } - - /** - * Create classe instance - */ - public static VersionField from(Object obj) { - return new VersionField(obj); - } - - public static VersionField from(Object obj, Class objClass) { - return new VersionField(obj, objClass); - } - - /** - * Reflection method to get a field value - * Store the field value and return a new instance of VersionField - * - * @param name field name - * @return a new instance of VersionField - * @throws NoSuchFieldException - * @throws IllegalAccessException - */ - VersionField get(String name) throws NoSuchFieldException, IllegalAccessException { - Object ret = this.objectClass.getField(name).get(this.object); - return new VersionField(ret); - } - - /** - * Reflection method to get a field with type - * Store the field value and return a new instance of VersionField - * - * @param fieldType field type - * @return a new instance of VersionField - * @throws NoSuchFieldException - * @throws IllegalAccessException - */ - VersionField getWithType(Class fieldType) throws NoSuchFieldException, IllegalAccessException { - final Optional maybeField = Arrays.stream(this.objectClass.getFields()) - .filter(f -> f.getType().isAssignableFrom(fieldType)).findFirst(); - if (!maybeField.isPresent()) { - throw new NoSuchFieldException("Can't find field with type : " + fieldType.getName()); - } - return new VersionField(maybeField.get().get(this.object)); - } - - /** - * Reflection method to invoke a method with type - * - * @param returnType return type - * @return a new instance of VersionField - * @throws NoSuchMethodException - * @throws IllegalAccessException - * @throws InvocationTargetException - */ - Object invokeMethodWithType(Class returnType) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - final Optional maybeMethod = Arrays.stream(this.objectClass.getMethods()) - .filter(m -> m.getReturnType().isAssignableFrom(returnType)).findFirst(); - if (!maybeMethod.isPresent()) { - throw new NoSuchMethodException("Can't find methode with return type : " + returnType.getName()); - } - return maybeMethod.get().invoke(this.object); - } - - /** - * Return the object value stored - * - * @return - */ - Object value() { - return this.object; - } -} diff --git a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/VersionSupportUtils.java b/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/VersionSupportUtils.java deleted file mode 100644 index b8bbf5b3..00000000 --- a/globalmarketchest/src/main/java/fr/epicanard/globalmarketchest/utils/reflection/VersionSupportUtils.java +++ /dev/null @@ -1,663 +0,0 @@ -package fr.epicanard.globalmarketchest.utils.reflection; - -import fr.epicanard.globalmarketchest.utils.Utils; -import fr.epicanard.globalmarketchest.utils.annotations.Version; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import java.lang.reflect.*; -import java.util.Arrays; -import java.util.Optional; - -import static fr.epicanard.globalmarketchest.utils.annotations.AnnotationCaller.call; -import static fr.epicanard.globalmarketchest.utils.reflection.ReflectionUtils.*; - -public class VersionSupportUtils { - - private final String NBTTAG = "GMCItem"; - - private static VersionSupportUtils INSTANCE; - - /** - * Private constructor VersionSupportUtils - */ - private VersionSupportUtils() { - } - - /** - * Singleton, method to get the instance of this class - */ - public static VersionSupportUtils getInstance() { - if (INSTANCE == null) - INSTANCE = new VersionSupportUtils(); - return INSTANCE; - } - - private Object newInstance(Class clazz, Object... args) { - try { - return clazz.getConstructor(fromObjectToClass(args)).newInstance(args); - } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - return null; - } - - // ======== TOOLS ============ - - /** - * Get the static object Item.REGISTRY - * - * @return return the static object - */ - private Object getRegistry() { - try { - return call("getRegistry", this); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - @Version(name = "getRegistry", versions = { "1.12" }) - public Object getRegistry_1_12() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { - return Path.MINECRAFT_SERVER.getClass("Item").getField("REGISTRY").get(null); - } - - @Version(name = "getRegistry", versions = { "1.13", "1.14", "1.15", "1.16" }) - public Object getRegistry_1_13() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { - return Path.MINECRAFT_SERVER.getClass("IRegistry").getField("ITEM").get(null); - } - - @Version(name = "getRegistry", versions = { "1.17" }) - public Object getRegistry_1_17() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { - return Path.MINECRAFT_CORE.getClass("IRegistry").getField("Z").get(null); - } - - @Version(name = "getRegistry", versions = { "1.18", "1.19.1", "1.19.2" }) - public Object getRegistry_1_18_19() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { - final Class registryBlockClass = Path.MINECRAFT_CORE.getClass("RegistryBlocks"); - final Class itemClass = getItemClass_latest(); - final Class registryClass = Path.MINECRAFT_CORE.getClass("IRegistry"); - final Optional maybeRegistryField = findParametrizedField(registryClass, registryBlockClass, itemClass); - - if (!maybeRegistryField.isPresent()) { - throw new NoSuchFieldException("Can't find item Registry."); - } - return maybeRegistryField.get().get(null); - } - - @Version(name = "getRegistry") - public Object getRegistry_latest() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { - final Class registryBlockClass = Path.MINECRAFT_CORE.getClass("RegistryBlocks"); - final Class itemClass = getItemClass_latest(); - final Class registryClass = Path.MINECRAFT_CORE_REGISTRIES.getClass("BuiltInRegistries"); - final Optional maybeRegistryField = findParametrizedField(registryClass, registryBlockClass, itemClass); - - if (!maybeRegistryField.isPresent()) { - throw new NoSuchFieldException("Can't find item Registry."); - } - return maybeRegistryField.get().get(null); - } - - @Version(name = "getRegistryItem", versions = { "1.12" }) - public Object getRegistryItem_1_12(Object registry, Object minecraftKey) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return registry.getClass().getMethod("get", Object.class).invoke(registry, minecraftKey); - } - - @Version(name = "getRegistryItem", versions = { "1.13", "1.14", "1.15", "1.16", "1.17" }) - public Object getRegistryItem_old(Object registry, Object minecraftKey) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return registry.getClass().getMethod("get", minecraftKey.getClass()).invoke(registry, minecraftKey); - } - - @Version(name = "getRegistryItem") - public Object getRegistryItem(Object registry, Object minecraftKey) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return registry.getClass().getMethod("a", minecraftKey.getClass()).invoke(registry, minecraftKey); - } - - @Version(name = "getMinecraftKey", versions = { "1.12" }) - public Object getMinecraftKey_1_12(Object registry, Object nmsItemStack) - throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return registry.getClass().getMethod("b", Object.class).invoke(registry, invokeMethod(nmsItemStack, "getItem")); - } - - @Version(name = "getMinecraftKey", versions = { "1.13", "1.14", "1.15", "1.16", "1.17" }) - public Object getMinecraftKey_1_13(Object registry, Object nmsItemStack) - throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return registry.getClass().getMethod("getKey", Object.class).invoke(registry, - invokeMethod(nmsItemStack, "getItem")); - } - - @Version(name = "getMinecraftKey", versions = { "1.18", "1.19" }) - public Object getMinecraftKey_1_18(Object registry, Object nmsItemStack) - throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return registry.getClass().getMethod("b", Object.class).invoke(registry, invokeMethod(nmsItemStack, "c")); - } - - @Version(name = "getMinecraftKey", versions = {"1.20.0, 1.20.1", "1.20.2", "1.20.3", "1.20.4"}) - public Object getMinecraftKey_1_20(Object registry, Object nmsItemStack) - throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return registry.getClass().getMethod("b", Object.class).invoke(registry, invokeMethod(nmsItemStack, "d")); - } - - @Version(name = "getMinecraftKey") - public Object getMinecraftKey_latest(Object registry, Object nmsItemStack) - throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return registry.getClass().getMethod("b", Object.class).invoke(registry, invokeMethod(nmsItemStack, "g")); - } - - @Version(name = "getNamespace", versions = { "1.14", "1.15", "1.16", "1.17" }) - public Object getNamespace_old(Object minecraftKey) { - return invokeMethod(minecraftKey, "getNamespace"); - } - - @Version(name = "getNamespace") - public Object getNamespace_latest(Object minecraftKey) { - return invokeMethod(minecraftKey, "b"); - } - - @Version(name = "getKey", versions = { "1.12", "1.13", "1.14", "1.15", "1.16", "1.17" }) - public Object getKey_old(Object minecraftKey) { - return invokeMethod(minecraftKey, "getKey"); - } - - @Version(name = "getKey") - public Object getKey_latest(Object minecraftKey) { - return invokeMethod(minecraftKey, "a"); - } - - @Version(name = "newNBTTagCompound", versions = { "1.12", "1.13", "1.14", "1.15", "1.16" }) - public Object newNBTTagCompound_old() throws ClassNotFoundException { - return newInstance(Path.MINECRAFT_SERVER.getClass("NBTTagCompound")); - } - - @Version(name = "newNBTTagCompound") - public Object newNBTTagCompound_latest() throws ClassNotFoundException { - return newInstance(Path.MINECRAFT_NBT.getClass("NBTTagCompound")); - } - - @Version(name = "getItemClass", versions = { "1.12", "1.13", "1.14", "1.15", "1.16" }) - public Class getItemClass_old() throws ClassNotFoundException { - return Path.MINECRAFT_SERVER.getClass("Item"); - } - - @Version(name = "getItemClass") - public Class getItemClass_latest() throws ClassNotFoundException { - return Path.MINECRAFT_WORLD_ITEM.getClass("Item"); - } - - @Version(name = "getName", versions = { "1.12", "1.13", "1.14", "1.15", "1.16", "1.17" }) - public Object getName_old(Object nmsItemStack) { - return invokeMethod(nmsItemStack, "getName"); - } - - @Version(name = "getName") - public Object getName_latest(Object nmsItemStack) - throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException { - final Class chatBaseComponent = Path.MINECRAFT_NETWORK_CHAT.getClass("IChatBaseComponent"); - return VersionField.from(nmsItemStack).invokeMethodWithType(chatBaseComponent); - } - - private String before1_18(String before, String after) { - switch (Utils.getVersion()) { - case "1.12": - case "1.13": - case "1.14": - case "1.15": - case "1.16": - case "1.17": - return before; - default: - return after; - } - } - - @Version(name = "getTag", versions = { "1.12", "1.13", "1.14", "1.15", "1.16", "1.17" }) - public Object getTagOld(Object itemStack) { - return invokeMethod(itemStack, "getTag"); - } - - @Version(name = "getTag", versions = { "1.18", "1.19", "1.20.0", "1.20.1", "1.20.2", "1.20.3", "1.20.4" }) - public Object getTag(Object itemStack) - throws ClassNotFoundException, InvocationTargetException, IllegalAccessException { - final Class nbtTagCompound = Path.MINECRAFT_NBT.getClass("NBTTagCompound"); - final Optional maybeMethod = Arrays.stream(itemStack.getClass().getMethods()) - .filter(m -> m.getReturnType().isAssignableFrom(nbtTagCompound) && m.getParameters().length == 0) - .findFirst(); - if (maybeMethod.isPresent()) - return maybeMethod.get().invoke(itemStack); - return null; - } - - @Version(name = "getTag") - public Object getTagLatest(Object itemStack) - throws ClassNotFoundException, InvocationTargetException, IllegalAccessException { - // net.minecraft.core.component.DataComponents.CUSTOM_DATA => DataComponents.b ? - final Class dataComponentTypeClass = Path.MINECRAFT_CORE_COMPONENT.getClass("DataComponentType"); - final Class dataComponentHolderClass = Path.MINECRAFT_CORE_COMPONENT.getClass("DataComponentHolder"); - final Class customDataClass = Path.MINECRAFT_WORLD_ITEM_COMPONENT.getClass("CustomData"); - final Class dataComponentsClass = Path.MINECRAFT_CORE_COMPONENT.getClass("DataComponents"); - // Get DataComponents.CUSTOM_DATA: DataComponentType - final Optional customDataComponent = findParametrizedField(dataComponentsClass, dataComponentTypeClass, customDataClass); - - if (!customDataComponent.isPresent()) - return null; - - // Get Method T get(DataComponentType) - final Optional maybeMethod = Arrays.stream(dataComponentHolderClass.getMethods()) - .filter(m -> { - return m.getGenericReturnType().getTypeName().equals("T") && m.getParameters().length == 1 - && m.getParameters()[0].getType().isAssignableFrom(dataComponentTypeClass); - }) - .findFirst(); - if (maybeMethod.isPresent()) - return maybeMethod.get().invoke(itemStack, customDataComponent.get().get(null)); - return null; - } - - @Version(name = "hasTagName", versions = { "1.12", "1.13", "1.14", "1.15", "1.17" }) - public String hasTagNameBefore1_18() { - return "hasKey"; // NBTTagCompound.hasKey - } - - @Version(name = "hasTagName", versions = { "1.18", "1.19", "1.20.0", "1.20.1", "1.20.2", "1.20.3", "1.20.4" }) - public String hasTagNameAfter1_19_20() { - return "e"; // NBTTagCompound.e - } - - @Version(name = "hasTagName") - public String hasTagNameLatest() { - return "a"; // CustomData.a - } - - public String setBooleanName() { - return before1_18("setBoolean", "a"); - } - - @Version(name = "setTag", versions = { "1.12", "1.13", "1.14", "1.15", "1.17" }) - public void setTagBefore1_18(Object nmsItemstack, Object tagCompound) { - invokeMethod(nmsItemstack, "setTag", tagCompound); - } - - @Version(name = "setTag", versions = { "1.18", "1.19", "1.20.0", "1.20.1", "1.20.2", "1.20.3", "1.20.4" }) - public void setTagAfter1_18(Object nmsItemstack, Object tagCompound) { - invokeMethod(nmsItemstack, "c", tagCompound); - } - - @Version(name = "setTag") - public void setTagLatest(Object nmsItemStack, Object tagCompound) { - try { - - final Class dataComponentTypeClass = Path.MINECRAFT_CORE_COMPONENT.getClass("DataComponentType"); - final Class customDataClass = Path.MINECRAFT_WORLD_ITEM_COMPONENT.getClass("CustomData"); - final Class dataComponentsClass = Path.MINECRAFT_CORE_COMPONENT.getClass("DataComponents"); - final Object customDataComponent = findParametrizedField(dataComponentsClass, dataComponentTypeClass, customDataClass).get().get(null); - - // CustomData.set(DataComponents.CUSTOM_DATA, nmsItemStack, tagCompound) - customDataClass - .getMethod("a", dataComponentTypeClass, nmsItemStack.getClass(), Path.MINECRAFT_NBT.getClass("NBTTagCompound")) - .invoke(null, customDataComponent, nmsItemStack, tagCompound); - } catch (ClassNotFoundException | InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { - e.printStackTrace(); - } - } - - @Version(name = "newMinecraftKey", versions = { "1.12", "1.13", "1.14", "1.15", "1.16" }) - public Object newMinecraftKey_old(String name) throws Exception { - return Path.MINECRAFT_SERVER.getClass("MinecraftKey").getConstructor(String.class).newInstance(name); - } - - @Version(name = "newMinecraftKey", versions = { "1.17", "1.18", "1.19", "1.20" }) - public Object newMinecraftKey_1_17(String name) throws Exception { - return Path.MINECRAFT_RESOURCES.getClass("MinecraftKey").getConstructor(String.class).newInstance(name); - } - - @Version(name = "newMinecraftKey") - public Object newMinecraftKey_latest(String name) throws Exception { - return Path.MINECRAFT_RESOURCES.getClass("MinecraftKey").getMethod("a", String.class).invoke(null, name); - } - - // ======= SPECIFIC METHOD =========== - - /** - * Get an itemStack with is minecraft key - * - * @param name - * @return - */ - public ItemStack getItemStack(String name) { - try { - Object minecraftKey = call("newMinecraftKey", this, name);; - - Object registry = getRegistry(); - Object item = call("getRegistryItem", this, registry, minecraftKey); - if (item == null) - return null; - - Class itemCLass = call("getItemClass", this); - - Method asNewCraftStack = Path.BUKKIT.getClass("inventory.CraftItemStack") - .getDeclaredMethod("asNewCraftStack", itemCLass); - ItemStack itemStack = (ItemStack) asNewCraftStack.invoke(null, item); - - return this.setNbtTag(itemStack); - - } catch (Exception e) { - e.printStackTrace(); - } - - return null; - } - - /** - * Get the minecraftkey in string. Format minecraft:dirt - * - * @param itemStack - * ItemStack - * @return return the string minecraft key - */ - public String getMinecraftKey(ItemStack itemStack) { - try { - Object nmsItemStack = NMSUtils.toNmsItemstack(itemStack); - - Object registry = getRegistry(); - Object minecraftKey = call("getMinecraftKey", this, registry, nmsItemStack); - - return call("getNamespace", this, minecraftKey) + ":" + call("getKey", this, minecraftKey); - - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - /** - * Get the display name of an itemstack - * - * @param itemStack ItemStack - * @return return the displayname - */ - public String getItemStackDisplayName(ItemStack itemStack) { - try { - Method asNMSCopy = Path.BUKKIT.getClass("inventory.CraftItemStack") - .getDeclaredMethod("asNMSCopy", ItemStack.class); - Object nmsItemStack = asNMSCopy.invoke(null, itemStack); - Object name = call("getName", this, nmsItemStack); - - if (name instanceof String) { - return (String) name; - } - return invokeMethod(name, "getString").toString(); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - /** - * Update the inventory name update by the player - * - * @param title The new inventory Name - * @param player The player - */ - @Version(name = "updateInventoryName", versions = { "1.12", "1.13" }) - public void updateInventoryName_1_13(String title, Player player) { - try { - Object entityPlayer = invokeMethod(player, "getHandle"); - Object chatMessage = newInstance(Path.MINECRAFT_SERVER.getClass("ChatMessage"), title, - new Object[] {}); - VersionField activeContainerVF = VersionField.from(entityPlayer).get("activeContainer"); - Object windowId = activeContainerVF.get("windowId").value(); - - Class ichat = Path.MINECRAFT_SERVER.getClass("IChatBaseComponent"); - - Object packet = Path.MINECRAFT_SERVER.getClass("PacketPlayOutOpenWindow") - .getConstructor(Integer.TYPE, String.class, ichat, Integer.TYPE) - .newInstance(windowId, "minecraft:chest", ichat.cast(chatMessage), - player.getOpenInventory().getTopInventory().getSize()); - - Object playerConnection = entityPlayer.getClass().getDeclaredField("playerConnection").get(entityPlayer); - - playerConnection.getClass().getMethod("sendPacket", Path.MINECRAFT_SERVER.getClass("Packet")) - .invoke(playerConnection, packet); - entityPlayer.getClass() - .getMethod("updateInventory", Path.MINECRAFT_SERVER.getClass("Container")) - .invoke(entityPlayer, activeContainerVF.value()); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Update the inventory name update by the player - * - * @param title The new inventory Name - * @param player The player - */ - @Version(name = "updateInventoryName", versions = { "1.14", "1.15", "1.16" }) - public void updateInventoryName_old(String title, Player player) { - try { - Object entityPlayer = invokeMethod(player, "getHandle"); - Object chatMessage = newInstance(Path.MINECRAFT_SERVER.getClass("ChatMessage"), title, - new Object[] {}); - VersionField activeContainerVF = VersionField.from(entityPlayer).get("activeContainer"); - Object windowId = activeContainerVF.get("windowId").value(); - - Class ichat = Path.MINECRAFT_SERVER.getClass("IChatBaseComponent"); - Class containers = Path.MINECRAFT_SERVER.getClass("Containers"); - - Object packet = Path.MINECRAFT_SERVER.getClass("PacketPlayOutOpenWindow") - .getConstructor(Integer.TYPE, containers, ichat) - .newInstance(windowId, containers.getField("GENERIC_9X6").get(null), ichat.cast(chatMessage)); - - Object playerConnection = entityPlayer.getClass().getDeclaredField("playerConnection").get(entityPlayer); - - playerConnection.getClass().getMethod("sendPacket", Path.MINECRAFT_SERVER.getClass("Packet")) - .invoke(playerConnection, packet); - entityPlayer.getClass() - .getMethod("updateInventory", Path.MINECRAFT_SERVER.getClass("Container")) - .invoke(entityPlayer, activeContainerVF.value()); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Update the inventory name update by the player - * - * @param title The new inventory Name - * @param player The player - */ - @Version(name = "updateInventoryName", versions = { "1.17" }) - public void updateInventoryName_1_17(String title, Player player) { - try { - Object entityPlayer = invokeMethod(player, "getHandle"); - Object chatMessage = newInstance(Path.MINECRAFT_NETWORK_CHAT.getClass("ChatMessage"), title, new Object[] {}); - VersionField activeContainerVF = VersionField.from(entityPlayer).get("bV"); - Object windowId = activeContainerVF.get("j").value(); - - Class ichat = Path.MINECRAFT_NETWORK_CHAT.getClass("IChatBaseComponent"); - Class containers = Path.MINECRAFT_WORLD_INVENTORY.getClass("Containers"); - - Object packet = Path.MINECRAFT_NETWORK_GAME.getClass("PacketPlayOutOpenWindow") - .getConstructor(Integer.TYPE, containers, ichat) - .newInstance(windowId, containers.getField("f").get(null), ichat.cast(chatMessage)); - - Object playerConnection = entityPlayer.getClass().getDeclaredField("b").get(entityPlayer); - - playerConnection.getClass().getMethod("sendPacket", Path.MINECRAFT_NETWORK_PROTOCOL.getClass("Packet")) - .invoke(playerConnection, packet); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Version(name = "updateInventoryName", versions = { "1.18" }) - public void updateInventoryName_1_18(String title, Player player) { - try { - Object entityPlayer = invokeMethod(player, "getHandle"); - Object chatMessage = newInstance(Path.MINECRAFT_NETWORK_CHAT.getClass("ChatMessage"), title, - new Object[] {}); - Class containerClass = Path.MINECRAFT_WORLD_INVENTORY.getClass("Container"); - VersionField activeContainerVF = VersionField.from(entityPlayer).getWithType(containerClass); - Object windowId = activeContainerVF.get("j").value(); - - Class ichat = Path.MINECRAFT_NETWORK_CHAT.getClass("IChatBaseComponent"); - Class containers = Path.MINECRAFT_WORLD_INVENTORY.getClass("Containers"); - - Object packet = Path.MINECRAFT_NETWORK_GAME.getClass("PacketPlayOutOpenWindow") - .getConstructor(Integer.TYPE, containers, ichat) - .newInstance(windowId, containers.getField("f").get(null), ichat.cast(chatMessage)); - - Object playerConnection = entityPlayer.getClass().getDeclaredField("b").get(entityPlayer); - - playerConnection.getClass().getMethod("a", Path.MINECRAFT_NETWORK_PROTOCOL.getClass("Packet")) - .invoke(playerConnection, packet); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Version(name = "updateInventoryName", versions = { "1.19" }) - public void updateInventoryName_1_19(String title, Player player) { - try { - Object entityPlayer = invokeMethod(player, "getHandle"); - Object chatMessage = Path.MINECRAFT_NETWORK_CHAT.getClass("IChatBaseComponent") - .getMethod("b", String.class).invoke(null, title); - Class containerClass = Path.MINECRAFT_WORLD_INVENTORY.getClass("Container"); - VersionField activeContainerVF = VersionField.from(entityPlayer).getWithType(containerClass); - Object windowId = activeContainerVF.get("j").value(); - - Class ichat = Path.MINECRAFT_NETWORK_CHAT.getClass("IChatBaseComponent"); - Class containers = Path.MINECRAFT_WORLD_INVENTORY.getClass("Containers"); - - Object packet = Path.MINECRAFT_NETWORK_GAME.getClass("PacketPlayOutOpenWindow") - .getConstructor(Integer.TYPE, containers, ichat) - .newInstance(windowId, containers.getField("f").get(null), ichat.cast(chatMessage)); - - Object playerConnection = entityPlayer.getClass().getDeclaredField("b").get(entityPlayer); - - playerConnection.getClass().getMethod("a", Path.MINECRAFT_NETWORK_PROTOCOL.getClass("Packet")) - .invoke(playerConnection, packet); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Version(name = "updateInventoryName", versions = { "1.20.0", "1.20.1" }) - public void updateInventoryName_latest_1_20(String title, Player player) { - try { - Object entityPlayer = invokeMethod(player, "getHandle"); - Object chatMessage = Path.MINECRAFT_NETWORK_CHAT.getClass("IChatBaseComponent") - .getMethod("b", String.class).invoke(null, title); - Class containerClass = Path.MINECRAFT_WORLD_INVENTORY.getClass("Container"); - VersionField activeContainerVF = VersionField.from(entityPlayer).getWithType(containerClass); - Object windowId = activeContainerVF.get("j").value(); - - Class ichat = Path.MINECRAFT_NETWORK_CHAT.getClass("IChatBaseComponent"); - Class containers = Path.MINECRAFT_WORLD_INVENTORY.getClass("Containers"); - - Object packet = Path.MINECRAFT_NETWORK_GAME.getClass("PacketPlayOutOpenWindow") - .getConstructor(Integer.TYPE, containers, ichat) - .newInstance(windowId, containers.getField("f").get(null), ichat.cast(chatMessage)); - - Object playerConnection = entityPlayer.getClass().getDeclaredField("c").get(entityPlayer); - - playerConnection.getClass().getMethod("a", Path.MINECRAFT_NETWORK_PROTOCOL.getClass("Packet")) - .invoke(playerConnection, packet); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Version(name = "updateInventoryName") - public void updateInventoryName_latest(String title, Player player) { - try { - Object entityPlayer = invokeMethod(player, "getHandle"); - Class entityHumanClass = Path.MINECRAFT_WORLD_ENTITY_PLAYER.getClass("EntityHuman"); - Object chatMessage = Path.MINECRAFT_NETWORK_CHAT.getClass("IChatBaseComponent") - .getMethod("b", String.class).invoke(null, title); - Class containerClass = Path.MINECRAFT_WORLD_INVENTORY.getClass("Container"); - VersionField activeContainerVF = VersionField.from(entityPlayer, entityHumanClass).getWithType(containerClass); - Object windowId = activeContainerVF.get("j").value(); - - Class ichat = Path.MINECRAFT_NETWORK_CHAT.getClass("IChatBaseComponent"); - Class containers = Path.MINECRAFT_WORLD_INVENTORY.getClass("Containers"); - - Object packet = Path.MINECRAFT_NETWORK_GAME.getClass("PacketPlayOutOpenWindow") - .getConstructor(Integer.TYPE, containers, ichat) - .newInstance(windowId, containers.getField("f").get(null), ichat.cast(chatMessage)); - - Object playerConnection = entityPlayer.getClass().getDeclaredField("c").get(entityPlayer); - - playerConnection.getClass().getMethod("b", Path.MINECRAFT_NETWORK_PROTOCOL.getClass("Packet")) - .invoke(playerConnection, packet); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Define if the GMC NBT TAG is set on this item - * - * @param itemStack Item to analyze - * @return Return if the item as gmc nbt tag - */ - public boolean hasNbtTag(ItemStack itemStack) { - try { - Object nmsItemStack = NMSUtils.toNmsItemstack(itemStack); - - Object tagCompound = call("getTag", this, nmsItemStack); - - return tagCompound != null && (Boolean) invokeMethod(tagCompound, call("hasTagName", this), this.NBTTAG); - } catch (Exception e) { - e.printStackTrace(); - } - return false; - } - - /** - * Set the custom GMC NBT TAG on item in parameter - * - * @param itemStack Item on which add NBT TAG - * @return ItemStack modified - */ - public ItemStack setNbtTag(ItemStack itemStack) { - if (itemStack == null) - return null; - if (this.hasNbtTag(itemStack)) - return itemStack; - - try { - Object nmsItemStack = NMSUtils.toNmsItemstack(itemStack); - - Object tagCompound = call("getTag", this, nmsItemStack); - - if (tagCompound == null) - tagCompound = call("newNBTTagCompound", this); - - tagCompound.getClass().getMethod(setBooleanName(), String.class, boolean.class).invoke(tagCompound, this.NBTTAG, true); - - call("setTag", this, nmsItemStack, tagCompound); - - return NMSUtils.toItemstack(nmsItemStack); - } catch (Exception e) { - e.printStackTrace(); - } - return itemStack; - } - - private Optional findParametrizedField(Class main, Class type, Class generic) { - return Arrays - .stream(main.getFields()) - .filter(f -> f.getType().isAssignableFrom(type) - && ((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0].equals(generic)) - .findFirst(); - - } - -}