1
0
mirror of https://github.com/GeyserMC/Floodgate.git synced 2025-12-22 16:29:25 +00:00

Re-added support for BungeeCord 1.18

Metrics showed that more than 33% of the BungeeCord platform users still use a 1.18.x version
This commit is contained in:
Tim203
2022-06-11 14:12:13 +02:00
parent 5d5713ed9e
commit af4030ac12
4 changed files with 71 additions and 37 deletions

View File

@@ -29,7 +29,6 @@ object Versions {
const val configUtilsVersion = "1.0-SNAPSHOT" const val configUtilsVersion = "1.0-SNAPSHOT"
const val spigotVersion = "1.13-R0.1-SNAPSHOT" const val spigotVersion = "1.13-R0.1-SNAPSHOT"
const val fastutilVersion = "8.5.3" const val fastutilVersion = "8.5.3"
const val lombokVersion = "1.18.20"
const val guiceVersion = "5.0.1" const val guiceVersion = "5.0.1"
const val nettyVersion = "4.1.49.Final" const val nettyVersion = "4.1.49.Final"
const val snakeyamlVersion = "1.28" const val snakeyamlVersion = "1.28"

View File

@@ -25,27 +25,48 @@
package org.geysermc.floodgate.pluginmessage; 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.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.Field;
import java.lang.reflect.Method;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.connection.InitialHandler; import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.connection.LoginResult; 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.logger.FloodgateLogger;
import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.geysermc.floodgate.skin.SkinApplier; import org.geysermc.floodgate.skin.SkinApplier;
import org.geysermc.floodgate.skin.SkinData; import org.geysermc.floodgate.skin.SkinData;
import org.geysermc.floodgate.util.ReflectionUtils;
@RequiredArgsConstructor @RequiredArgsConstructor
public final class BungeeSkinApplier implements SkinApplier { 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 { 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; private final FloodgateLogger logger;
@@ -71,11 +92,17 @@ public final class BungeeSkinApplier implements SkinApplier {
if (loginResult == null) { if (loginResult == null) {
// id and name are unused and properties will be overridden // id and name are unused and properties will be overridden
loginResult = new LoginResult(null, null, null); 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);
} }
} }

View File

@@ -46,6 +46,10 @@ public final class ReflectionUtils {
@Setter @Setter
private static String prefix; 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 * 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 <i>prefix</i>.<i>classname</i> * this method is equal to calling {@link #getClass(String)} with <i>prefix</i>.<i>classname</i>
@@ -56,13 +60,13 @@ public final class ReflectionUtils {
*/ */
@Nullable @Nullable
public static Class<?> getPrefixedClass(String className) { public static Class<?> getPrefixedClass(String className) {
return getClass(prefix + "." + className); return getClass(applyPrefix(className));
} }
@Nullable @Nullable
public static Class<?> getPrefixedClassSilently(String className) { public static Class<?> getPrefixedClassSilently(String className) {
try { try {
return Class.forName(prefix + "." + className); return Class.forName(applyPrefix(className));
} catch (ClassNotFoundException ignored) { } catch (ClassNotFoundException ignored) {
return null; 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 @Nullable
public static <T> Constructor<T> getConstructor(Class<T> clazz, boolean declared, Class<?>... parameters) { public static <T> Constructor<T> getConstructor(Class<T> clazz, boolean declared, Class<?>... parameters) {
try { try {

View File

@@ -25,6 +25,7 @@
package org.geysermc.floodgate.util; 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.getField;
import static org.geysermc.floodgate.util.ReflectionUtils.getFieldOfType; import static org.geysermc.floodgate.util.ReflectionUtils.getFieldOfType;
import static org.geysermc.floodgate.util.ReflectionUtils.getMethod; import static org.geysermc.floodgate.util.ReflectionUtils.getMethod;
@@ -85,12 +86,12 @@ public class ClassNames {
// SpigotInjector // SpigotInjector
MINECRAFT_SERVER = getClassOrFallBack( MINECRAFT_SERVER = getClassOrFallback(
"net.minecraft.server.MinecraftServer", "net.minecraft.server.MinecraftServer",
nmsPackage + "MinecraftServer" nmsPackage + "MinecraftServer"
); );
SERVER_CONNECTION = getClassOrFallBack( SERVER_CONNECTION = getClassOrFallback(
"net.minecraft.server.network.ServerConnection", "net.minecraft.server.network.ServerConnection",
nmsPackage + "ServerConnection" nmsPackage + "ServerConnection"
); );
@@ -105,14 +106,14 @@ public class ClassNames {
craftOfflinePlayerClass, true, craftServerClass, GameProfile.class); craftOfflinePlayerClass, true, craftServerClass, GameProfile.class);
// SpigotDataHandler // SpigotDataHandler
Class<?> networkManager = getClassOrFallBack( Class<?> networkManager = getClassOrFallback(
"net.minecraft.network.NetworkManager", "net.minecraft.network.NetworkManager",
nmsPackage + "NetworkManager" nmsPackage + "NetworkManager"
); );
SOCKET_ADDRESS = getFieldOfType(networkManager, SocketAddress.class, false); SOCKET_ADDRESS = getFieldOfType(networkManager, SocketAddress.class, false);
HANDSHAKE_PACKET = getClassOrFallBack( HANDSHAKE_PACKET = getClassOrFallback(
"net.minecraft.network.protocol.handshake.PacketHandshakingInSetProtocol", "net.minecraft.network.protocol.handshake.PacketHandshakingInSetProtocol",
nmsPackage + "PacketHandshakingInSetProtocol" nmsPackage + "PacketHandshakingInSetProtocol"
); );
@@ -120,12 +121,12 @@ public class ClassNames {
HANDSHAKE_HOST = getFieldOfType(HANDSHAKE_PACKET, String.class); HANDSHAKE_HOST = getFieldOfType(HANDSHAKE_PACKET, String.class);
checkNotNull(HANDSHAKE_HOST, "Handshake host"); checkNotNull(HANDSHAKE_HOST, "Handshake host");
LOGIN_START_PACKET = getClassOrFallBack( LOGIN_START_PACKET = getClassOrFallback(
"net.minecraft.network.protocol.login.PacketLoginInStart", "net.minecraft.network.protocol.login.PacketLoginInStart",
nmsPackage + "PacketLoginInStart" nmsPackage + "PacketLoginInStart"
); );
LOGIN_LISTENER = getClassOrFallBack( LOGIN_LISTENER = getClassOrFallback(
"net.minecraft.server.network.LoginListener", "net.minecraft.server.network.LoginListener",
nmsPackage + "LoginListener" nmsPackage + "LoginListener"
); );
@@ -146,14 +147,14 @@ public class ClassNames {
INIT_UUID = getMethod(LOGIN_LISTENER, "initUUID"); INIT_UUID = getMethod(LOGIN_LISTENER, "initUUID");
checkNotNull(INIT_UUID, "initUUID from LoginListener"); checkNotNull(INIT_UUID, "initUUID from LoginListener");
Class<?> packetListenerClass = getClassOrFallBack( Class<?> packetListenerClass = getClassOrFallback(
"net.minecraft.network.PacketListener", "net.minecraft.network.PacketListener",
nmsPackage + "PacketListener" nmsPackage + "PacketListener"
); );
PACKET_LISTENER = getFieldOfType(networkManager, packetListenerClass); PACKET_LISTENER = getFieldOfType(networkManager, packetListenerClass);
checkNotNull(PACKET_LISTENER, "Packet listener"); checkNotNull(PACKET_LISTENER, "Packet listener");
LOGIN_HANDLER = getClassOrFallBack( LOGIN_HANDLER = getClassOrFallback(
"net.minecraft.server.network.LoginListener$LoginHandler", "net.minecraft.server.network.LoginListener$LoginHandler",
nmsPackage + "LoginListener$LoginHandler" nmsPackage + "LoginListener$LoginHandler"
); );
@@ -188,25 +189,6 @@ public class ClassNames {
paperConfig == null ? null : getField(paperConfig, "velocitySupport"); 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) { private static void checkNotNull(Object toCheck, String objectName) {
Preconditions.checkNotNull(toCheck, objectName + " cannot be null"); Preconditions.checkNotNull(toCheck, objectName + " cannot be null");
} }