diff --git a/ProtocolLib/.classpath b/ProtocolLib/.classpath index 408271fe..0bc481ca 100644 --- a/ProtocolLib/.classpath +++ b/ProtocolLib/.classpath @@ -10,6 +10,5 @@ - diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java b/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java index 3d4c4c0e..7a1c612d 100644 --- a/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java +++ b/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java @@ -441,17 +441,17 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok try { manager.registerEvents(new Listener() { - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPlayerJoin(PlayerJoinEvent event) { playerInjection.injectPlayer(event.getPlayer()); } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPlayerQuit(PlayerQuitEvent event) { playerInjection.uninjectPlayer(event.getPlayer()); } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPluginDisabled(PluginDisableEvent event) { // Clean up in case the plugin forgets if (event.getPlugin() != plugin) { @@ -487,7 +487,7 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok Class eventPriority = loader.loadClass("org.bukkit.event.Event$Priority"); // Get the priority - Object priorityNormal = Enum.valueOf(eventPriority, "Normal"); + Object priorityNormal = Enum.valueOf(eventPriority, "Highest"); // Get event types Object playerJoinType = Enum.valueOf(eventTypes, "PLAYER_JOIN"); diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/player/NetworkServerInjector.java b/ProtocolLib/src/com/comphenix/protocol/injector/player/NetworkServerInjector.java index 243c0fc7..55ebd698 100644 --- a/ProtocolLib/src/com/comphenix/protocol/injector/player/NetworkServerInjector.java +++ b/ProtocolLib/src/com/comphenix/protocol/injector/player/NetworkServerInjector.java @@ -136,8 +136,17 @@ public class NetworkServerInjector extends PlayerInjector { }); // Use the existing field values when we create our copy - DefaultInstances serverInstances = DefaultInstances.fromArray( + DefaultInstances serverInstances = null; + + if (hasProxyServerHandler()) { + Class> minecraftSuperClass = getFirstMinecraftSuperClass(serverHandler.getClass()); + serverInstances = DefaultInstances.fromArray( + ExistingGenerator.fromObjectFields(serverHandler, minecraftSuperClass)); + } else { + serverInstances = DefaultInstances.fromArray( ExistingGenerator.fromObjectFields(serverHandler)); + } + serverInstances.setNonNull(true); serverInstances.setMaximumRecursion(1); @@ -154,6 +163,15 @@ public class NetworkServerInjector extends PlayerInjector { "Cannot hook player: Unable to find a valid constructor for the NetServerHandler object."); } } + + private Class> getFirstMinecraftSuperClass(Class> clazz) { + if (clazz.getName().startsWith("net.minecraft")) + return clazz; + else if (clazz.equals(Object.class)) + return clazz; + else + return clazz.getSuperclass(); + } @Override public void cleanupAll() { diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/player/NetworkSpoutHook.java b/ProtocolLib/src/com/comphenix/protocol/injector/player/NetworkSpoutHook.java deleted file mode 100644 index e71bacef..00000000 --- a/ProtocolLib/src/com/comphenix/protocol/injector/player/NetworkSpoutHook.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.comphenix.protocol.injector.player; - -import java.lang.reflect.InvocationTargetException; -import java.util.logging.Logger; - -import net.minecraft.server.Packet; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; - -import com.comphenix.protocol.events.PacketListener; -import com.comphenix.protocol.injector.ListenerInvoker; - -public class NetworkSpoutHook extends PlayerInjector { - - public NetworkSpoutHook(Logger logger, Player player, ListenerInvoker invoker) throws IllegalAccessException { - super(logger, player, invoker); - } - - @Override - protected boolean hasListener(int packetID) { - return false; - } - - @Override - public boolean canInject() { - return getSpout() != null; - } - - private Plugin getSpout() { - // Spout must be loaded - try { - return Bukkit.getServer().getPluginManager().getPlugin("Spout"); - } catch (Throwable e) { - return null; - } - } - - @Override - public void injectManager() { - - } - - @Override - public void sendServerPacket(Packet packet, boolean filtered) throws InvocationTargetException { - - } - - @Override - public void cleanupAll() { - // TODO Auto-generated method stub - - } - - @Override - public void checkListener(PacketListener listener) { - // We support everything Spout does - } -} diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/player/PlayerInjectionHandler.java b/ProtocolLib/src/com/comphenix/protocol/injector/player/PlayerInjectionHandler.java index 1ceb0725..d10bfb64 100644 --- a/ProtocolLib/src/com/comphenix/protocol/injector/player/PlayerInjectionHandler.java +++ b/ProtocolLib/src/com/comphenix/protocol/injector/player/PlayerInjectionHandler.java @@ -23,6 +23,11 @@ import com.comphenix.protocol.injector.PlayerLoggedOutException; import com.comphenix.protocol.injector.PacketFilterManager.PlayerInjectHooks; import com.google.common.collect.ImmutableSet; +/** + * Responsible for injecting into a player's sendPacket method. + * + * @author Kristian + */ public class PlayerInjectionHandler { // Server connection injection diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/player/PlayerInjector.java b/ProtocolLib/src/com/comphenix/protocol/injector/player/PlayerInjector.java index 9a1779ec..f80b8e49 100644 --- a/ProtocolLib/src/com/comphenix/protocol/injector/player/PlayerInjector.java +++ b/ProtocolLib/src/com/comphenix/protocol/injector/player/PlayerInjector.java @@ -50,6 +50,9 @@ abstract class PlayerInjector { protected static Field inputField; protected static Field netHandlerField; + // Whether or not we're using a proxy type + private static boolean hasProxyType; + // To add our injected array lists protected static StructureModifier networkModifier; @@ -142,6 +145,14 @@ abstract class PlayerInjector { } } + /** + * Retrieve whether or not the server handler is a proxy object. + * @return TRUE if it is, FALSE otherwise. + */ + protected boolean hasProxyServerHandler() { + return hasProxyType; + } + private Field getProxyField(EntityPlayer notchEntity, Field serverField) { try { @@ -154,6 +165,8 @@ abstract class PlayerInjector { if (handler instanceof Factory) return null; + hasProxyType = true; + // No? Is it a Proxy type? try { FuzzyReflection reflection = FuzzyReflection.fromObject(handler, true); @@ -162,7 +175,7 @@ abstract class PlayerInjector { return reflection.getFieldByType(".*NetServerHandler"); } catch (RuntimeException e) { - logger.log(Level.WARNING, "Server handler is a proxy type.", e); + logger.log(Level.WARNING, "Detected server handler proxy type by another plugin. Conflict may occur!"); } } diff --git a/ProtocolLib/src/com/comphenix/protocol/reflect/ObjectCloner.java b/ProtocolLib/src/com/comphenix/protocol/reflect/ObjectCloner.java index 65902cbd..e64c32a8 100644 --- a/ProtocolLib/src/com/comphenix/protocol/reflect/ObjectCloner.java +++ b/ProtocolLib/src/com/comphenix/protocol/reflect/ObjectCloner.java @@ -55,6 +55,14 @@ public class ObjectCloner { // System.out.println(String.format("Writing value %s to %s", // value, modifier.getFields().get(i).getName())); } + + // Copy private fields underneath + Class> superclass = commonType.getSuperclass(); + + if (!superclass.equals(Object.class)) { + copyTo(source, destination, superclass); + } + } catch (FieldAccessException e) { throw new RuntimeException("Unable to copy fields from " + commonType.getName(), e); } diff --git a/ProtocolLib/src/com/comphenix/protocol/reflect/instances/DefaultInstances.java b/ProtocolLib/src/com/comphenix/protocol/reflect/instances/DefaultInstances.java index 8c3b8ebc..fad95379 100644 --- a/ProtocolLib/src/com/comphenix/protocol/reflect/instances/DefaultInstances.java +++ b/ProtocolLib/src/com/comphenix/protocol/reflect/instances/DefaultInstances.java @@ -235,8 +235,9 @@ public class DefaultInstances { params[i] = getDefaultInternal(types[i], providers, recursionLevel + 1); // Did we break the non-null contract? - if (params[i] == null && nonNull) + if (params[i] == null && nonNull) { return null; + } } return createInstance(type, minimum, types, params); @@ -244,7 +245,6 @@ public class DefaultInstances { } catch (Exception e) { // Nope, we couldn't create this type - e.printStackTrace(); } // No suitable default value could be found diff --git a/ProtocolLib/src/com/comphenix/protocol/reflect/instances/ExistingGenerator.java b/ProtocolLib/src/com/comphenix/protocol/reflect/instances/ExistingGenerator.java index 97bad0a6..25f78a03 100644 --- a/ProtocolLib/src/com/comphenix/protocol/reflect/instances/ExistingGenerator.java +++ b/ProtocolLib/src/com/comphenix/protocol/reflect/instances/ExistingGenerator.java @@ -33,13 +33,37 @@ public class ExistingGenerator implements InstanceProvider { * @return The instance generator. */ public static ExistingGenerator fromObjectFields(Object object) { + if (object == null) + throw new IllegalArgumentException("Object cannot be NULL."); + + return fromObjectFields(object, object.getClass()); + } + + /** + * Automatically create an instance provider from a objects public and private fields. + * + * If two or more fields share the same type, the last declared non-null field will take + * precedent. + * @param object - object to create an instance generator from. + * @param type - the type to cast the object. + * @return The instance generator. + */ + public static ExistingGenerator fromObjectFields(Object object, Class> type) { ExistingGenerator generator = new ExistingGenerator(); + // Possible errors + if (object == null) + throw new IllegalArgumentException("Object cannot be NULL."); + if (type == null) + throw new IllegalArgumentException("Type cannot be NULL."); + if (!type.isAssignableFrom(object.getClass())) + throw new IllegalArgumentException("Type must be a superclass or be the same type."); + // Read instances from every field. - for (Field field : FuzzyReflection.fromObject(object, true).getFields()) { + for (Field field : FuzzyReflection.fromClass(type, true).getFields()) { try { Object value = FieldUtils.readField(field, object, true); - + // Use the type of the field, not the object itself if (value != null) generator.addObject(field.getType(), value);
+ * If two or more fields share the same type, the last declared non-null field will take + * precedent. + * @param object - object to create an instance generator from. + * @param type - the type to cast the object. + * @return The instance generator. + */ + public static ExistingGenerator fromObjectFields(Object object, Class> type) { ExistingGenerator generator = new ExistingGenerator(); + // Possible errors + if (object == null) + throw new IllegalArgumentException("Object cannot be NULL."); + if (type == null) + throw new IllegalArgumentException("Type cannot be NULL."); + if (!type.isAssignableFrom(object.getClass())) + throw new IllegalArgumentException("Type must be a superclass or be the same type."); + // Read instances from every field. - for (Field field : FuzzyReflection.fromObject(object, true).getFields()) { + for (Field field : FuzzyReflection.fromClass(type, true).getFields()) { try { Object value = FieldUtils.readField(field, object, true); - + // Use the type of the field, not the object itself if (value != null) generator.addObject(field.getType(), value);