diff --git a/build-logic/src/main/kotlin/Versions.kt b/build-logic/src/main/kotlin/Versions.kt index dca638e6..740288d8 100644 --- a/build-logic/src/main/kotlin/Versions.kt +++ b/build-logic/src/main/kotlin/Versions.kt @@ -29,7 +29,6 @@ object Versions { const val configUtilsVersion = "1.0-SNAPSHOT" const val spigotVersion = "1.13-R0.1-SNAPSHOT" const val fastutilVersion = "8.5.3" - const val lombokVersion = "1.18.20" const val guiceVersion = "5.0.1" const val nettyVersion = "4.1.49.Final" const val snakeyamlVersion = "1.28" diff --git a/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeeSkinApplier.java b/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeeSkinApplier.java index 35e19bd2..ee10c47a 100644 --- a/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeeSkinApplier.java +++ b/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeeSkinApplier.java @@ -25,27 +25,48 @@ package org.geysermc.floodgate.pluginmessage; +import static com.google.common.base.Preconditions.checkNotNull; import static org.geysermc.floodgate.util.ReflectionUtils.getFieldOfType; -import static org.geysermc.floodgate.util.ReflectionUtils.setValue; +import static org.geysermc.floodgate.util.ReflectionUtils.getMethodByName; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.Method; import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.connection.InitialHandler; import net.md_5.bungee.connection.LoginResult; -import net.md_5.bungee.protocol.Property; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.skin.SkinApplier; import org.geysermc.floodgate.skin.SkinData; +import org.geysermc.floodgate.util.ReflectionUtils; @RequiredArgsConstructor public final class BungeeSkinApplier implements SkinApplier { - private static final Field LOGIN_RESULT; + private static final Field LOGIN_RESULT_FIELD; + private static final Method SET_PROPERTIES_METHOD; + + private static final Class PROPERTY_CLASS; + private static final Constructor PROPERTY_CONSTRUCTOR; static { - LOGIN_RESULT = getFieldOfType(InitialHandler.class, LoginResult.class); + LOGIN_RESULT_FIELD = getFieldOfType(InitialHandler.class, LoginResult.class); + checkNotNull(LOGIN_RESULT_FIELD, "LoginResult field cannot be null"); + + SET_PROPERTIES_METHOD = getMethodByName(LoginResult.class, "setProperties", true); + + PROPERTY_CLASS = ReflectionUtils.getClassOrFallbackPrefixed( + "protocol.Property", "connection.LoginResult.Property" + ); + + PROPERTY_CONSTRUCTOR = ReflectionUtils.getConstructor( + PROPERTY_CLASS, true, + String.class, String.class, String.class + ); + checkNotNull(PROPERTY_CONSTRUCTOR, "Property constructor cannot be null"); } private final FloodgateLogger logger; @@ -71,11 +92,17 @@ public final class BungeeSkinApplier implements SkinApplier { if (loginResult == null) { // id and name are unused and properties will be overridden loginResult = new LoginResult(null, null, null); - setValue(handler, LOGIN_RESULT, loginResult); + ReflectionUtils.setValue(handler, LOGIN_RESULT_FIELD, loginResult); } - Property property = new Property("textures", skinData.getValue(), skinData.getSignature()); + Object property = ReflectionUtils.newInstance( + PROPERTY_CONSTRUCTOR, + "textures", skinData.getValue(), skinData.getSignature() + ); - loginResult.setProperties(new Property[]{property}); + Object propertyArray = Array.newInstance(PROPERTY_CLASS, 1); + Array.set(propertyArray, 0, property); + + ReflectionUtils.invoke(loginResult, SET_PROPERTIES_METHOD, propertyArray); } } diff --git a/core/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java b/core/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java index 63605c66..32596344 100644 --- a/core/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java +++ b/core/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java @@ -46,6 +46,10 @@ public final class ReflectionUtils { @Setter private static String prefix; + private static String applyPrefix(String className) { + return prefix + "." + className; + } + /** * Get a class that is prefixed with the prefix provided in {@link #setPrefix(String)}. Calling * this method is equal to calling {@link #getClass(String)} with prefix.classname @@ -56,13 +60,13 @@ public final class ReflectionUtils { */ @Nullable public static Class getPrefixedClass(String className) { - return getClass(prefix + "." + className); + return getClass(applyPrefix(className)); } @Nullable public static Class getPrefixedClassSilently(String className) { try { - return Class.forName(prefix + "." + className); + return Class.forName(applyPrefix(className)); } catch (ClassNotFoundException ignored) { return null; } @@ -109,6 +113,28 @@ public final class ReflectionUtils { } } + public static Class getClassOrFallbackPrefixed(String className, String fallbackClassName) { + return getClassOrFallback(applyPrefix(className), applyPrefix(fallbackClassName)); + } + + public static Class getClassOrFallback(String className, String fallbackClassName) { + Class clazz = getClassSilently(className); + + if (clazz != null) { + if (Constants.DEBUG_MODE) { + System.out.println("Found class (primary): " + clazz.getName()); + } + return clazz; + } + + // do throw an exception when both classes couldn't be found + clazz = ReflectionUtils.getClassOrThrow(fallbackClassName); + if (Constants.DEBUG_MODE) { + System.out.println("Found class (fallback): " + clazz.getName()); + } + return clazz; + } + @Nullable public static Constructor getConstructor(Class clazz, boolean declared, Class... parameters) { try { diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java b/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java index 66801723..4d0908e7 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java +++ b/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java @@ -25,6 +25,7 @@ package org.geysermc.floodgate.util; +import static org.geysermc.floodgate.util.ReflectionUtils.getClassOrFallback; import static org.geysermc.floodgate.util.ReflectionUtils.getField; import static org.geysermc.floodgate.util.ReflectionUtils.getFieldOfType; import static org.geysermc.floodgate.util.ReflectionUtils.getMethod; @@ -85,12 +86,12 @@ public class ClassNames { // SpigotInjector - MINECRAFT_SERVER = getClassOrFallBack( + MINECRAFT_SERVER = getClassOrFallback( "net.minecraft.server.MinecraftServer", nmsPackage + "MinecraftServer" ); - SERVER_CONNECTION = getClassOrFallBack( + SERVER_CONNECTION = getClassOrFallback( "net.minecraft.server.network.ServerConnection", nmsPackage + "ServerConnection" ); @@ -105,14 +106,14 @@ public class ClassNames { craftOfflinePlayerClass, true, craftServerClass, GameProfile.class); // SpigotDataHandler - Class networkManager = getClassOrFallBack( + Class networkManager = getClassOrFallback( "net.minecraft.network.NetworkManager", nmsPackage + "NetworkManager" ); SOCKET_ADDRESS = getFieldOfType(networkManager, SocketAddress.class, false); - HANDSHAKE_PACKET = getClassOrFallBack( + HANDSHAKE_PACKET = getClassOrFallback( "net.minecraft.network.protocol.handshake.PacketHandshakingInSetProtocol", nmsPackage + "PacketHandshakingInSetProtocol" ); @@ -120,12 +121,12 @@ public class ClassNames { HANDSHAKE_HOST = getFieldOfType(HANDSHAKE_PACKET, String.class); checkNotNull(HANDSHAKE_HOST, "Handshake host"); - LOGIN_START_PACKET = getClassOrFallBack( + LOGIN_START_PACKET = getClassOrFallback( "net.minecraft.network.protocol.login.PacketLoginInStart", nmsPackage + "PacketLoginInStart" ); - LOGIN_LISTENER = getClassOrFallBack( + LOGIN_LISTENER = getClassOrFallback( "net.minecraft.server.network.LoginListener", nmsPackage + "LoginListener" ); @@ -146,14 +147,14 @@ public class ClassNames { INIT_UUID = getMethod(LOGIN_LISTENER, "initUUID"); checkNotNull(INIT_UUID, "initUUID from LoginListener"); - Class packetListenerClass = getClassOrFallBack( + Class packetListenerClass = getClassOrFallback( "net.minecraft.network.PacketListener", nmsPackage + "PacketListener" ); PACKET_LISTENER = getFieldOfType(networkManager, packetListenerClass); checkNotNull(PACKET_LISTENER, "Packet listener"); - LOGIN_HANDLER = getClassOrFallBack( + LOGIN_HANDLER = getClassOrFallback( "net.minecraft.server.network.LoginListener$LoginHandler", nmsPackage + "LoginListener$LoginHandler" ); @@ -188,25 +189,6 @@ public class ClassNames { paperConfig == null ? null : getField(paperConfig, "velocitySupport"); } - private static Class getClassOrFallBack(String className, String fallbackName) { - Class clazz = ReflectionUtils.getClassSilently(className); - - if (clazz != null) { - if (Constants.DEBUG_MODE) { - System.out.println("Found class (primary): " + clazz.getName()); - } - return clazz; - } - - // do throw an exception when both classes couldn't be found - clazz = ReflectionUtils.getClassOrThrow(fallbackName); - if (Constants.DEBUG_MODE) { - System.out.println("Found class (fallback): " + clazz.getName()); - } - - return clazz; - } - private static void checkNotNull(Object toCheck, String objectName) { Preconditions.checkNotNull(toCheck, objectName + " cannot be null"); }