diff --git a/pom.xml b/pom.xml index 0ed60ae..1c9a571 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ tech.sbdevelopment MapReflectionAPI - 1.6 + 1.6.1 jar MapReflectionAPI diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/ReflectionUtils.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/ReflectionUtils.java index 5a02c40..1edf971 100644 --- a/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/ReflectionUtils.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/ReflectionUtils.java @@ -51,7 +51,7 @@ import java.util.regex.Pattern; * A useful resource used to compare mappings is Mini's Mapping Viewer * * @author Crypto Morin - * @version 7.0.0 + * @version 7.1.0 */ public final class ReflectionUtils { /** @@ -151,6 +151,7 @@ public final class ReflectionUtils { /** * Gets the full version information of the server. Useful for including in errors. + * * @since 7.0.0 */ public static String getVersionInformation() { @@ -171,7 +172,7 @@ public final class ReflectionUtils { public static Integer getLatestPatchNumberOf(int minorVersion) { if (minorVersion <= 0) throw new IllegalArgumentException("Minor version must be positive: " + minorVersion); - // https://minecraft.fandom.com/wiki/Java_Edition_version_history + // https://minecraft.wiki/w/Java_Edition_version_history // There are many ways to do this, but this is more visually appealing. int[] patches = { /* 1 */ 1, @@ -194,7 +195,7 @@ public final class ReflectionUtils { /* 17 */ 1,// \_!_/ /* 18 */ 2, /* 19 */ 4, - /* 20 */ 0, + /* 20 */ 2, }; if (minorVersion > patches.length) return null; @@ -237,6 +238,13 @@ public final class ReflectionUtils { Class craftPlayer = getCraftClass("entity.CraftPlayer"); Class craftWorld = getCraftClass("CraftWorld"); Class playerConnection = getNMSClass("server.network", "PlayerConnection"); + Class playerCommonConnection; + if (supports(20) && supportsPatch(2)) { + // The packet send method has been abstracted from ServerGamePacketListenerImpl to ServerCommonPacketListenerImpl in 1.20.2 + playerCommonConnection = getNMSClass("server.network", "ServerCommonPacketListenerImpl"); + } else { + playerCommonConnection = playerConnection; + } MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle sendPacket = null, getHandle = null, getHandleWorld = null, connection = null; @@ -247,7 +255,7 @@ public final class ReflectionUtils { getHandle = lookup.findVirtual(craftPlayer, "getHandle", MethodType.methodType(entityPlayer)); getHandleWorld = lookup.findVirtual(craftWorld, "getHandle", MethodType.methodType(worldServer)); sendPacket = lookup.findVirtual(playerConnection, - v(18, "a").orElse("sendPacket"), + v(20, 2, "b").v(18, "a").orElse("sendPacket"), MethodType.methodType(void.class, getNMSClass("network.protocol", "Packet"))); } catch (NoSuchMethodException | NoSuchFieldException | IllegalAccessException ex) { ex.printStackTrace(); @@ -263,15 +271,26 @@ public final class ReflectionUtils { } /** - * This method is purely for readability. - * No performance is gained. + * Gives the {@code handle} object if the server version is equal or greater than the given version. + * This method is purely for readability and should be always used with {@link VersionHandler#orElse(Object)}. * + * @see #v(int, int, Object) + * @see VersionHandler#orElse(Object) * @since 5.0.0 */ public static VersionHandler v(int version, T handle) { return new VersionHandler<>(version, handle); } + /** + * Overload for {@link #v(int, T)} that supports patch versions + * + * @since 9.5.0 + */ + public static VersionHandler v(int version, int patch, T handle) { + return new VersionHandler<>(version, patch, handle); + } + public static CallableVersionHandler v(int version, Callable handle) { return new CallableVersionHandler<>(version, handle); } @@ -288,6 +307,20 @@ public final class ReflectionUtils { return MINOR_NUMBER >= minorNumber; } + /** + * Checks whether the server version is equal or greater than the given version. + * + * @param minorNumber the minor version to compare the server version with. + * @param patchNumber the patch number to compare the server version with. + * @return true if the version is equal or newer, otherwise false. + * @see #MINOR_NUMBER + * @see #PATCH_NUMBER + * @since 7.1.0 + */ + public static boolean supports(int minorNumber, int patchNumber) { + return (MINOR_NUMBER == minorNumber && supportsPatch(patchNumber)) || MINOR_NUMBER > minorNumber; + } + /** * Checks whether the server version is equal or greater than the given version. * @@ -300,36 +333,28 @@ public final class ReflectionUtils { return PATCH_NUMBER >= patchNumber; } - /** - * Checks whether the server version is equal or greater than the given version. - * If minorNumber matches, it will check if patchNumber is equal or greater, - * if minorNumber does not match, it will check if minorNumber is greater. - * - * @param minorNumber the minor version to compare the server version with. - * @param patchNumber the patch version to compare the server version with. - * @see #MINOR_NUMBER - * @see #PATCH_NUMBER - */ - public static boolean supports(int minorNumber, int patchNumber) { - return (MINOR_NUMBER == minorNumber && supportsPatch(patchNumber)) || MINOR_NUMBER > minorNumber; - } - /** * Get a NMS (net.minecraft.server) class which accepts a package for 1.17 compatibility. * - * @param newPackage the 1.17 package name. - * @param name the name of the class. + * @param packageName the 1.17+ package name of this class. + * @param name the name of the class. * @return the NMS class or null if not found. * @since 4.0.0 */ @Nullable - public static Class getNMSClass(@Nonnull String newPackage, @Nonnull String name) { - if (supports(17)) name = newPackage + '.' + name; - return getNMSClass(name); + public static Class getNMSClass(@Nullable String packageName, @Nonnull String name) { + if (packageName != null && supports(17)) name = packageName + '.' + name; + + try { + return Class.forName(NMS_PACKAGE + name); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + return null; + } } /** - * Get a NMS (net.minecraft.server) class. + * Get a NMS {@link #NMS_PACKAGE} class. * * @param name the name of the class. * @return the NMS class or null if not found. @@ -337,12 +362,7 @@ public final class ReflectionUtils { */ @Nullable public static Class getNMSClass(@Nonnull String name) { - try { - return Class.forName(NMS_PACKAGE + name); - } catch (ClassNotFoundException ex) { - ex.printStackTrace(); - return null; - } + return getNMSClass(null, name); } /** @@ -437,6 +457,10 @@ public final class ReflectionUtils { } } + /** + * @deprecated Use {@link #toArrayClass(Class)} instead. + */ + @Deprecated public static Class getArrayClass(String clazz, boolean nms) { clazz = "[L" + (nms ? NMS_PACKAGE : CRAFTBUKKIT_PACKAGE) + clazz + ';'; try { @@ -447,6 +471,15 @@ public final class ReflectionUtils { } } + /** + * Gives an array version of a class. For example if you wanted {@code EntityPlayer[]} you'd use: + *
{@code
+     *     Class EntityPlayer = ReflectionUtils.getNMSClass("...", "EntityPlayer");
+     *     Class EntityPlayerArray = ReflectionUtils.toArrayClass(EntityPlayer);
+     * }
+ * + * @param clazz the class to get the array version of. You could use for multi-dimensions arrays too. + */ public static Class toArrayClass(Class clazz) { try { return Class.forName("[L" + clazz.getName() + ';'); @@ -457,26 +490,39 @@ public final class ReflectionUtils { } public static final class VersionHandler { - private int version; + private int version, patch; private T handle; private VersionHandler(int version, T handle) { - if (supports(version)) { + this(version, 0, handle); + } + + private VersionHandler(int version, int patch, T handle) { + if (supports(version) && supportsPatch(patch)) { this.version = version; + this.patch = patch; this.handle = handle; } } public VersionHandler v(int version, T handle) { - if (version == this.version) - throw new IllegalArgumentException("Cannot have duplicate version handles for version: " + version); - if (version > this.version && supports(version)) { + return v(version, 0, handle); + } + + public VersionHandler v(int version, int patch, T handle) { + if (version == this.version && patch == this.patch) + throw new IllegalArgumentException("Cannot have duplicate version handles for version: " + version + '.' + patch); + if (version > this.version && supports(version) && patch >= this.patch && supportsPatch(patch)) { this.version = version; + this.patch = patch; this.handle = handle; } return this; } + /** + * If none of the previous version checks matched, it'll return this object. + */ public T orElse(T handle) { return this.version == 0 ? handle : this.handle; } @@ -512,4 +558,4 @@ public final class ReflectionUtils { } } } -} \ No newline at end of file +}