From 1a07026c582f1c0f75ace18d3093efb79c8e170d Mon Sep 17 00:00:00 2001 From: Tim203 Date: Mon, 13 May 2024 12:01:04 +0200 Subject: [PATCH] Use less reflection on Velocity and fixed ChildFirstClassLoader --- buildSrc/src/main/kotlin/extensions.kt | 27 +++---- .../floodgate.shadow-conventions.gradle.kts | 4 +- core/build.gradle.kts | 2 + gradle.properties | 2 +- gradle/libs.versions.toml | 3 +- .../classloader/LibraryClassLoader.java | 4 + .../isolation/util/ChildFirstClassLoader.java | 79 ++++++------------- velocity/base/build.gradle.kts | 2 + .../addon/data/VelocityProxyDataHandler.java | 63 +++------------ .../addon/data/VelocityServerDataHandler.java | 51 ++---------- .../velocity/inject/VelocityInjector.java | 24 ++---- .../player/VelocityConnectionManager.java | 38 +++------ velocity/isolated/build.gradle.kts | 2 + 13 files changed, 86 insertions(+), 215 deletions(-) diff --git a/buildSrc/src/main/kotlin/extensions.kt b/buildSrc/src/main/kotlin/extensions.kt index 2d7040df..9a275738 100644 --- a/buildSrc/src/main/kotlin/extensions.kt +++ b/buildSrc/src/main/kotlin/extensions.kt @@ -26,7 +26,6 @@ import net.kyori.indra.git.IndraGitExtension import org.gradle.api.Project import org.gradle.api.artifacts.MinimalExternalModuleDependency -import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.provider.Provider import org.gradle.kotlin.dsl.the @@ -59,23 +58,20 @@ fun buildNumberAsString(): String = val providedDependencies = mutableMapOf>>() val relocatedPackages = mutableMapOf>() -fun Project.provided(pattern: String, name: String, version: String, excludedOn: Int = 0b110) { - val format = "${calcExclusion(pattern, 0b100, excludedOn)}:" + - "${calcExclusion(name, 0b10, excludedOn)}:" + - calcExclusion(version, 0b1, excludedOn) - +fun Project.providedDependency(dependency: MinimalExternalModuleDependency) { + val format = "${dependency.group}:${dependency.name}:" providedDependencies.getOrPut(project.name) { mutableSetOf() }.add(Pair(format, format)) - dependencies.add("compileOnlyApi", "$pattern:$name:$version") } -fun Project.provided(dependency: ProjectDependency) { - providedDependencies.getOrPut(project.name) { mutableSetOf() } - .add(Pair(dependency.group + ":" + dependency.name, dependency)) - dependencies.add("compileOnlyApi", dependency) -} +fun Project.providedDependency(provider: Provider) = + providedDependency(provider.get()) -fun Project.provided(dependency: MinimalExternalModuleDependency) = - provided(dependency.module.group, dependency.module.name, dependency.versionConstraint.requiredVersion) +fun Project.provided(dependency: MinimalExternalModuleDependency) { + providedDependency(dependency) + dependencies.add("compileOnlyApi", + "${dependency.group}:${dependency.name}:${dependency.versionConstraint.requiredVersion}" + ) +} fun Project.provided(provider: Provider) = provided(provider.get()) @@ -83,6 +79,3 @@ fun Project.provided(provider: Provider) = fun Project.relocate(pattern: String) = relocatedPackages.getOrPut(project.name) { mutableSetOf() } .add(pattern) - -private fun calcExclusion(section: String, bit: Int, excludedOn: Int): String = - if (excludedOn and bit > 0) section else "" \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/floodgate.shadow-conventions.gradle.kts b/buildSrc/src/main/kotlin/floodgate.shadow-conventions.gradle.kts index bb2c95b0..e173529c 100644 --- a/buildSrc/src/main/kotlin/floodgate.shadow-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/floodgate.shadow-conventions.gradle.kts @@ -21,8 +21,8 @@ tasks { doFirst { mergeServiceFiles() - providedDependencies[project.name]?.forEach { (name, notation) -> - sJar.dependencies { + sJar.dependencies { + providedDependencies[project.name]?.forEach { (name, notation) -> println("Excluding $name from ${project.name}") exclude(dependency(notation)) } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index ba2ee8d6..fb2d5412 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -41,7 +41,9 @@ dependencies { // present on all platforms provided(libs.netty.transport) provided(libs.netty.codec) +providedDependency(libs.slf4j) +// we're isolated but bstats doesn't know that relocate("org.bstats") tasks { diff --git a/gradle.properties b/gradle.properties index 617bb8d5..06db680e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,5 +2,5 @@ org.gradle.configureondemand=true org.gradle.caching=true org.gradle.parallel=true -version=2.2.2-SNAPSHOT +version=3.0.0-SNAPSHOT micronautVersion=4.3.1 \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f7236b47..23349982 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,7 +28,7 @@ paper = "1.20.2-R0.1-SNAPSHOT" authlib = "5.0.47" # velocity -velocity = "3.2.0-SNAPSHOT" +velocity = "3.3.0-SNAPSHOT" # buildSrc indra = "3.1.3" @@ -93,6 +93,7 @@ authlib = { module = "com.mojang:authlib", version.ref = "authlib" } # velocity cloud-velocity = { module = "org.incendo:cloud-velocity", version.ref = "cloud" } velocity-api = { module = "com.velocitypowered:velocity-api", version.ref = "velocity" } +velocity-proxy = { module = "com.velocitypowered:velocity-proxy", version.ref = "velocity" } # buildSrc checker-qual = { module = "org.checkerframework:checker-qual", version.ref = "checkerframework" } diff --git a/isolation/src/main/java/org/geysermc/floodgate/isolation/library/classloader/LibraryClassLoader.java b/isolation/src/main/java/org/geysermc/floodgate/isolation/library/classloader/LibraryClassLoader.java index eea69c95..74652600 100644 --- a/isolation/src/main/java/org/geysermc/floodgate/isolation/library/classloader/LibraryClassLoader.java +++ b/isolation/src/main/java/org/geysermc/floodgate/isolation/library/classloader/LibraryClassLoader.java @@ -61,4 +61,8 @@ public class LibraryClassLoader extends URLClassLoader { public boolean isLoaded(Path path) { return loadedPaths.contains(path); } + + static { + ClassLoader.registerAsParallelCapable(); + } } diff --git a/isolation/src/main/java/org/geysermc/floodgate/isolation/util/ChildFirstClassLoader.java b/isolation/src/main/java/org/geysermc/floodgate/isolation/util/ChildFirstClassLoader.java index 115d4e68..a2cd8423 100644 --- a/isolation/src/main/java/org/geysermc/floodgate/isolation/util/ChildFirstClassLoader.java +++ b/isolation/src/main/java/org/geysermc/floodgate/isolation/util/ChildFirstClassLoader.java @@ -28,98 +28,65 @@ package org.geysermc.floodgate.isolation.util; import java.io.IOException; import java.net.URL; import java.util.Enumeration; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; import java.util.Objects; import org.geysermc.floodgate.isolation.library.classloader.LibraryClassLoader; -// Based of a Medium article https://medium.com/@isuru89/java-a-child-first-class-loader-cbd9c3d0305 public class ChildFirstClassLoader extends LibraryClassLoader { - private final ClassLoader systemClassLoader; - public ChildFirstClassLoader(ClassLoader parent) { super(Objects.requireNonNull(parent)); - systemClassLoader = getSystemClassLoader(); } @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - Class loadedClass = findLoadedClass(name); - if (loadedClass == null) { - try { - if (systemClassLoader != null) { - loadedClass = systemClassLoader.loadClass(name); - } - } catch (ClassNotFoundException ignored) {} - - try { - if (loadedClass == null) { + synchronized (getClassLoadingLock(name)) { + Class loadedClass = findLoadedClass(name); + if (loadedClass == null) { + // actual Java system classes (like java.lang.Integer) should be loaded by the parent classloader, + // which does use the system class loader (unlike us). findClass only returns its own classes. + // We don't call the system class loader ourselves since e.g. on Velocity, Velocity is the system. + // This resulted in Velocity overriding our own Configurate version for example + try { loadedClass = findClass(name); + } catch (ClassNotFoundException ignored) { + loadedClass = super.loadClass(name, resolve); } - } catch (ClassNotFoundException e) { - loadedClass = super.loadClass(name, resolve); } - } - if (resolve) { - resolveClass(loadedClass); + if (resolve) { + resolveClass(loadedClass); + } + return loadedClass; } - return loadedClass; } @Override public Enumeration getResources(String name) throws IOException { - List allResources = new LinkedList<>(); - - Enumeration systemResources = systemClassLoader.getResources(name); - if (systemResources != null) { - while (systemResources.hasMoreElements()) { - allResources.add(systemResources.nextElement()); - } - } - - Enumeration thisResources = findResources(name); - if (thisResources != null) { - while (thisResources.hasMoreElements()) { - allResources.add(thisResources.nextElement()); - } - } - - Enumeration parentResources = getParent().getResources(name); - if (parentResources != null) { - while (parentResources.hasMoreElements()) { - allResources.add(parentResources.nextElement()); - } - } - return new Enumeration<>() { - final Iterator it = allResources.iterator(); + final Enumeration thisResources = findResources(name); + final Enumeration parentResources = getParent().getResources(name); @Override public boolean hasMoreElements() { - return it.hasNext(); + return thisResources.hasMoreElements() || parentResources.hasMoreElements(); } @Override public URL nextElement() { - return it.next(); + return thisResources.hasMoreElements() ? thisResources.nextElement() : parentResources.nextElement(); } }; } @Override public URL getResource(String name) { - URL resource = null; - if (systemClassLoader != null) { - resource = systemClassLoader.getResource(name); - } - if (resource == null) { - resource = findResource(name); - } + URL resource = findResource(name); if (resource == null) { resource = getParent().getResource(name); } return resource; } + + static { + ClassLoader.registerAsParallelCapable(); + } } diff --git a/velocity/base/build.gradle.kts b/velocity/base/build.gradle.kts index 88ad2c49..43333b1f 100644 --- a/velocity/base/build.gradle.kts +++ b/velocity/base/build.gradle.kts @@ -17,3 +17,5 @@ relocate("org.yaml.snakeyaml") // these dependencies are already present on the platform provided(libs.gson) provided(libs.velocity.api) +provided(libs.velocity.proxy) +providedDependency(libs.slf4j) diff --git a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityProxyDataHandler.java b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityProxyDataHandler.java index 7aee850a..5f47a01c 100644 --- a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityProxyDataHandler.java +++ b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityProxyDataHandler.java @@ -26,18 +26,18 @@ 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; -import static org.geysermc.floodgate.core.util.ReflectionUtils.invoke; import static org.geysermc.floodgate.core.util.ReflectionUtils.setValue; +import com.velocitypowered.proxy.connection.MinecraftConnection; +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.connection.client.InitialLoginSessionHandler; +import com.velocitypowered.proxy.protocol.packet.HandshakePacket; +import com.velocitypowered.proxy.protocol.packet.ServerLoginPacket; import io.netty.channel.Channel; import io.netty.util.AttributeKey; import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.net.InetSocketAddress; import org.geysermc.api.connection.Connection; import org.geysermc.floodgate.core.addon.data.CommonNettyDataHandler; @@ -49,51 +49,16 @@ import org.geysermc.floodgate.core.connection.FloodgateDataHandler.HandleResult; import org.geysermc.floodgate.core.logger.FloodgateLogger; public final class VelocityProxyDataHandler extends CommonNettyDataHandler { - private static final Field HANDSHAKE; - private static final Class HANDSHAKE_PACKET; - private static final Field HANDSHAKE_SERVER_ADDRESS; private static final Field REMOTE_ADDRESS; - private static final Class SERVER_LOGIN_PACKET; - private static final Method GET_SESSION_HANDLER; private static final Class INITIAL_LOGIN_SESSION_HANDLER; private static final Field FORCE_KEY_AUTHENTICATION; static { - Class iic = getPrefixedClass("connection.client.InitialInboundConnection"); - requireNonNull(iic, "InitialInboundConnection class cannot be null"); - - HANDSHAKE = getField(iic, "handshake"); - requireNonNull(HANDSHAKE, "Handshake field cannot be null"); - - 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"); - requireNonNull(HANDSHAKE_SERVER_ADDRESS, "Address in the Handshake packet cannot be null"); - Class minecraftConnection = getPrefixedClass("connection.MinecraftConnection"); REMOTE_ADDRESS = getField(minecraftConnection, "remoteAddress"); requireNonNull(REMOTE_ADDRESS, "remoteAddress cannot be null"); - SERVER_LOGIN_PACKET = getClassOrFallbackPrefixed( - "protocol.packet.ServerLoginPacket", - "protocol.packet.ServerLogin" - ); - requireNonNull(SERVER_LOGIN_PACKET, "ServerLogin packet class cannot be null"); - - - Method sessionHandler = getMethodByName(minecraftConnection, "getActiveSessionHandler", true); - if (sessionHandler == null) { - // We are pre-1.20.2 - sessionHandler = getMethodByName(minecraftConnection, "getSessionHandler", true); - } - GET_SESSION_HANDLER = sessionHandler; - requireNonNull(GET_SESSION_HANDLER, "getSessionHandler method cannot be null"); - INITIAL_LOGIN_SESSION_HANDLER = getPrefixedClass("connection.client.InitialLoginSessionHandler"); requireNonNull(INITIAL_LOGIN_SESSION_HANDLER, "InitialLoginSessionHandler cannot be null"); @@ -122,7 +87,7 @@ public final class VelocityProxyDataHandler extends CommonNettyDataHandler { @Override protected Object setHostname(Object handshakePacket, String hostname) { - setValue(handshakePacket, HANDSHAKE_SERVER_ADDRESS, hostname); + ((HandshakePacket) handshakePacket).setServerAddress(hostname); return handshakePacket; } @@ -138,23 +103,21 @@ public final class VelocityProxyDataHandler extends CommonNettyDataHandler { @Override public boolean channelRead(Object packet) { - if (HANDSHAKE_PACKET.isInstance(packet)) { - handle(packet, getCastedValue(packet, HANDSHAKE_SERVER_ADDRESS)); + if (packet instanceof HandshakePacket handshake) { + handle(packet, handshake.getServerAddress()); // otherwise, it'll get read twice. once by the packet queue and once by this method return false; } // at this point we know that forceKeyAuthentication is enabled - if (SERVER_LOGIN_PACKET.isInstance(packet)) { - Object minecraftConnection = ctx.pipeline().get("handler"); - Object sessionHandler = invoke(minecraftConnection, GET_SESSION_HANDLER); - if (!INITIAL_LOGIN_SESSION_HANDLER.isInstance(sessionHandler)) { + if (packet instanceof ServerLoginPacket) { + MinecraftConnection minecraftConnection = (MinecraftConnection) ctx.pipeline().get("handler"); + MinecraftSessionHandler sessionHandler = minecraftConnection.getActiveSessionHandler(); + if (!(sessionHandler instanceof InitialLoginSessionHandler)) { logger.error("Expected player's session handler to be InitialLoginSessionHandler"); return true; } - if (FORCE_KEY_AUTHENTICATION != null) { - setValue(sessionHandler, FORCE_KEY_AUTHENTICATION, false); - } + setValue(sessionHandler, FORCE_KEY_AUTHENTICATION, false); } return true; } diff --git a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityServerDataHandler.java b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityServerDataHandler.java index dcc68d5c..5707f62e 100644 --- a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityServerDataHandler.java +++ b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityServerDataHandler.java @@ -25,17 +25,9 @@ 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; -import static org.geysermc.floodgate.core.util.ReflectionUtils.invoke; -import static org.geysermc.floodgate.core.util.ReflectionUtils.setValue; - import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.proxy.connection.MinecraftConnection; +import com.velocitypowered.proxy.protocol.packet.HandshakePacket; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelOutboundHandlerAdapter; @@ -44,8 +36,6 @@ import io.netty.util.AttributeKey; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; -import java.lang.reflect.Field; -import java.lang.reflect.Method; import org.geysermc.api.connection.Connection; import org.geysermc.floodgate.core.api.SimpleFloodgateApi; import org.geysermc.floodgate.core.connection.FloodgateConnection; @@ -55,32 +45,6 @@ import org.geysermc.floodgate.core.crypto.FloodgateDataCodec; @ChannelHandler.Sharable @SuppressWarnings("ConstantConditions") public final class VelocityServerDataHandler extends ChannelOutboundHandlerAdapter { - private static final Class HANDSHAKE_PACKET; - private static final Field HANDSHAKE_ADDRESS; - private static final Method GET_ASSOCIATION; - private static final Method GET_PLAYER; - - static { - HANDSHAKE_PACKET = getClassOrFallbackPrefixed( - "protocol.packet.HandshakePacket", - "protocol.packet.Handshake" - ); - requireNonNull(HANDSHAKE_PACKET, "Handshake packet class cannot be null"); - - HANDSHAKE_ADDRESS = getField(HANDSHAKE_PACKET, "serverAddress"); - requireNonNull(HANDSHAKE_ADDRESS, "Address field of the Handshake packet cannot be null"); - - Class minecraftConnection = getPrefixedClass("connection.MinecraftConnection"); - - GET_ASSOCIATION = getMethod(minecraftConnection, "getAssociation"); - requireNonNull(GET_ASSOCIATION, "getAssociation in MinecraftConnection cannot be null"); - - Class serverConnection = getPrefixedClass("connection.backend.VelocityServerConnection"); - - GET_PLAYER = getMethod(serverConnection, "getPlayer"); - requireNonNull(GET_PLAYER, "getPlayer in VelocityServerConnection cannot be null"); - } - @Inject SimpleFloodgateApi api; @Inject FloodgateDataCodec dataCodec; @@ -90,16 +54,15 @@ public final class VelocityServerDataHandler extends ChannelOutboundHandlerAdapt @Override public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { - if (HANDSHAKE_PACKET.isInstance(packet)) { - String address = getCastedValue(packet, HANDSHAKE_ADDRESS); + if (packet instanceof HandshakePacket handshake) { + String address = handshake.getServerAddress(); // The connection to the backend server is not the same connection as the client to the proxy. // This gets the client to proxy Connection from the backend server connection. // get the FloodgatePlayer from the ConnectedPlayer - Object minecraftConnection = ctx.pipeline().get("handler"); - Object association = invoke(minecraftConnection, GET_ASSOCIATION); - Player velocityPlayer = castedInvoke(association, GET_PLAYER); + MinecraftConnection minecraftConnection = (MinecraftConnection) ctx.pipeline().get("handler"); + Player velocityPlayer = (Player) minecraftConnection.getAssociation(); Connection connection = api.connectionByPlatformIdentifier(velocityPlayer); if (connection != null) { @@ -120,7 +83,7 @@ public final class VelocityServerDataHandler extends ChannelOutboundHandlerAdapt remaining = address.substring(addressFinished); } - setValue(packet, HANDSHAKE_ADDRESS, originalAddress + '\0' + encodedData + remaining); + handshake.setServerAddress(originalAddress + '\0' + encodedData + remaining); } ctx.pipeline().remove(this); diff --git a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/inject/VelocityInjector.java b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/inject/VelocityInjector.java index 2f0eb800..339c7148 100644 --- a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/inject/VelocityInjector.java +++ b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/inject/VelocityInjector.java @@ -25,12 +25,12 @@ package org.geysermc.floodgate.velocity.inject; -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.getMethod; -import static org.geysermc.floodgate.core.util.ReflectionUtils.getValue; import static org.geysermc.floodgate.core.util.ReflectionUtils.invoke; import com.velocitypowered.api.proxy.ProxyServer; +import com.velocitypowered.proxy.network.ConnectionManager; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; import jakarta.inject.Inject; @@ -46,31 +46,23 @@ public final class VelocityInjector extends CommonPlatformInjector { @Getter private boolean injected; @Override - @SuppressWarnings("rawtypes") + @SuppressWarnings({"DataFlowIssue", "deprecation"}) public void inject() { if (isInjected()) { return; } - Object connectionManager = getValue(server, "cm"); + ConnectionManager connectionManager = getCastedValue(server, "cm"); // Client <-> Proxy - Object serverInitializerHolder = getValue(connectionManager, "serverChannelInitializer"); - ChannelInitializer serverInitializer = castedInvoke(serverInitializerHolder, "get"); - - Method serverSetter = getMethod(serverInitializerHolder, "set", ChannelInitializer.class); - invoke(serverInitializerHolder, serverSetter, - new VelocityChannelInitializer(this, serverInitializer, false)); + var serverChannelInitializer = connectionManager.serverChannelInitializer; + serverChannelInitializer.set(new VelocityChannelInitializer(this, serverChannelInitializer.get(), false)); // Proxy <-> Server - Object backendInitializerHolder = getValue(connectionManager, "backendChannelInitializer"); - ChannelInitializer backendInitializer = castedInvoke(backendInitializerHolder, "get"); - - Method backendSetter = getMethod(backendInitializerHolder, "set", ChannelInitializer.class); - invoke(backendInitializerHolder, backendSetter, - new VelocityChannelInitializer(this, backendInitializer, true)); + var backendChannelInitializer = connectionManager.backendChannelInitializer; + backendChannelInitializer.set(new VelocityChannelInitializer(this, backendChannelInitializer.get(), true)); injected = true; } diff --git a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/player/VelocityConnectionManager.java b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/player/VelocityConnectionManager.java index 0d94204b..1e31147e 100644 --- a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/player/VelocityConnectionManager.java +++ b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/player/VelocityConnectionManager.java @@ -26,20 +26,18 @@ package org.geysermc.floodgate.velocity.player; import static org.geysermc.floodgate.core.util.ReflectionUtils.getField; -import static org.geysermc.floodgate.core.util.ReflectionUtils.getFieldOfType; -import static org.geysermc.floodgate.core.util.ReflectionUtils.getMethod; import static org.geysermc.floodgate.core.util.ReflectionUtils.getPrefixedClass; import static org.geysermc.floodgate.core.util.ReflectionUtils.getValue; -import static org.geysermc.floodgate.core.util.ReflectionUtils.invoke; -import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.proxy.connection.MinecraftConnection; +import com.velocitypowered.proxy.connection.client.LoginInboundConnection; +import com.velocitypowered.proxy.connection.util.VelocityInboundConnection; import io.netty.channel.Channel; import io.netty.util.AttributeKey; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import java.lang.reflect.Field; -import java.lang.reflect.Method; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.api.connection.Connection; import org.geysermc.floodgate.core.connection.ConnectionManager; @@ -48,10 +46,6 @@ import org.geysermc.floodgate.core.connection.ConnectionManager; public class VelocityConnectionManager extends ConnectionManager { private static final Class LOGIN_INBOUND_CONNECTION; private static final Field INITIAL_CONNECTION_DELEGATE; - private static final Class INITIAL_INBOUND_CONNECTION; - private static final Class MINECRAFT_CONNECTION; - private static final Method GET_CONNECTION; - private static final Field CHANNEL; @Inject @Named("connectionAttribute") @@ -59,25 +53,21 @@ public class VelocityConnectionManager extends ConnectionManager { @Override protected @Nullable Object platformIdentifierOrConnectionFor(Object input) { - if (input instanceof Player) { - // ConnectedPlayer implements VelocityInboundConnection, - // just like InitialInboundConnection - return invoke(input, GET_CONNECTION); + // ConnectedPlayer (Player) implements VelocityInboundConnection, + // just like InitialInboundConnection + if (input instanceof VelocityInboundConnection connection) { + return connection.getConnection(); } // LoginInboundConnection doesn't have a direct Channel reference, // but it does have an InitialInboundConnection reference - if (LOGIN_INBOUND_CONNECTION.isInstance(input)) { + if (input instanceof LoginInboundConnection) { return getValue(input, INITIAL_CONNECTION_DELEGATE); } // InitialInboundConnection -> MinecraftConnection -> Channel -> FloodgateConnection attribute - - if (INITIAL_INBOUND_CONNECTION.isInstance(input)) { - return invoke(input, GET_CONNECTION); - } - if (MINECRAFT_CONNECTION.isInstance(input)) { - return getValue(input, CHANNEL); + if (input instanceof MinecraftConnection connection) { + return connection.getChannel(); } if (input instanceof Channel channel) { return channel.attr(connectionAttribute).get(); @@ -96,13 +86,5 @@ public class VelocityConnectionManager extends ConnectionManager { static { LOGIN_INBOUND_CONNECTION = getPrefixedClass("connection.client.LoginInboundConnection"); INITIAL_CONNECTION_DELEGATE = getField(LOGIN_INBOUND_CONNECTION, "delegate"); - - INITIAL_INBOUND_CONNECTION = getPrefixedClass("connection.client.InitialInboundConnection"); - MINECRAFT_CONNECTION = getPrefixedClass("connection.MinecraftConnection"); - - Class velocityInboundConnection = getPrefixedClass("connection.util.VelocityInboundConnection"); - GET_CONNECTION = getMethod(velocityInboundConnection, "getConnection"); - - CHANNEL = getFieldOfType(MINECRAFT_CONNECTION, Channel.class); } } diff --git a/velocity/isolated/build.gradle.kts b/velocity/isolated/build.gradle.kts index b32b885c..2a2d9f6b 100644 --- a/velocity/isolated/build.gradle.kts +++ b/velocity/isolated/build.gradle.kts @@ -7,6 +7,8 @@ dependencies { compileOnlyApi(libs.velocity.api) } +providedDependency(libs.slf4j) + tasks { jar { dependsOn(":velocity-base:build", configurations.runtimeClasspath)