diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/InjectedArrayList.java b/ProtocolLib/src/com/comphenix/protocol/injector/InjectedArrayList.java new file mode 100644 index 00000000..14b8e025 --- /dev/null +++ b/ProtocolLib/src/com/comphenix/protocol/injector/InjectedArrayList.java @@ -0,0 +1,115 @@ +package com.comphenix.protocol.injector; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Set; + +import net.minecraft.server.Packet; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import com.comphenix.protocol.injector.PlayerInjector.FakePacket; + +/** + * The array list that notifies when packets are sent by the server. + * + * @author Kristian + */ +class InjectedArrayList extends ArrayList { + + /** + * Silly Eclipse. + */ + private static final long serialVersionUID = -1173865905404280990L; + + private PlayerInjector injector; + private Set ignoredPackets; + private ClassLoader classLoader; + + public InjectedArrayList(ClassLoader classLoader, PlayerInjector injector, Set ignoredPackets) { + this.classLoader = classLoader; + this.injector = injector; + this.ignoredPackets = ignoredPackets; + } + + @Override + public boolean add(Packet packet) { + + Packet result = null; + + // Check for fake packets and ignored packets + if (packet instanceof FakePacket) { + return true; + } else if (ignoredPackets.contains(packet)) { + ignoredPackets.remove(packet); + } else { + result = injector.handlePacketRecieved(packet); + } + + // A NULL packet indicate cancelling + try { + if (result != null) { + super.add(result); + } else { + // We'll use the FakePacket marker instead of preventing the filters + injector.sendServerPacket(createNegativePacket(packet), true); + } + + // Collection.add contract + return true; + + } catch (InvocationTargetException e) { + throw new RuntimeException("Reverting cancelled packet failed.", e.getTargetException()); + } + } + + /** + * Used by a hack that reverses the effect of a cancelled packet. Returns a packet + * whereby every int method's return value is inverted (a => -a). + * + * @param source - packet to invert. + * @return The inverted packet. + */ + Packet createNegativePacket(Packet source) { + Enhancer ex = new Enhancer(); + Class type = source.getClass(); + + // 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. + // + // We do that by constructing a special packet of the same type that returns + // a negative integer for all zero-parameter integer methods. This includes the + // size() method, which is used by the queue method to count the number of + // bytes to add. + // + // Essentially, we have: + // + // public class NegativePacket extends [a packet] { + // @Override + // public int size() { + // return -super.size(); + // } + // ect. + // } + ex.setInterfaces(new Class[] { FakePacket.class } ); + ex.setUseCache(true); + ex.setClassLoader(classLoader); + ex.setSuperclass(type); + ex.setCallback(new MethodInterceptor() { + @Override + public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { + if (method.getReturnType().equals(int.class) && args.length == 0) { + Integer result = (Integer) proxy.invokeSuper(obj, args); + return -result; + } else { + return proxy.invokeSuper(obj, args); + } + } + }); + + return (Packet) ex.create(); + } +} diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java b/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java index 6cd5244a..3d5e362c 100644 --- a/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java +++ b/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java @@ -29,9 +29,6 @@ import java.util.concurrent.ConcurrentHashMap; import net.minecraft.server.EntityPlayer; import net.minecraft.server.Packet; -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.Player; @@ -219,7 +216,6 @@ class PlayerInjector { } } - @SuppressWarnings("serial") public void injectManager() { if (networkManager != null) { @@ -236,38 +232,7 @@ class PlayerInjector { synchronized(minecraftList) { // The list we'll be inserting - List hackedList = new ArrayList() { - @Override - public boolean add(Packet packet) { - - Packet result = null; - - // Check for fake packets and ignored packets - if (packet instanceof FakePacket) { - return true; - } else if (ignoredPackets.contains(packet)) { - ignoredPackets.remove(packet); - } else { - result = handlePacketRecieved(packet); - } - - // A NULL packet indicate cancelling - try { - if (result != null) { - super.add(result); - } else { - // We'll use the FakePacket marker instead of preventing the filters - sendServerPacket(createNegativePacket(packet), true); - } - - // Collection.add contract - return true; - - } catch (InvocationTargetException e) { - throw new RuntimeException("Reverting cancelled packet failed.", e.getTargetException()); - } - } - }; + List hackedList = new InjectedArrayList(manager.getClassLoader(), this, ignoredPackets); // Add every previously stored packet for (Packet packet : minecraftList) { @@ -284,54 +249,6 @@ class PlayerInjector { } } - /** - * Used by a hack that reverses the effect of a cancelled packet. Returns a packet - * whereby every int method's return value is inverted (a => -a). - * - * @param source - packet to invert. - * @return The inverted packet. - */ - private Packet createNegativePacket(Packet source) { - Enhancer ex = new Enhancer(); - Class type = source.getClass(); - - // 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. - // - // We do that by constructing a special packet of the same type that returns - // a negative integer for all zero-parameter integer methods. This includes the - // size() method, which is used by the queue method to count the number of - // bytes to add. - // - // Essentially, we have: - // - // public class NegativePacket extends [a packet] { - // @Override - // public int size() { - // return -super.size(); - // } - // ect. - // } - ex.setInterfaces(new Class[] { FakePacket.class } ); - ex.setUseCache(true); - ex.setClassLoader(manager.getClassLoader()); - ex.setSuperclass(type); - ex.setCallback(new MethodInterceptor() { - @Override - public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { - if (method.getReturnType().equals(int.class) && args.length == 0) { - Integer result = (Integer) proxy.invokeSuper(obj, args); - return -result; - } else { - return proxy.invokeSuper(obj, args); - } - } - }); - - return (Packet) ex.create(); - } - /** * Allows a packet to be recieved by the listeners. * @param packet - packet to recieve.