1
0
mirror of https://github.com/GeyserMC/Floodgate.git synced 2026-01-04 15:31:48 +00:00

Made Floodgate dev compatible with latest Spigot & Velocity changes

This commit is contained in:
Tim203
2024-01-22 20:51:10 +01:00
parent ec5faf2065
commit 62296d8c5c
5 changed files with 87 additions and 31 deletions

View File

@@ -181,29 +181,34 @@ public final class SpigotDataHandler extends CommonNettyDataHandler {
}
}
// set the player his GameProfile, we can't change the username without this
GameProfile gameProfile = new GameProfile(connection.javaUuid(), connection.javaUsername());
setValue(packetListener, ClassNames.LOGIN_PROFILE, gameProfile);
// we have to fake the offline player (login) cycle
// just like on Spigot:
Object loginHandler = ClassNames.LOGIN_HANDLER_CONSTRUCTOR.newInstance(packetListener);
if (ClassNames.IS_PRE_1_20_2) {
// 1.20.1 and below
// LoginListener#initUUID
// new LoginHandler().fireEvents();
// - set profile, otherwise the username doesn't change
// - LoginListener#initUUID
// - new LoginHandler().fireEvents();
// and the tick of LoginListener will do the rest
Object loginHandler = ClassNames.LOGIN_HANDLER_CONSTRUCTOR.newInstance(packetListener);
setValue(packetListener, ClassNames.LOGIN_PROFILE, gameProfile);
ClassNames.INIT_UUID.invoke(packetListener);
ClassNames.FIRE_LOGIN_EVENTS.invoke(loginHandler);
} else {
// 1.20.2 and above we directly register the profile
} else if (!ClassNames.IS_POST_LOGIN_HANDLER) {
// 1.20.2 until somewhere in 1.20.4 we can directly register the profile
Object loginHandler = ClassNames.LOGIN_HANDLER_CONSTRUCTOR.newInstance(packetListener);
ClassNames.FIRE_LOGIN_EVENTS_GAME_PROFILE.invoke(loginHandler, gameProfile);
} else {
// somewhere during 1.20.4 md_5 moved stuff to CraftBukkit
// LoginListener#callPlayerPreLoginEvents(GameProfile)
// LoginListener#startClientVerification(GameProfile)
ClassNames.CALL_PLAYER_PRE_LOGIN_EVENTS.invoke(packetListener, gameProfile);
ClassNames.START_CLIENT_VERIFICATION.invoke(packetListener, gameProfile);
}
ctx.pipeline().remove(this);

View File

@@ -36,6 +36,8 @@ import static org.geysermc.floodgate.core.util.ReflectionUtils.getValue;
import static org.geysermc.floodgate.core.util.ReflectionUtils.invoke;
import static org.geysermc.floodgate.core.util.ReflectionUtils.makeAccessible;
import static org.geysermc.floodgate.spigot.util.MappingUtils.classFor;
import static org.geysermc.floodgate.spigot.util.MappingUtils.fieldFor;
import static org.geysermc.floodgate.spigot.util.MappingUtils.methodFor;
import com.mojang.authlib.GameProfile;
import io.netty.channel.ChannelHandlerContext;
@@ -58,11 +60,10 @@ public class ClassNames {
public static final Class<?> HANDSHAKE_PACKET;
public static final Class<?> LOGIN_START_PACKET;
public static final Class<?> LOGIN_LISTENER;
public static final Class<?> LOGIN_HANDLER;
@Nullable public static final Class<?> CLIENT_INTENT;
public static final Constructor<OfflinePlayer> CRAFT_OFFLINE_PLAYER_CONSTRUCTOR;
public static final Constructor<?> LOGIN_HANDLER_CONSTRUCTOR;
@Nullable public static final Constructor<?> LOGIN_HANDLER_CONSTRUCTOR;
@Nullable public static final Constructor<?> HANDSHAKE_PACKET_CONSTRUCTOR;
public static final Field SOCKET_ADDRESS;
@@ -83,13 +84,18 @@ public class ClassNames {
@Nullable public static final Method INIT_UUID;
@Nullable public static final Method FIRE_LOGIN_EVENTS;
@Nullable public static final Method FIRE_LOGIN_EVENTS_GAME_PROFILE;
@Nullable public static final Method CALL_PLAYER_PRE_LOGIN_EVENTS;
@Nullable public static final Method START_CLIENT_VERIFICATION;
public static final Field BUNGEE;
public static final boolean IS_FOLIA;
public static final boolean IS_PRE_1_20_2;
public static final boolean IS_POST_LOGIN_HANDLER;
static {
// ahhhhhhh, this class should really be reworked at this point
// SpigotSkinApplier
Class<?> craftPlayerClass = MappingUtils.craftbukkitClass("entity.CraftPlayer");
GET_PROFILE_METHOD = getMethod(craftPlayerClass, "getProfile");
@@ -154,6 +160,14 @@ public class ClassNames {
INIT_UUID = getMethod(LOGIN_LISTENER, "initUUID");
IS_PRE_1_20_2 = INIT_UUID != null;
// somewhere during 1.20.4 md_5 moved PreLogin logic to CraftBukkit
CALL_PLAYER_PRE_LOGIN_EVENTS = getMethod(
LOGIN_LISTENER,
"callPlayerPreLoginEvents",
GameProfile.class
);
IS_POST_LOGIN_HANDLER = CALL_PLAYER_PRE_LOGIN_EVENTS != null;
if (IS_PRE_1_20_2) {
Class<?> packetListenerClass = classFor("net.minecraft.network", "PacketListener");
PACKET_LISTENER = getFieldOfType(networkManager, packetListenerClass);
@@ -161,28 +175,41 @@ public class ClassNames {
// We get the field by name on 1.20.2+ as there are now multiple fields of this type in network manager
// PacketListener packetListener of NetworkManager
PACKET_LISTENER = MappingUtils.fieldFor(networkManager, "packetListener", "q");
PACKET_LISTENER = fieldFor(networkManager, "packetListener", "q");
makeAccessible(PACKET_LISTENER);
}
requireNonNull(PACKET_LISTENER, "Packet listener");
LOGIN_HANDLER = classFor(
"net.minecraft.server.network",
"ServerLoginPacketListenerImpl$LoginHandler",
"LoginListener$LoginHandler"
);
if (IS_POST_LOGIN_HANDLER) {
makeAccessible(CALL_PLAYER_PRE_LOGIN_EVENTS);
LOGIN_HANDLER_CONSTRUCTOR =
getConstructor(LOGIN_HANDLER, true, LOGIN_LISTENER);
requireNonNull(LOGIN_HANDLER_CONSTRUCTOR, "LoginHandler constructor");
START_CLIENT_VERIFICATION = methodFor(LOGIN_LISTENER, "startClientVerification", "b", GameProfile.class);
requireNonNull(START_CLIENT_VERIFICATION, "startClientVerification");
makeAccessible(START_CLIENT_VERIFICATION);
FIRE_LOGIN_EVENTS = getMethod(LOGIN_HANDLER, "fireEvents");
LOGIN_HANDLER_CONSTRUCTOR = null;
FIRE_LOGIN_EVENTS = null;
FIRE_LOGIN_EVENTS_GAME_PROFILE = null;
} else {
Class<?> loginHandler = classFor(
"net.minecraft.server.network",
"ServerLoginPacketListenerImpl$LoginHandler",
"LoginListener$LoginHandler"
);
// LoginHandler().fireEvents(GameProfile)
FIRE_LOGIN_EVENTS_GAME_PROFILE = getMethod(LOGIN_HANDLER, "fireEvents", GameProfile.class);
requireNonNull(FIRE_LOGIN_EVENTS, FIRE_LOGIN_EVENTS_GAME_PROFILE,
"fireEvents from LoginHandler", "fireEvents(GameProfile) from LoginHandler");
LOGIN_HANDLER_CONSTRUCTOR =
getConstructor(loginHandler, true, LOGIN_LISTENER);
requireNonNull(LOGIN_HANDLER_CONSTRUCTOR, "LoginHandler constructor");
FIRE_LOGIN_EVENTS = getMethod(loginHandler, "fireEvents");
// LoginHandler().fireEvents(GameProfile)
FIRE_LOGIN_EVENTS_GAME_PROFILE = getMethod(loginHandler, "fireEvents", GameProfile.class);
requireNonNull(FIRE_LOGIN_EVENTS, FIRE_LOGIN_EVENTS_GAME_PROFILE,
"fireEvents from LoginHandler", "fireEvents(GameProfile) from LoginHandler");
START_CLIENT_VERIFICATION = null;
}
PAPER_DISABLE_USERNAME_VALIDATION = getField(LOGIN_LISTENER,
"iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation");
@@ -249,11 +276,11 @@ public class ClassNames {
String.class, int.class, CLIENT_INTENT);
requireNonNull(HANDSHAKE_PACKET_CONSTRUCTOR, "Handshake packet constructor");
HANDSHAKE_PORT = MappingUtils.fieldFor(HANDSHAKE_PACKET, "port", "a");
HANDSHAKE_PORT = fieldFor(HANDSHAKE_PACKET, "port", "a");
requireNonNull(HANDSHAKE_PORT, "Handshake port");
makeAccessible(HANDSHAKE_PORT);
HANDSHAKE_PROTOCOL = MappingUtils.fieldFor(HANDSHAKE_PACKET, "protocolVersion", "c");
HANDSHAKE_PROTOCOL = fieldFor(HANDSHAKE_PACKET, "protocolVersion", "c");
requireNonNull(HANDSHAKE_PROTOCOL, "Handshake protocol");
makeAccessible(HANDSHAKE_PROTOCOL);

View File

@@ -1,6 +1,7 @@
package org.geysermc.floodgate.spigot.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.bukkit.Bukkit;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.floodgate.core.util.ReflectionUtils;
@@ -48,6 +49,18 @@ public class MappingUtils {
throw new IllegalStateException(genericMessage("field " + mojangName + " for class " + clazz));
}
public static Method methodFor(Class<?> clazz, String mojangName, String spigotName, Class<?>... args) {
var mojmap = ReflectionUtils.getMethod(clazz, mojangName, args);
if (mojmap != null) {
return mojmap;
}
var spigot = ReflectionUtils.getMethod(clazz, spigotName, args);
if (spigot != null) {
return spigot;
}
throw new IllegalStateException(genericMessage("method " + mojangName + " for class " + clazz));
}
private static String genericMessage(String specific) {
return "Could not find " + specific + ". What server software are you using?";
}

View File

@@ -27,6 +27,7 @@ package org.geysermc.floodgate.velocity.addon.data;
import static java.util.Objects.requireNonNull;
import static org.geysermc.floodgate.core.util.ReflectionUtils.getCastedValue;
import static org.geysermc.floodgate.core.util.ReflectionUtils.getClassOrFallbackPrefixed;
import static org.geysermc.floodgate.core.util.ReflectionUtils.getField;
import static org.geysermc.floodgate.core.util.ReflectionUtils.getMethodByName;
import static org.geysermc.floodgate.core.util.ReflectionUtils.getPrefixedClass;
@@ -65,7 +66,10 @@ public final class VelocityProxyDataHandler extends CommonNettyDataHandler {
HANDSHAKE = getField(iic, "handshake");
requireNonNull(HANDSHAKE, "Handshake field cannot be null");
HANDSHAKE_PACKET = getPrefixedClass("protocol.packet.Handshake");
HANDSHAKE_PACKET = getClassOrFallbackPrefixed(
"protocol.packet.HandshakePacket",
"protocol.packet.Handshake"
);
requireNonNull(HANDSHAKE_PACKET, "Handshake packet class cannot be null");
HANDSHAKE_SERVER_ADDRESS = getField(HANDSHAKE_PACKET, "serverAddress");
@@ -75,7 +79,10 @@ public final class VelocityProxyDataHandler extends CommonNettyDataHandler {
REMOTE_ADDRESS = getField(minecraftConnection, "remoteAddress");
requireNonNull(REMOTE_ADDRESS, "remoteAddress cannot be null");
SERVER_LOGIN_PACKET = getPrefixedClass("protocol.packet.ServerLogin");
SERVER_LOGIN_PACKET = getClassOrFallbackPrefixed(
"protocol.packet.ServerLoginPacket",
"protocol.packet.ServerLogin"
);
requireNonNull(SERVER_LOGIN_PACKET, "ServerLogin packet class cannot be null");

View File

@@ -28,6 +28,7 @@ package org.geysermc.floodgate.velocity.addon.data;
import static java.util.Objects.requireNonNull;
import static org.geysermc.floodgate.core.util.ReflectionUtils.castedInvoke;
import static org.geysermc.floodgate.core.util.ReflectionUtils.getCastedValue;
import static org.geysermc.floodgate.core.util.ReflectionUtils.getClassOrFallbackPrefixed;
import static org.geysermc.floodgate.core.util.ReflectionUtils.getField;
import static org.geysermc.floodgate.core.util.ReflectionUtils.getMethod;
import static org.geysermc.floodgate.core.util.ReflectionUtils.getPrefixedClass;
@@ -60,7 +61,10 @@ public final class VelocityServerDataHandler extends ChannelOutboundHandlerAdapt
private static final Method GET_PLAYER;
static {
HANDSHAKE_PACKET = getPrefixedClass("protocol.packet.Handshake");
HANDSHAKE_PACKET = getClassOrFallbackPrefixed(
"protocol.packet.HandshakePacket",
"protocol.packet.Handshake"
);
requireNonNull(HANDSHAKE_PACKET, "Handshake packet class cannot be null");
HANDSHAKE_ADDRESS = getField(HANDSHAKE_PACKET, "serverAddress");