From 5a96a63ff85aaba91c061285e801041e9dcaa5ec Mon Sep 17 00:00:00 2001 From: "Kristian S. Stangeland" Date: Fri, 21 Dec 2012 00:27:13 +0100 Subject: [PATCH] Added support for 1.4.6. Yes, it's essentially a hack, but I don't have enough time today to find a better way. It will have to do until 1.5.0 is out. --- .../player/InjectedServerConnection.java | 3 +- .../injector/player/NetLoginInjector.java | 8 +- .../player/NetworkServerInjector.java | 3 +- .../injector/player/PlayerInjector.java | 16 ++-- .../protocol/utility/CachedPackage.java | 10 +++ .../protocol/utility/MinecraftReflection.java | 90 ++++++++++++++++++- 6 files changed, 118 insertions(+), 12 deletions(-) diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedServerConnection.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedServerConnection.java index 1d94a9c9..1886cac9 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedServerConnection.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedServerConnection.java @@ -77,7 +77,8 @@ class InjectedServerConnection { return; if (minecraftServerField == null) - minecraftServerField = FuzzyReflection.fromObject(server, true).getFieldByType(".*MinecraftServer"); + minecraftServerField = FuzzyReflection.fromObject(server, true). + getFieldByType("MinecraftServer", MinecraftReflection.getMinecraftServerClass()); try { minecraftServer = FieldUtils.readField(minecraftServerField, server, true); diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetLoginInjector.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetLoginInjector.java index 64e2f005..9ac2f5f8 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetLoginInjector.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetLoginInjector.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import com.comphenix.protocol.error.ErrorReporter; import com.comphenix.protocol.injector.GamePhase; import com.comphenix.protocol.injector.player.TemporaryPlayerFactory.InjectContainer; +import com.comphenix.protocol.utility.MinecraftReflection; import com.google.common.collect.Maps; /** @@ -62,9 +63,9 @@ class NetLoginInjector { } catch (Throwable e) { // Minecraft can't handle this, so we'll deal with it here - reporter.reportDetailed(this, "Unable to hook NetLoginHandler.", e, inserting); + reporter.reportDetailed(this, "Unable to hook " + + MinecraftReflection.getNetLoginHandlerName() + ".", e, inserting); return inserting; - } } @@ -103,7 +104,8 @@ class NetLoginInjector { } catch (Throwable e) { // Don't leak this to Minecraft - reporter.reportDetailed(this, "Cannot cleanup NetLoginHandler.", e, removing); + reporter.reportDetailed(this, "Cannot cleanup " + + MinecraftReflection.getNetLoginHandlerName() + ".", e, removing); } } } diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkServerInjector.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkServerInjector.java index a7b42de2..eacc83de 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkServerInjector.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkServerInjector.java @@ -141,7 +141,8 @@ public class NetworkServerInjector extends PlayerInjector { } throw new RuntimeException( - "Cannot hook player: Unable to find a valid constructor for the NetServerHandler object."); + "Cannot hook player: Unable to find a valid constructor for the " + + MinecraftReflection.getNetServerHandlerClass().getName() + " object."); } } diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/PlayerInjector.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/PlayerInjector.java index 239f6b7a..25d683c6 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/PlayerInjector.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/PlayerInjector.java @@ -156,7 +156,8 @@ abstract class PlayerInjector { // Retrieve the server handler if (serverHandlerField == null) { - serverHandlerField = FuzzyReflection.fromObject(notchEntity).getFieldByType(".*NetServerHandler"); + serverHandlerField = FuzzyReflection.fromObject(notchEntity).getFieldByType( + "NetServerHandler", MinecraftReflection.getNetServerHandlerClass()); proxyServerField = getProxyField(notchEntity, serverHandlerField); } @@ -166,7 +167,8 @@ abstract class PlayerInjector { // Next, get the network manager if (networkManagerField == null) - networkManagerField = FuzzyReflection.fromObject(serverHandler).getFieldByType(".*NetworkManager"); + networkManagerField = FuzzyReflection.fromObject(serverHandler). + getFieldByType(".*" + MinecraftReflection.getNetworkManagerName()); initializeNetworkManager(networkManagerField, serverHandler); } } @@ -181,7 +183,8 @@ abstract class PlayerInjector { loginHandler = netLoginHandler; if (netLoginNetworkField == null) - netLoginNetworkField = FuzzyReflection.fromObject(netLoginHandler).getFieldByType(".*NetworkManager"); + netLoginNetworkField = FuzzyReflection.fromObject(netLoginHandler). + getFieldByType(".*" + MinecraftReflection.getNetworkManagerName()); initializeNetworkManager(netLoginNetworkField, netLoginHandler); } } @@ -341,7 +344,7 @@ abstract class PlayerInjector { FuzzyReflection reflection = FuzzyReflection.fromObject(handler, true); // It might be - return reflection.getFieldByType(".*NetServerHandler"); + return reflection.getFieldByType("NetServerHandler", MinecraftReflection.getNetServerHandlerClass()); } catch (RuntimeException e) { // Damn @@ -367,7 +370,7 @@ abstract class PlayerInjector { try { if (netHandlerField == null) netHandlerField = FuzzyReflection.fromClass(networkManager.getClass(), true). - getFieldByType("net\\.minecraft\\.NetHandler"); + getFieldByType("NetHandler", MinecraftReflection.getNetHandlerClass()); } catch (RuntimeException e1) { // Swallow it } @@ -398,7 +401,8 @@ abstract class PlayerInjector { */ private Object getEntityPlayer(Object netHandler) throws IllegalAccessException { if (entityPlayerField == null) - entityPlayerField = FuzzyReflection.fromObject(netHandler).getFieldByType(".*EntityPlayer"); + entityPlayerField = FuzzyReflection.fromObject(netHandler).getFieldByType( + "EntityPlayer", MinecraftReflection.getEntityPlayerClass()); return FieldUtils.readField(entityPlayerField, netHandler); } diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/utility/CachedPackage.java b/ProtocolLib/src/main/java/com/comphenix/protocol/utility/CachedPackage.java index e69f956c..7d552fb7 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/utility/CachedPackage.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/utility/CachedPackage.java @@ -18,6 +18,16 @@ class CachedPackage { this.cache = Maps.newConcurrentMap(); } + /** + * Associate a given class with a class name. + * @param className - class name. + * @param clazz - type of class. + */ + @SuppressWarnings("rawtypes") + public void setPackageClass(String className, Class clazz) { + cache.put(className, clazz); + } + /** * Retrieve the class object of a specific class in the current package. * @param className - the specific class. diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java b/ProtocolLib/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java index e21be948..15ba850f 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java @@ -11,6 +11,7 @@ import org.bukkit.Server; import org.bukkit.inventory.ItemStack; import com.comphenix.protocol.injector.BukkitUnwrapper; +import com.google.common.base.Joiner; /** * Methods and constants specifically used in conjuction with reflecting Minecraft object. @@ -289,7 +290,31 @@ public class MinecraftReflection { */ @SuppressWarnings("rawtypes") public static Class getNetLoginHandlerClass() { - return getMinecraftClass("NetLoginHandler"); + return getMinecraftClass("NetLoginHandler", "PendingConnection"); + } + + /** + * Retrieve the NetServerHandler class. + * @return The NetServerHandler class. + */ + public static Class getNetServerHandlerClass() { + return getMinecraftClass("NetServerHandler", "PlayerConnection"); + } + + /** + * Retrieve the NetworkManager class. + * @return The NetworkManager class. + */ + public static Class getNetworkManagerClass() { + return getMinecraftClass("NetworkManager"); + } + + /** + * Retrieve the NetHandler class. + * @return The NetHandler class. + */ + public static Class getNetHandlerClass() { + return getMinecraftClass("NetHandler"); } /** @@ -310,6 +335,14 @@ public class MinecraftReflection { return getMinecraftClass("WorldType"); } + /** + * Retrieve the MinecraftServer class. + * @return MinecraftServer class. + */ + public static Class getMinecraftServerClass() { + return getMinecraftClass("MinecraftServer"); + } + /** * Retrieve the DataWatcher class. * @return The DataWatcher class. @@ -516,4 +549,59 @@ public class MinecraftReflection { minecraftPackage = new CachedPackage(getMinecraftPackage()); return minecraftPackage.getPackageClass(className); } + + /** + * Retrieve the first class that matches a specified Minecraft name. + * @param classes - the specific Minecraft class. + * @return Class object. + * @throws RuntimeException If we are unable to find any of the given classes. + */ + @SuppressWarnings("rawtypes") + public static Class getMinecraftClass(String className, String... aliases) { + try { + // Try the main class first + return getMinecraftClass(className); + } catch (RuntimeException e1) { + Class success = null; + + // Try every alias too + for (String alias : aliases) { + try { + success = getMinecraftClass(alias); + break; + } catch (RuntimeException e2) { + // Swallov + } + } + + if (success != null) { + // Save it for later + minecraftPackage.setPackageClass(className, success); + return success; + } else { + // Hack failed + throw new RuntimeException( + String.format("Unable to find %s (%s)", + className, + Joiner.on(", ").join(aliases)) + ); + } + } + } + + /** + * Dynamically retrieve the NetworkManager name. + * @return Name of the NetworkManager class. + */ + public static String getNetworkManagerName() { + return getNetworkManagerClass().getSimpleName(); + } + + /** + * Dynamically retrieve the name of the current NetLoginHandler. + * @return Name of the NetLoginHandler class. + */ + public static String getNetLoginHandlerName() { + return getNetLoginHandlerClass().getSimpleName(); + } }