diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/ListenerInvoker.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/ListenerInvoker.java index f27b64e5..52b702fc 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/ListenerInvoker.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/ListenerInvoker.java @@ -1,67 +1,68 @@ -/* - * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol. - * Copyright (C) 2012 Kristian S. Stangeland - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 USA - */ - -package com.comphenix.protocol.injector; - -import com.comphenix.protocol.events.PacketEvent; - -/** - * Represents an object that initiate the packet listeners. - * - * @author Kristian - */ -public interface ListenerInvoker { - - /** - * Invokes the given packet event for every registered listener. - * @param event - the packet event to invoke. - */ - public abstract void invokePacketRecieving(PacketEvent event); - - /** - * Invokes the given packet event for every registered listener. - * @param event - the packet event to invoke. - */ - public abstract void invokePacketSending(PacketEvent event); - - /** - * Retrieve the associated ID of a packet. - * @param packet - the packet. - * @return The packet ID. - */ - public abstract int getPacketID(Object packet); - - /** - * Associate a given class with the given packet ID. Internal method. - * @param clazz - class to associate. - */ - public abstract void unregisterPacketClass(Class clazz); - - /** - * Remove a given class from the packet registry. Internal method. - * @param clazz - class to remove. - */ - public abstract void registerPacketClass(Class clazz, int packetID); - - /** - * Retrieves the correct packet class from a given packet ID. - * @param packetID - the packet ID. - * @param forceVanilla - whether or not to look for vanilla classes, not injected classes. - * @return The associated class. - */ - public abstract Class getPacketClassFromID(int packetID, boolean forceVanilla); +/* + * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol. + * Copyright (C) 2012 Kristian S. Stangeland + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ + +package com.comphenix.protocol.injector; + +import com.comphenix.protocol.events.PacketEvent; + +/** + * Represents an object that initiate the packet listeners. + * + * @author Kristian + */ +public interface ListenerInvoker { + + /** + * Invokes the given packet event for every registered listener. + * @param event - the packet event to invoke. + */ + public abstract void invokePacketRecieving(PacketEvent event); + + /** + * Invokes the given packet event for every registered listener. + * @param event - the packet event to invoke. + */ + public abstract void invokePacketSending(PacketEvent event); + + /** + * Retrieve the associated ID of a packet. + * @param packet - the packet. + * @return The packet ID. + */ + public abstract int getPacketID(Object packet); + + /** + * Associate a given class with the given packet ID. Internal method. + * @param clazz - class to associate. + */ + public abstract void unregisterPacketClass(Class clazz); + + /** + * Register a given class in the packet registry. Internal method. + * @param clazz - class to register. + * @param packetID - the the new associated packet ID. + */ + public abstract void registerPacketClass(Class clazz, int packetID); + + /** + * Retrieves the correct packet class from a given packet ID. + * @param packetID - the packet ID. + * @param forceVanilla - whether or not to look for vanilla classes, not injected classes. + * @return The associated class. + */ + public abstract Class getPacketClassFromID(int packetID, boolean forceVanilla); } \ No newline at end of file diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedArrayList.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedArrayList.java index 33e45f63..bc4cf76f 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedArrayList.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedArrayList.java @@ -21,12 +21,16 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Set; +import java.util.concurrent.ConcurrentMap; +import com.comphenix.protocol.Packets; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.error.Report; import com.comphenix.protocol.error.ReportType; import com.comphenix.protocol.injector.ListenerInvoker; import com.comphenix.protocol.injector.player.NetworkFieldInjector.FakePacket; +import com.comphenix.protocol.utility.MinecraftReflection; +import com.google.common.collect.MapMaker; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Enhancer; @@ -46,6 +50,9 @@ class InjectedArrayList extends ArrayList { */ private static final long serialVersionUID = -1173865905404280990L; + // Fake inverted proxy objects + private static ConcurrentMap delegateLookup = new MapMaker().weakKeys().makeMap(); + private transient PlayerInjector injector; private transient Set ignoredPackets; private transient ClassLoader classLoader; @@ -108,10 +115,7 @@ class InjectedArrayList extends ArrayList { ListenerInvoker invoker = injector.getInvoker(); int packetID = invoker.getPacketID(source); - Class type = invoker.getPacketClassFromID(packetID, true); - System.out.println(type.getName()); - // We want to subtract the byte amount that were added to the running // total of outstanding packets. Otherwise, cancelling too many packets // might cause a "disconnect.overflow" error. @@ -131,7 +135,7 @@ class InjectedArrayList extends ArrayList { // ect. // } Enhancer ex = new Enhancer(); - ex.setSuperclass(type); + ex.setSuperclass(MinecraftReflection.getPacketClass()); ex.setInterfaces(new Class[] { FakePacket.class } ); ex.setUseCache(true); ex.setClassLoader(classLoader); @@ -143,7 +147,10 @@ class InjectedArrayList extends ArrayList { try { // Temporarily associate the fake packet class invoker.registerPacketClass(proxyClass, packetID); - return proxyClass.newInstance(); + Object proxy = proxyClass.newInstance(); + + InjectedArrayList.registerDelegate(proxy, source); + return proxy; } catch (Exception e) { // Don't pollute the throws tree @@ -154,18 +161,33 @@ class InjectedArrayList extends ArrayList { } } + /** + * Ensure that the inverted integer proxy uses the given object as source. + * @param proxy - inverted integer proxy. + * @param source - source object. + */ + private static void registerDelegate(Object proxy, Object source) { + delegateLookup.put(proxy, source); + } + /** * Inverts the integer result of every integer method. * @author Kristian */ - private class InvertedIntegerCallback implements MethodInterceptor { + private class InvertedIntegerCallback implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { + final Object delegate = delegateLookup.get(obj); + + if (delegate == null) { + throw new IllegalStateException("Unable to find delegate source for " + obj); + } + if (method.getReturnType().equals(int.class) && args.length == 0) { - Integer result = (Integer) proxy.invokeSuper(obj, args); + Integer result = (Integer) proxy.invoke(delegate, args); return -result; } else { - return proxy.invokeSuper(obj, args); + return proxy.invoke(delegate, args); } } }