diff --git a/ProtocolLib/src/com/comphenix/protocol/events/PacketEvent.java b/ProtocolLib/src/com/comphenix/protocol/events/PacketEvent.java
index 799154f3..92b039fa 100644
--- a/ProtocolLib/src/com/comphenix/protocol/events/PacketEvent.java
+++ b/ProtocolLib/src/com/comphenix/protocol/events/PacketEvent.java
@@ -148,6 +148,8 @@ public class PacketEvent extends EventObject implements Cancellable {
/**
* Whether or not this packet was created by the server.
+ *
+ * Most listeners can deduce this by noting which listener method was invoked.
* @return TRUE if the packet was created by the server, FALSE if it was created by a client.
*/
public boolean isServerPacket() {
diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java b/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java
index 6d854ccb..e9009586 100644
--- a/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java
+++ b/ProtocolLib/src/com/comphenix/protocol/injector/PacketFilterManager.java
@@ -293,7 +293,7 @@ public final class PacketFilterManager implements ProtocolManager {
* @param event - the packet event to invoke.
*/
public void invokePacketRecieving(PacketEvent event) {
- handlePacket(recievedListeners, event);
+ handlePacket(recievedListeners, event, false);
}
/**
@@ -301,7 +301,7 @@ public final class PacketFilterManager implements ProtocolManager {
* @param event - the packet event to invoke.
*/
public void invokePacketSending(PacketEvent event) {
- handlePacket(sendingListeners, event);
+ handlePacket(sendingListeners, event, true);
}
/**
@@ -311,7 +311,7 @@ public final class PacketFilterManager implements ProtocolManager {
* @param packetListeners - packet listeners that will receive this event.
* @param event - the evnet to broadcast.
*/
- private void handlePacket(SortedPacketListenerList packetListeners, PacketEvent event) {
+ private void handlePacket(SortedPacketListenerList packetListeners, PacketEvent event, boolean sending) {
// By default, asynchronous packets are queued for processing
if (asyncFilterManager.hasAsynchronousListeners(event)) {
@@ -319,7 +319,10 @@ public final class PacketFilterManager implements ProtocolManager {
}
// Process synchronous events
- packetListeners.invokePacketRecieving(logger, event);
+ if (sending)
+ packetListeners.invokePacketSending(logger, event);
+ else
+ packetListeners.invokePacketRecieving(logger, event);
// To cancel asynchronous processing, use the async marker
if (!event.isCancelled() && !hasAsyncCancelled(event.getAsyncMarker())) {
diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java b/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java
index b92fd3c0..2ae2976d 100644
--- a/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java
+++ b/ProtocolLib/src/com/comphenix/protocol/injector/PlayerInjector.java
@@ -223,7 +223,7 @@ abstract class PlayerInjector {
Integer id = MinecraftRegistry.getPacketToID().get(packet.getClass());
// Make sure we're listening
- if (id != null && sendingFilters.contains(id)) {
+ if (id != null && sendingFilters.contains(id)) {
// A packet has been sent guys!
PacketContainer container = new PacketContainer(id, packet);
PacketEvent event = PacketEvent.fromServer(manager, container, player);
diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/ReadPacketModifier.java b/ProtocolLib/src/com/comphenix/protocol/injector/ReadPacketModifier.java
index d2e71c60..d5b84bbe 100644
--- a/ProtocolLib/src/com/comphenix/protocol/injector/ReadPacketModifier.java
+++ b/ProtocolLib/src/com/comphenix/protocol/injector/ReadPacketModifier.java
@@ -97,7 +97,7 @@ class ReadPacketModifier implements MethodInterceptor {
// We need this in order to get the correct player
DataInputStream input = (DataInputStream) args[0];
-
+
// Let the people know
PacketContainer container = new PacketContainer(packetID, (Packet) thisObj);
PacketEvent event = packetInjector.packetRecieved(container, input);
diff --git a/ProtocolLib/src/com/comphenix/protocol/injector/SortedPacketListenerList.java b/ProtocolLib/src/com/comphenix/protocol/injector/SortedPacketListenerList.java
index 27df4585..7ff8cddd 100644
--- a/ProtocolLib/src/com/comphenix/protocol/injector/SortedPacketListenerList.java
+++ b/ProtocolLib/src/com/comphenix/protocol/injector/SortedPacketListenerList.java
@@ -57,7 +57,7 @@ class SortedPacketListenerList extends AbstractConcurrentListenerMultimap {
// Cache of previous types
protected Map subtypeCache;
+ // Whether or subclasses should handle conversion
+ protected boolean customConvertHandling;
+
/**
* Creates a structure modifier.
* @param targetType - the structure to modify.
@@ -125,7 +128,7 @@ public class StructureModifier {
Object result = FieldUtils.readField(data.get(fieldIndex), target, true);
// Use the converter, if we have it
- if (converter != null)
+ if (needConversion())
return converter.getSpecific(result);
else
return (TField) result;
@@ -164,7 +167,7 @@ public class StructureModifier {
throw new IllegalStateException("Cannot write to a NULL target.");
// Use the converter, if it exists
- Object obj = converter != null ? converter.getGeneric(value) : value;
+ Object obj = needConversion() ? converter.getGeneric(value) : value;
try {
FieldUtils.writeField(data.get(fieldIndex), target, obj, true);
@@ -176,6 +179,14 @@ public class StructureModifier {
return this;
}
+ /**
+ * Whether or not we should use the converter instance.
+ * @return TRUE if we should, FALSE otherwise.
+ */
+ private final boolean needConversion() {
+ return converter != null && !customConvertHandling;
+ }
+
/**
* Writes the value of a given field IF and ONLY if it exists.
* @param fieldIndex - index of the potential field.
@@ -362,7 +373,7 @@ public class StructureModifier {
/**
* Retrieves a structure modifier with the same type and target, but using a new object converter.
- * @param converter- the object converter to use.
+ * @param converter - the object converter to use.
* @return Structure modifier with the new converter.
*/
@SuppressWarnings("unchecked")
diff --git a/ProtocolLib/src/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java b/ProtocolLib/src/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java
index 5ddb19f8..d96236f7 100644
--- a/ProtocolLib/src/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java
+++ b/ProtocolLib/src/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java
@@ -13,10 +13,15 @@ import com.comphenix.protocol.reflect.instances.DefaultInstances;
* @author Kristian
* @param Field type.
*/
-public class CompiledStructureModifier extends StructureModifier {
+public abstract class CompiledStructureModifier extends StructureModifier {
// Used to compile instances of structure modifiers
protected StructureCompiler compiler;
+ public CompiledStructureModifier() {
+ super();
+ customConvertHandling = true;
+ }
+
// Speed up the default writer
@SuppressWarnings("unchecked")
@Override
@@ -35,6 +40,29 @@ public class CompiledStructureModifier extends StructureModifier
return this;
}
+ @SuppressWarnings("unchecked")
+ @Override
+ public final TField read(int fieldIndex) throws FieldAccessException {
+ Object result = readGenerated(fieldIndex);
+
+ if (converter != null)
+ return converter.getSpecific(result);
+ else
+ return (TField) result;
+ }
+
+ protected abstract Object readGenerated(int fieldIndex) throws FieldAccessException;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public StructureModifier write(int index, Object value) throws FieldAccessException {
+ if (converter != null)
+ value = converter.getGeneric((TField) value);
+ return writeGenerated(index, value);
+ }
+
+ protected abstract StructureModifier writeGenerated(int index, Object value) throws FieldAccessException;
+
@Override
public StructureModifier withTarget(Object target) {
if (compiler != null)
diff --git a/ProtocolLib/src/com/comphenix/protocol/reflect/compiler/StructureCompiler.java b/ProtocolLib/src/com/comphenix/protocol/reflect/compiler/StructureCompiler.java
index 837aa778..24477dff 100644
--- a/ProtocolLib/src/com/comphenix/protocol/reflect/compiler/StructureCompiler.java
+++ b/ProtocolLib/src/com/comphenix/protocol/reflect/compiler/StructureCompiler.java
@@ -14,40 +14,39 @@ import com.google.common.base.Objects;
import net.sf.cglib.asm.*;
-// This class will automatically generate the following type of structure modifier:
-//
-// public class CompiledStructure$Packet20NamedEntitySpawnObject extends CompiledStructureModifier {
+// public class CompiledStructureModifierPacket20 extends CompiledStructureModifier {
//
// private Packet20NamedEntitySpawn typedTarget;
-//
-// public CompiledStructure$Packet20NamedEntitySpawnObject(StructureModifier other, StructureCompiler compiler) {
+//
+// public CompiledStructureModifierPacket20(StructureModifier other, StructureCompiler compiler) {
+// super();
// initialize(other);
-// this.typedTarget = (Packet20NamedEntitySpawn) other.getTarget();
+// this.target = other.getTarget();
+// this.typedTarget = (Packet20NamedEntitySpawn) target;
// this.compiler = compiler;
// }
//
-// @SuppressWarnings("unchecked")
// @Override
-// public TField read(int fieldIndex) throws FieldAccessException {
+// protected Object readGenerated(int fieldIndex) throws FieldAccessException {
//
// Packet20NamedEntitySpawn target = typedTarget;
//
// switch (fieldIndex) {
-// case 0: return (TField) (Object) target.a;
-// case 1: return (TField) (Object) target.b;
-// case 2: return (TField) (Object) target.c;
-// case 3: return (TField) (Object) target.d;
-// case 4: return (TField) (Object) target.e;
-// case 5: return (TField) (Object) target.f;
-// case 6: return (TField) (Object) target.g;
-// case 7: return (TField) (Object) target.h;
+// case 0: return (Object) target.a;
+// case 1: return (Object) target.b;
+// case 2: return (Object) target.c;
+// case 3: return super.read(fieldIndex);
+// case 4: return super.read(fieldIndex);
+// case 5: return (Object) target.f;
+// case 6: return (Object) target.g;
+// case 7: return (Object) target.h;
// default:
// throw new FieldAccessException("Invalid index " + fieldIndex);
// }
// }
//
// @Override
-// public StructureModifier write(int index, Object value) {
+// protected StructureModifier writeGenerated(int index, Object value) throws FieldAccessException {
//
// Packet20NamedEntitySpawn target = typedTarget;
//
@@ -56,8 +55,8 @@ import net.sf.cglib.asm.*;
// case 1: target.b = (String) value; break;
// case 2: target.c = (Integer) value; break;
// case 3: target.d = (Integer) value; break;
-// case 4: target.e = (Integer) value; break;
-// case 5: target.f = (Byte) value; break;
+// case 4: super.write(index, value); break;
+// case 5: super.write(index, value); break;
// case 6: target.g = (Byte) value; break;
// case 7: target.h = (Integer) value; break;
// default:
@@ -265,7 +264,7 @@ public final class StructureCompiler {
String methodDescriptor = "(ILjava/lang/Object;)L" + SUPER_CLASS + ";";
String methodSignature = "(ITTField;)L" + SUPER_CLASS + ";";
- MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, "write", methodDescriptor, methodSignature,
+ MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PROTECTED, "writeGenerated", methodDescriptor, methodSignature,
new String[] { FIELD_EXCEPTION_CLASS });
BoxingHelper boxingHelper = new BoxingHelper(mv);
@@ -349,7 +348,7 @@ public final class StructureCompiler {
}
private void createReadMethod(ClassWriter cw, String className, List fields, String targetSignature, String targetName) {
- MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, "read", "(I)Ljava/lang/Object;", "(I)TTField;",
+ MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PROTECTED, "readGenerated", "(I)Ljava/lang/Object;", null,
new String[] { "com/comphenix/protocol/reflect/FieldAccessException" });
BoxingHelper boxingHelper = new BoxingHelper(mv);