Ensure that the compiled structures respect the converter field.

In addition, fixed a bug that prevented client listeners from
receiving any packets.
This commit is contained in:
Kristian S. Stangeland 2012-10-01 02:17:13 +02:00
parent 46d9a6e975
commit c2b4b5fce3
8 changed files with 75 additions and 32 deletions

View File

@ -148,6 +148,8 @@ public class PacketEvent extends EventObject implements Cancellable {
/**
* Whether or not this packet was created by the server.
* <p>
* 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() {

View File

@ -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())) {

View File

@ -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);

View File

@ -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);

View File

@ -57,7 +57,7 @@ class SortedPacketListenerList extends AbstractConcurrentListenerMultimap<Packet
} catch (Throwable e) {
// Minecraft doesn't want your Exception.
logger.log(Level.SEVERE,
"Exception occured in onPacketReceiving() for " +
"Exception occured in onPacketSending() for " +
PacketAdapter.getPluginName(element.getListener()), e);
}
}

View File

@ -58,6 +58,9 @@ public class StructureModifier<TField> {
// Cache of previous types
protected Map<Class, StructureModifier> 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<TField> {
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<TField> {
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<TField> {
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<TField> {
/**
* 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")

View File

@ -13,10 +13,15 @@ import com.comphenix.protocol.reflect.instances.DefaultInstances;
* @author Kristian
* @param <TField> Field type.
*/
public class CompiledStructureModifier<TField> extends StructureModifier<TField> {
public abstract class CompiledStructureModifier<TField> extends StructureModifier<TField> {
// 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<TField> extends StructureModifier<TField>
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<TField> write(int index, Object value) throws FieldAccessException {
if (converter != null)
value = converter.getGeneric((TField) value);
return writeGenerated(index, value);
}
protected abstract StructureModifier<TField> writeGenerated(int index, Object value) throws FieldAccessException;
@Override
public StructureModifier<TField> withTarget(Object target) {
if (compiler != null)

View File

@ -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<TField> extends CompiledStructureModifier<TField> {
// public class CompiledStructureModifierPacket20<TField> extends CompiledStructureModifier<TField> {
//
// private Packet20NamedEntitySpawn typedTarget;
//
// public CompiledStructure$Packet20NamedEntitySpawnObject(StructureModifier<TField> other, StructureCompiler compiler) {
//
// public CompiledStructureModifierPacket20(StructureModifier<TField> 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<TField> write(int index, Object value) {
// protected StructureModifier<TField> 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 + "<TTField;>;";
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<Field> 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);