diff --git a/ProtocolLib/src/com/comphenix/protocol/ProtocolLibrary.java b/ProtocolLib/src/com/comphenix/protocol/ProtocolLibrary.java
index 3b2711c9..68060fbb 100644
--- a/ProtocolLib/src/com/comphenix/protocol/ProtocolLibrary.java
+++ b/ProtocolLib/src/com/comphenix/protocol/ProtocolLibrary.java
@@ -35,11 +35,12 @@ public class ProtocolLibrary extends JavaPlugin {
@Override
public void onDisable() {
protocolManager.close();
+ protocolManager = null;
}
/**
* Retrieves the packet protocol manager.
- * @return Packet protocol manager.
+ * @return Packet protocol manager, or NULL if it has been disabled.
*/
public static ProtocolManager getProtocolManager() {
return protocolManager;
diff --git a/ProtocolLib/src/com/comphenix/protocol/ProtocolManager.java b/ProtocolLib/src/com/comphenix/protocol/ProtocolManager.java
index 3e37fc2d..c109d32d 100644
--- a/ProtocolLib/src/com/comphenix/protocol/ProtocolManager.java
+++ b/ProtocolLib/src/com/comphenix/protocol/ProtocolManager.java
@@ -75,6 +75,20 @@ public interface ProtocolManager {
* @return New encapsulated Minecraft packet.
*/
public PacketContainer createPacket(int id);
+
+ /**
+ * Constructs a new encapsulated Minecraft packet with the given ID.
+ *
+ * If set to true, the skip default option will prevent the system from assigning
+ * non-primitive fields in the packet to a new default instance. For instance, certain
+ * packets - like Packet60Explosion - require a List or Set to be non-null. If the
+ * skipDefaults option is false, the List or Set will be automatically created.
+ *
+ * @param id - packet ID.
+ * @param skipDefaults - TRUE to skip setting default values, FALSE otherwise.
+ * @return New encapsulated Minecraft packet.
+ */
+ public PacketContainer createPacket(int id, boolean skipDefaults);
/**
* Retieves a set of every enabled packet.
diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java b/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java
index c96e5cea..804d0391 100644
--- a/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java
+++ b/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java
@@ -217,7 +217,23 @@ public final class PacketFilterManager implements ProtocolManager {
@Override
public PacketContainer createPacket(int id) {
- return new PacketContainer(id);
+ return createPacket(id, false);
+ }
+
+ @Override
+ public PacketContainer createPacket(int id, boolean skipDefaults) {
+ PacketContainer packet = new PacketContainer(id);
+
+ // Use any default values if possible
+ if (!skipDefaults) {
+ try {
+ packet.getModifier().writeDefaults();
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Security exception.", e);
+ }
+ }
+
+ return packet;
}
@Override
@@ -324,6 +340,8 @@ public final class PacketFilterManager implements ProtocolManager {
if (packetInjector != null)
packetInjector.cleanupAll();
+ // Remove listeners
+ packetListeners.clear();
playerInjection.clear();
connectionLookup.clear();
hasClosed = true;
diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java b/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java
index dcbefb72..49def95c 100644
--- a/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java
+++ b/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java
@@ -2,14 +2,19 @@ package com.comphenix.protocol.injector;
import java.io.DataInputStream;
import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
+import java.util.Collections;
+import java.util.List;
+import java.util.ArrayList;
import java.util.Set;
+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;
@@ -18,9 +23,19 @@ import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.FieldUtils;
import com.comphenix.protocol.reflect.FuzzyReflection;
+import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.reflect.VolatileField;
+import com.google.common.collect.Sets;
class PlayerInjector {
+
+ /**
+ * Marker interface that indicates a packet is fake and should not be processed.
+ * @author Kristian
+ */
+ public interface FakePacket {
+ // Nothing
+ }
// Cache previously retrieved fields
private static Field serverHandlerField;
@@ -28,15 +43,27 @@ class PlayerInjector {
private static Field inputField;
private static Field netHandlerField;
+ // To add our injected array lists
+ private static StructureModifier