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");
}