From 0c3e8658ff3a1235fad0f4202bf34c34ad7383e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Kr=C3=BCger?= Date: Fri, 1 Nov 2024 12:35:23 +0100 Subject: [PATCH] fix(spigot): look up fields/methods based on type and predicate instead of hardcoding obfuscated field names --- gradle.properties | 2 +- .../mcbrawls/inject/spigot/InjectSpigot.java | 14 ++++++++++ .../ClientConnectionInterceptor.java | 26 ++++++++++++++++--- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/gradle.properties b/gradle.properties index bc0dd3d..27992e8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ yarn_mappings=1.21.1+build.3 loader_version=0.16.7 # Mod Properties -version=2.1.0 +version=2.1.1 group=net.mcbrawls.inject id=inject diff --git a/spigot/src/main/java/net/mcbrawls/inject/spigot/InjectSpigot.java b/spigot/src/main/java/net/mcbrawls/inject/spigot/InjectSpigot.java index 698e3ac..324ff9a 100644 --- a/spigot/src/main/java/net/mcbrawls/inject/spigot/InjectSpigot.java +++ b/spigot/src/main/java/net/mcbrawls/inject/spigot/InjectSpigot.java @@ -17,11 +17,25 @@ public class InjectSpigot implements InjectPlatform { private InjectSpigot() { } + private boolean isRunningPaper() { + try { + Class.forName("com.destroystokyo.paper.PaperConfig"); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + @Override public void registerInjector(Injector injector) { injectors.add(injector); if (!hasInitialized) { + if (isRunningPaper()) { + LOGGER.warning("It looks like you are running Paper - Inject Spigot is unsupported on Paper!"); + LOGGER.warning("Please use Inject Paper instead!"); + } + new ClientConnectionInterceptor().install((channel) -> { var pipeline = channel.pipeline(); injectors.forEach(pipeline::addFirst); diff --git a/spigot/src/main/java/net/mcbrawls/inject/spigot/interceptor/ClientConnectionInterceptor.java b/spigot/src/main/java/net/mcbrawls/inject/spigot/interceptor/ClientConnectionInterceptor.java index a080186..51a6a12 100644 --- a/spigot/src/main/java/net/mcbrawls/inject/spigot/interceptor/ClientConnectionInterceptor.java +++ b/spigot/src/main/java/net/mcbrawls/inject/spigot/interceptor/ClientConnectionInterceptor.java @@ -6,8 +6,11 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; import java.util.List; import java.util.function.Consumer; +import java.util.function.Function; public class ClientConnectionInterceptor { @@ -44,6 +47,22 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception } } + private Method getMethodByReturnType(Class clazz, Class returnType) { + return Arrays.stream(clazz.getDeclaredMethods()) + .filter((method) -> method.getReturnType().equals(returnType)) + .findFirst() + .get(); + } + + // Predicate is needed to make sure we find the `List channels` instead of `List connections` + // since `channels` is private. + private Field getFieldByTypeAndPredicate(Class clazz, Class type, Function predicate) { + return Arrays.stream(clazz.getDeclaredFields()) + .filter((field) -> field.getType().equals(type) && predicate.apply(field)) + .findFirst() + .get(); + } + private List getChannels() { final String serverVersion = this.getServerVersion(); @@ -55,15 +74,14 @@ private List getChannels() { final Method craftServerGetServerMethod = craftServerClass.getDeclaredMethod("getServer"); final Object minecraftServer = craftServerGetServerMethod.invoke(craftServerObject); - final Method getConnectionMethod = minecraftServerClass.getDeclaredMethod("ai"); + final Method getConnectionMethod = getMethodByReturnType(minecraftServerClass, Class.forName("net.minecraft.server.network.ServerConnection")); final Object serverConnection = getConnectionMethod.invoke(minecraftServer); - final Field channelsField = serverConnection.getClass().getDeclaredField("f"); + final Field channelsField = getFieldByTypeAndPredicate(serverConnection.getClass(), List.class, (field) -> Modifier.isPrivate(field.getModifiers())); channelsField.setAccessible(true); return (List) channelsField.get(serverConnection); - } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException | - NoSuchFieldException e) { + } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { throw new RuntimeException(e); } }