Archiviert
13
0

Refactor the wrapper classes so they inherit from a common class.

Dieser Commit ist enthalten in:
Kristian S. Stangeland 2013-12-09 13:46:41 +01:00
Ursprung 143ed2ff02
Commit e8759d0b72
12 geänderte Dateien mit 303 neuen und 256 gelöschten Zeilen

Datei anzeigen

@ -43,6 +43,10 @@ public class PacketType implements Serializable {
public static class Handshake { public static class Handshake {
private static final Protocol PROTOCOL = Protocol.HANDSHAKING; private static final Protocol PROTOCOL = Protocol.HANDSHAKING;
/**
* Incoming packets.
* @author Kristian
*/
public static class Client extends ObjectEnum<PacketType> { public static class Client extends ObjectEnum<PacketType> {
private final static Sender SENDER = Sender.CLIENT; private final static Sender SENDER = Sender.CLIENT;
/** /**
@ -92,6 +96,10 @@ public class PacketType implements Serializable {
public static class Play { public static class Play {
private static final Protocol PROTOCOL = Protocol.GAME; private static final Protocol PROTOCOL = Protocol.GAME;
/**
* Outgoing packets.
* @author Kristian
*/
public static class Server extends ObjectEnum<PacketType> { public static class Server extends ObjectEnum<PacketType> {
private final static Sender SENDER = Sender.SERVER; private final static Sender SENDER = Sender.SERVER;
@ -183,6 +191,10 @@ public class PacketType implements Serializable {
} }
} }
/**
* Incoming packets.
* @author Kristian
*/
public static class Client extends ObjectEnum<PacketType> { public static class Client extends ObjectEnum<PacketType> {
private final static Sender SENDER = Sender.CLIENT; private final static Sender SENDER = Sender.CLIENT;
@ -236,6 +248,10 @@ public class PacketType implements Serializable {
public static class Status { public static class Status {
private static final Protocol PROTOCOL = Protocol.STATUS; private static final Protocol PROTOCOL = Protocol.STATUS;
/**
* Outgoing packets.
* @author Kristian
*/
public static class Server extends ObjectEnum<PacketType> { public static class Server extends ObjectEnum<PacketType> {
private final static Sender SENDER = Sender.SERVER; private final static Sender SENDER = Sender.SERVER;
@ -256,6 +272,10 @@ public class PacketType implements Serializable {
} }
} }
/**
* Incoming packets.
* @author Kristian
*/
public static class Client extends ObjectEnum<PacketType> { public static class Client extends ObjectEnum<PacketType> {
private final static Sender SENDER = Sender.CLIENT; private final static Sender SENDER = Sender.CLIENT;
@ -288,6 +308,10 @@ public class PacketType implements Serializable {
public static class Login { public static class Login {
private static final Protocol PROTOCOL = Protocol.LOGIN; private static final Protocol PROTOCOL = Protocol.LOGIN;
/**
* Outgoing packets.
* @author Kristian
*/
public static class Server extends ObjectEnum<PacketType> { public static class Server extends ObjectEnum<PacketType> {
private final static Sender SENDER = Sender.SERVER; private final static Sender SENDER = Sender.SERVER;
@ -309,6 +333,10 @@ public class PacketType implements Serializable {
} }
} }
/**
* Incoming packets.
* @author Kristian
*/
public static class Client extends ObjectEnum<PacketType> { public static class Client extends ObjectEnum<PacketType> {
private final static Sender SENDER = Sender.CLIENT; private final static Sender SENDER = Sender.CLIENT;
@ -341,6 +369,10 @@ public class PacketType implements Serializable {
public static class Legacy { public static class Legacy {
private static final Protocol PROTOCOL = Protocol.LEGACY; private static final Protocol PROTOCOL = Protocol.LEGACY;
/**
* Outgoing packets.
* @author Kristian
*/
// Missing server packets: [10, 11, 12, 21, 107, 252] // Missing server packets: [10, 11, 12, 21, 107, 252]
public static class Server extends ObjectEnum<PacketType> { public static class Server extends ObjectEnum<PacketType> {
private final static Sender SENDER = Sender.SERVER; private final static Sender SENDER = Sender.SERVER;
@ -377,6 +409,10 @@ public class PacketType implements Serializable {
} }
} }
/**
* Incoming packets.
* @author Kristian
*/
// Missing client packets: [1, 9, 255] // Missing client packets: [1, 9, 255]
public static class Client extends ObjectEnum<PacketType> { public static class Client extends ObjectEnum<PacketType> {
private final static Sender SENDER = Sender.CLIENT; private final static Sender SENDER = Sender.CLIENT;

Datei anzeigen

@ -0,0 +1,50 @@
package com.comphenix.protocol.wrappers;
import com.google.common.base.Preconditions;
/**
* Represents a wrapper for an NMS object.
* @author Kristian
*/
public abstract class AbstractWrapper {
protected Object handle;
protected Class<?> handleType;
/**
* Construct a new NMS wrapper.
* @param handle - the wrapped NMS object.
*/
public AbstractWrapper(Class<?> handleType) {
this.handleType = Preconditions.checkNotNull(handleType, "handleType cannot be NULL");
}
/**
* Set the underlying NMS object.
* @param handle - the NMS object.
* @throws IllegalArgumentException If the handle is NULL.
* @throws IllegalArgumentException If the handle is not assignable to {@link #getHandleType()}.
*/
protected void setHandle(Object handle) {
if (handle == null)
throw new IllegalArgumentException("handle cannot be NULL.");
if (!handleType.isAssignableFrom(handle.getClass()))
throw new IllegalArgumentException("handle (" + handle + ") is not a " + handleType);
this.handle = handle;
}
/**
* Retrieves the underlying NMS object.
* @return The underlying NMS object.
*/
public Object getHandle() {
return handle;
}
/**
* Retrieve the type of the handle.
* @return The type of the handle.
*/
public Class<?> getHandleType() {
return handleType;
}
}

Datei anzeigen

@ -24,7 +24,7 @@ import com.google.common.collect.Sets;
* Represents a single attribute sent in packet 44. * Represents a single attribute sent in packet 44.
* @author Kristian * @author Kristian
*/ */
public class WrappedAttribute { public class WrappedAttribute extends AbstractWrapper {
// Shared structure modifier // Shared structure modifier
private static StructureModifier<Object> ATTRIBUTE_MODIFIER; private static StructureModifier<Object> ATTRIBUTE_MODIFIER;
@ -43,6 +43,22 @@ public class WrappedAttribute {
// Cached modifiers list // Cached modifiers list
private Set<WrappedAttributeModifier> attributeModifiers; private Set<WrappedAttributeModifier> attributeModifiers;
/**
* Construct a wrapper around a specific NMS instance.
* @param handle - the NMS instance.
*/
private WrappedAttribute(@Nonnull Object handle) {
super(MinecraftReflection.getAttributeSnapshotClass());
setHandle(handle);
// Initialize modifier
if (ATTRIBUTE_MODIFIER == null) {
ATTRIBUTE_MODIFIER = new StructureModifier<Object>(MinecraftReflection.getAttributeSnapshotClass());
}
this.modifier = ATTRIBUTE_MODIFIER.withTarget(handle);
}
/** /**
* Construct a new wrapped attribute around a specific NMS instance. * Construct a new wrapped attribute around a specific NMS instance.
* @param handle - handle to a NMS AttributeSnapshot. * @param handle - handle to a NMS AttributeSnapshot.
@ -70,33 +86,6 @@ public class WrappedAttribute {
return new Builder(Preconditions.checkNotNull(template, "template cannot be NULL.")); return new Builder(Preconditions.checkNotNull(template, "template cannot be NULL."));
} }
/**
* Construct a wrapper around a specific NMS instance.
* @param handle - the NMS instance.
*/
private WrappedAttribute(@Nonnull Object handle) {
this.handle = Preconditions.checkNotNull(handle, "handle cannot be NULL.");
// Check handle type
if (!MinecraftReflection.getAttributeSnapshotClass().isAssignableFrom(handle.getClass())) {
throw new IllegalArgumentException("handle (" + handle + ") must be a AttributeSnapshot.");
}
// Initialize modifier
if (ATTRIBUTE_MODIFIER == null) {
ATTRIBUTE_MODIFIER = new StructureModifier<Object>(MinecraftReflection.getAttributeSnapshotClass());
}
this.modifier = ATTRIBUTE_MODIFIER.withTarget(handle);
}
/**
* Retrieve the underlying NMS attribute snapshot.
* @return The underlying attribute snapshot.
*/
public Object getHandle() {
return handle;
}
/** /**
* Retrieve the unique attribute key that identifies its function. * Retrieve the unique attribute key that identifies its function.
* <p> * <p>

Datei anzeigen

@ -19,7 +19,7 @@ import com.google.common.base.Preconditions;
* *
* @author Kristian * @author Kristian
*/ */
public class WrappedAttributeModifier { public class WrappedAttributeModifier extends AbstractWrapper {
/** /**
* Represents the different modifier operations. * Represents the different modifier operations.
* <p> * <p>
@ -86,10 +86,7 @@ public class WrappedAttributeModifier {
// The constructor we are interested in // The constructor we are interested in
private static Constructor<?> ATTRIBUTE_MODIFIER_CONSTRUCTOR; private static Constructor<?> ATTRIBUTE_MODIFIER_CONSTRUCTOR;
/** // A modifier for the wrapped handler
* Handle to the underlying AttributeModifier.
*/
protected Object handle;
protected StructureModifier<Object> modifier; protected StructureModifier<Object> modifier;
// Cached values // Cached values
@ -98,6 +95,58 @@ public class WrappedAttributeModifier {
private final Operation operation; private final Operation operation;
private final double amount; private final double amount;
/**
* Construct a new wrapped attribute modifier with no associated handle.
* <p>
* Note that the handle object is not initialized after this constructor.
* @param uuid - the UUID.
* @param name - the human readable name.
* @param amount - the amount.
* @param operation - the operation.
*/
protected WrappedAttributeModifier(UUID uuid, String name, double amount, Operation operation) {
super(MinecraftReflection.getAttributeModifierClass());
// Use the supplied values instead of reading from the NMS instance
this.uuid = uuid;
this.name = name;
this.amount = amount;
this.operation = operation;
}
/**
* Construct an attribute modifier wrapper around a given NMS instance.
* @param handle - the NMS instance.
*/
protected WrappedAttributeModifier(@Nonnull Object handle) {
// Update handle and modifier
super(MinecraftReflection.getAttributeModifierClass());
setHandle(handle);
initializeModifier(handle);
// Load final values, caching them
this.uuid = (UUID) modifier.withType(UUID.class).read(0);
this.name = (String) modifier.withType(String.class).read(0);
this.amount = (Double) modifier.withType(double.class).read(0);
this.operation = Operation.fromId((Integer) modifier.withType(int.class).read(0));
}
/**
* Construct an attribute modifier wrapper around a NMS instance.
* @param handle - the NMS instance.
* @param uuid - the UUID.
* @param name - the human readable name.
* @param amount - the amount.
* @param operation - the operation.
*/
protected WrappedAttributeModifier(@Nonnull Object handle, UUID uuid, String name, double amount, Operation operation) {
this(uuid, name, amount, operation);
// Initialize handle and modifier
setHandle(handle);
initializeModifier(handle);
}
/** /**
* Construct a new attribute modifier builder. * Construct a new attribute modifier builder.
* <p> * <p>
@ -135,54 +184,7 @@ public class WrappedAttributeModifier {
public static WrappedAttributeModifier fromHandle(@Nonnull Object handle) { public static WrappedAttributeModifier fromHandle(@Nonnull Object handle) {
return new WrappedAttributeModifier(handle); return new WrappedAttributeModifier(handle);
} }
/**
* Construct a new wrapped attribute modifier with no associated handle.
* @param uuid - the UUID.
* @param name - the human readable name.
* @param amount - the amount.
* @param operation - the operation.
*/
protected WrappedAttributeModifier(UUID uuid, String name, double amount, Operation operation) {
// Use the supplied values instead of reading from the NMS instance
this.uuid = uuid;
this.name = name;
this.amount = amount;
this.operation = operation;
}
/**
* Construct an attribute modifier wrapper around a given NMS instance.
* @param handle - the NMS instance.
*/
protected WrappedAttributeModifier(@Nonnull Object handle) {
// Update handle and modifier
setHandle(handle);
initializeModifier(handle);
// Load final values, caching them
this.uuid = (UUID) modifier.withType(UUID.class).read(0);
this.name = (String) modifier.withType(String.class).read(0);
this.amount = (Double) modifier.withType(double.class).read(0);
this.operation = Operation.fromId((Integer) modifier.withType(int.class).read(0));
}
/**
* Construct an attribute modifier wrapper around a NMS instance.
* @param handle - the NMS instance.
* @param uuid - the UUID.
* @param name - the human readable name.
* @param amount - the amount.
* @param operation - the operation.
*/
protected WrappedAttributeModifier(@Nonnull Object handle, UUID uuid, String name, double amount, Operation operation) {
this(uuid, name, amount, operation);
// Initialize handle and modifier
setHandle(handle);
initializeModifier(handle);
}
/** /**
* Initialize modifier from a given handle. * Initialize modifier from a given handle.
* @param handle - the handle. * @param handle - the handle.
@ -196,17 +198,6 @@ public class WrappedAttributeModifier {
this.modifier = BASE_MODIFIER.withTarget(handle); this.modifier = BASE_MODIFIER.withTarget(handle);
} }
/**
* Set the handle of a modifier.
* @param handle - the underlying handle.
*/
private void setHandle(Object handle) {
// Check handle type
if (!MinecraftReflection.getAttributeModifierClass().isAssignableFrom(handle.getClass()))
throw new IllegalArgumentException("handle (" + handle + ") must be a AttributeModifier.");
this.handle = handle;
}
/** /**
* Retrieve the unique UUID that identifies the origin of this modifier. * Retrieve the unique UUID that identifies the origin of this modifier.
* @return The unique UUID. * @return The unique UUID.
@ -241,16 +232,6 @@ public class WrappedAttributeModifier {
return amount; return amount;
} }
/**
* Invoked when we need to construct a handle object.
*/
protected void checkHandle() {
if (handle == null) {
handle = newBuilder(this).build().getHandle();
initializeModifier(handle);
}
}
/** /**
* Retrieve the underlying attribute modifier. * Retrieve the underlying attribute modifier.
* @return The underlying modifier. * @return The underlying modifier.

Datei anzeigen

@ -11,7 +11,7 @@ import com.comphenix.protocol.utility.MinecraftReflection;
* Represents a chat component added in Minecraft 1.7.2 * Represents a chat component added in Minecraft 1.7.2
* @author Kristian * @author Kristian
*/ */
public class WrappedChatComponent { public class WrappedChatComponent extends AbstractWrapper {
private static final Class<?> SERIALIZER = MinecraftReflection.getChatSerializer(); private static final Class<?> SERIALIZER = MinecraftReflection.getChatSerializer();
private static final Class<?> COMPONENT = MinecraftReflection.getIChatBaseComponent(); private static final Class<?> COMPONENT = MinecraftReflection.getIChatBaseComponent();
private static MethodAccessor SERIALIZE_COMPONENT = null; private static MethodAccessor SERIALIZE_COMPONENT = null;
@ -32,11 +32,11 @@ public class WrappedChatComponent {
MinecraftReflection.getCraftChatMessage(), "fromString", String.class); MinecraftReflection.getCraftChatMessage(), "fromString", String.class);
} }
private Object handle;
private transient String cache; private transient String cache;
private WrappedChatComponent(Object handle, String cache) { private WrappedChatComponent(Object handle, String cache) {
this.handle = handle; super(MinecraftReflection.getIChatBaseComponent());
setHandle(handle);
this.cache = cache; this.cache = cache;
} }
@ -46,10 +46,6 @@ public class WrappedChatComponent {
* @return The wrapper. * @return The wrapper.
*/ */
public static WrappedChatComponent fromHandle(Object handle) { public static WrappedChatComponent fromHandle(Object handle) {
if (handle == null)
throw new IllegalArgumentException("handle cannot be NULL.");
if (!COMPONENT.isAssignableFrom(handle.getClass()))
throw new IllegalArgumentException("handle (" + handle + ") is not a " + COMPONENT);
return new WrappedChatComponent(handle, null); return new WrappedChatComponent(handle, null);
} }
@ -100,14 +96,6 @@ public class WrappedChatComponent {
this.handle = DESERIALIZE_COMPONENT.invoke(null, obj); this.handle = DESERIALIZE_COMPONENT.invoke(null, obj);
this.cache = obj; this.cache = obj;
} }
/**
* Retrieve the underlying IChatBaseComponent instance.
* @return The underlying instance.
*/
public Object getHandle() {
return handle;
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {

Datei anzeigen

@ -26,27 +26,26 @@ import com.google.common.base.Objects;
* *
* @author Kristian * @author Kristian
*/ */
public class WrappedChunkCoordinate implements Comparable<WrappedChunkCoordinate> { public class WrappedChunkCoordinate extends AbstractWrapper implements Comparable<WrappedChunkCoordinate> {
/** /**
* If TRUE, NULLs should be put before non-null instances of this class. * If TRUE, NULLs should be put before non-null instances of this class.
*/ */
private static final boolean LARGER_THAN_NULL = true; private static final boolean LARGER_THAN_NULL = true;
@SuppressWarnings("rawtypes")
protected Comparable handle;
// Used to access a ChunkCoordinate // Used to access a ChunkCoordinate
private static StructureModifier<Integer> intModifier; private static StructureModifier<Integer> SHARED_MODIFIER;
// The current modifier
private StructureModifier<Integer> handleModifier;
/** /**
* Create a new empty wrapper. * Create a new empty wrapper.
*/ */
@SuppressWarnings("rawtypes")
public WrappedChunkCoordinate() { public WrappedChunkCoordinate() {
try { super(MinecraftReflection.getChunkCoordinatesClass());
this.handle = (Comparable) MinecraftReflection.getChunkCoordinatesClass().newInstance();
initializeModifier(); try {
setHandle(getHandleType().newInstance());
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Cannot construct chunk coordinate."); throw new RuntimeException("Cannot construct chunk coordinate.");
} }
@ -58,17 +57,17 @@ public class WrappedChunkCoordinate implements Comparable<WrappedChunkCoordinate
*/ */
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public WrappedChunkCoordinate(Comparable handle) { public WrappedChunkCoordinate(Comparable handle) {
if (handle == null) super(MinecraftReflection.getChunkCoordinatesClass());
throw new IllegalArgumentException("handle cannot be NULL"); setHandle(handle);
this.handle = handle;
initializeModifier();
} }
// Ensure that the structure modifier is initialized // Ensure that the structure modifier is initialized
private void initializeModifier() { private StructureModifier<Integer> getModifier() {
if (intModifier == null) { if (SHARED_MODIFIER == null)
intModifier = new StructureModifier<Object>(handle.getClass(), null, false).withType(int.class); SHARED_MODIFIER = new StructureModifier<Object>(handle.getClass(), null, false).withType(int.class);
} if (handleModifier == null)
handleModifier = SHARED_MODIFIER.withTarget(handle);
return handleModifier;
} }
/** /**
@ -101,7 +100,7 @@ public class WrappedChunkCoordinate implements Comparable<WrappedChunkCoordinate
* @return The x coordinate. * @return The x coordinate.
*/ */
public int getX() { public int getX() {
return intModifier.read(0); return getModifier().read(0);
} }
/** /**
@ -109,7 +108,7 @@ public class WrappedChunkCoordinate implements Comparable<WrappedChunkCoordinate
* @param newX - the new x coordinate. * @param newX - the new x coordinate.
*/ */
public void setX(int newX) { public void setX(int newX) {
intModifier.write(0, newX); getModifier().write(0, newX);
} }
/** /**
@ -117,7 +116,7 @@ public class WrappedChunkCoordinate implements Comparable<WrappedChunkCoordinate
* @return The y coordinate. * @return The y coordinate.
*/ */
public int getY() { public int getY() {
return intModifier.read(1); return getModifier().read(1);
} }
/** /**
@ -125,7 +124,7 @@ public class WrappedChunkCoordinate implements Comparable<WrappedChunkCoordinate
* @param newY - the new y coordinate. * @param newY - the new y coordinate.
*/ */
public void setY(int newY) { public void setY(int newY) {
intModifier.write(1, newY); getModifier().write(1, newY);
} }
/** /**
@ -133,7 +132,7 @@ public class WrappedChunkCoordinate implements Comparable<WrappedChunkCoordinate
* @return The z coordinate. * @return The z coordinate.
*/ */
public int getZ() { public int getZ() {
return intModifier.read(2); return getModifier().read(2);
} }
/** /**
@ -141,7 +140,7 @@ public class WrappedChunkCoordinate implements Comparable<WrappedChunkCoordinate
* @param newZ - the new z coordinate. * @param newZ - the new z coordinate.
*/ */
public void setZ(int newZ) { public void setZ(int newZ) {
intModifier.write(2, newZ); getModifier().write(2, newZ);
} }
/** /**
@ -159,7 +158,7 @@ public class WrappedChunkCoordinate implements Comparable<WrappedChunkCoordinate
if (other.handle == null) if (other.handle == null)
return LARGER_THAN_NULL ? -1 : 1; return LARGER_THAN_NULL ? -1 : 1;
else else
return handle.compareTo(other.handle); return ((Comparable<Object>) handle).compareTo(other.handle);
} }
@Override @Override

Datei anzeigen

@ -52,35 +52,32 @@ import com.google.common.collect.Iterators;
* *
* @author Kristian * @author Kristian
*/ */
public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> { public class WrappedDataWatcher extends AbstractWrapper implements Iterable<WrappedWatchableObject> {
/** /**
* Used to assign integer IDs to given types. * Used to assign integer IDs to given types.
*/ */
private static Map<Class<?>, Integer> typeMap; private static Map<Class<?>, Integer> TYPE_MAP;
// Fields // Fields
private static Field valueMapField; private static Field VALUE_MAP_FIELD;
private static Field readWriteLockField; private static Field READ_WRITE_LOCK_FIELD;
private static Field entityField; private static Field ENTITY_FIELD;
// Methods // Methods
private static Method createKeyValueMethod; private static Method CREATE_KEY_VALUE_METHOD;
private static Method updateKeyValueMethod; private static Method UPDATE_KEY_VALUE_METHOD;
private static Method getKeyValueMethod; private static Method GET_KEY_VALUE_METHOD;
// Constructors // Constructors
private static Constructor<?> createDataWatcherConstructor; private static Constructor<?> CREATE_DATA_WATCHER_CONSTRUCTOR;
// Entity methods // Entity methods
private volatile static Field entityDataField; private volatile static Field ENTITY_DATA_FIELD;
/** /**
* Whether or not this class has already been initialized. * Whether or not this class has already been initialized.
*/ */
private static boolean hasInitialized; private static boolean HAS_INITIALIZED;
// The underlying DataWatcher we're modifying
protected Object handle;
// Lock // Lock
private ReadWriteLock readWriteLock; private ReadWriteLock readWriteLock;
@ -96,12 +93,14 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
* @throws FieldAccessException If we're unable to wrap a DataWatcher. * @throws FieldAccessException If we're unable to wrap a DataWatcher.
*/ */
public WrappedDataWatcher() { public WrappedDataWatcher() {
super(MinecraftReflection.getDataWatcherClass());
// Just create a new watcher // Just create a new watcher
try { try {
if (MinecraftReflection.isUsingNetty()) { if (MinecraftReflection.isUsingNetty()) {
this.handle = newEntityHandle(null); setHandle(newEntityHandle(null));
} else { } else {
this.handle = MinecraftReflection.getDataWatcherClass().newInstance(); setHandle(getHandleType().newInstance());
} }
initialize(); initialize();
@ -116,12 +115,8 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
* @throws FieldAccessException If we're unable to wrap a DataWatcher. * @throws FieldAccessException If we're unable to wrap a DataWatcher.
*/ */
public WrappedDataWatcher(Object handle) { public WrappedDataWatcher(Object handle) {
if (handle == null) super(MinecraftReflection.getDataWatcherClass());
throw new IllegalArgumentException("Handle cannot be NULL."); setHandle(handle);
if (!MinecraftReflection.isDataWatcher(handle))
throw new IllegalArgumentException("The value " + handle + " is not a DataWatcher.");
this.handle = handle;
initialize(); initialize();
} }
@ -150,10 +145,10 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
Class<?> dataWatcher = MinecraftReflection.getDataWatcherClass(); Class<?> dataWatcher = MinecraftReflection.getDataWatcherClass();
try { try {
if (createDataWatcherConstructor == null) if (CREATE_DATA_WATCHER_CONSTRUCTOR == null)
createDataWatcherConstructor = dataWatcher.getConstructor(MinecraftReflection.getEntityClass()); CREATE_DATA_WATCHER_CONSTRUCTOR = dataWatcher.getConstructor(MinecraftReflection.getEntityClass());
return createDataWatcherConstructor.newInstance( return CREATE_DATA_WATCHER_CONSTRUCTOR.newInstance(
BukkitUnwrapper.getInstance().unwrapItem(entity) BukkitUnwrapper.getInstance().unwrapItem(entity)
); );
} catch (Exception e) { } catch (Exception e) {
@ -190,14 +185,6 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
} }
} }
/**
* Retrieves the underlying data watcher.
* @return The underlying data watcher.
*/
public Object getHandle() {
return handle;
}
/** /**
* Retrieve the ID of a given type, if it's allowed to be watched. * Retrieve the ID of a given type, if it's allowed to be watched.
* @return The ID, or NULL if it cannot be watched. * @return The ID, or NULL if it cannot be watched.
@ -205,7 +192,7 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
*/ */
public static Integer getTypeID(Class<?> clazz) throws FieldAccessException { public static Integer getTypeID(Class<?> clazz) throws FieldAccessException {
initialize(); initialize();
return typeMap.get(WrappedWatchableObject.getUnwrappedType(clazz)); return TYPE_MAP.get(WrappedWatchableObject.getUnwrappedType(clazz));
} }
/** /**
@ -216,7 +203,7 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
public static Class<?> getTypeClass(int id) throws FieldAccessException { public static Class<?> getTypeClass(int id) throws FieldAccessException {
initialize(); initialize();
for (Map.Entry<Class<?>, Integer> entry : typeMap.entrySet()) { for (Map.Entry<Class<?>, Integer> entry : TYPE_MAP.entrySet()) {
if (Objects.equal(entry.getValue(), id)) { if (Objects.equal(entry.getValue(), id)) {
return entry.getKey(); return entry.getKey();
} }
@ -462,7 +449,7 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
if (watchable != null) { if (watchable != null) {
new WrappedWatchableObject(watchable).setValue(newValue, update); new WrappedWatchableObject(watchable).setValue(newValue, update);
} else { } else {
createKeyValueMethod.invoke(handle, index, WrappedWatchableObject.getUnwrapped(newValue)); CREATE_KEY_VALUE_METHOD.invoke(handle, index, WrappedWatchableObject.getUnwrapped(newValue));
} }
// Handle invoking the method // Handle invoking the method
@ -479,9 +466,9 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
private Object getWatchedObject(int index) throws FieldAccessException { private Object getWatchedObject(int index) throws FieldAccessException {
// We use the get-method first and foremost // We use the get-method first and foremost
if (getKeyValueMethod != null) { if (GET_KEY_VALUE_METHOD != null) {
try { try {
return getKeyValueMethod.invoke(handle, index); return GET_KEY_VALUE_METHOD.invoke(handle, index);
} catch (Exception e) { } catch (Exception e) {
throw new FieldAccessException("Cannot invoke get key method for index " + index, e); throw new FieldAccessException("Cannot invoke get key method for index " + index, e);
} }
@ -506,8 +493,8 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
// Cache the read write lock // Cache the read write lock
if (readWriteLock != null) if (readWriteLock != null)
return readWriteLock; return readWriteLock;
else if (readWriteLockField != null) else if (READ_WRITE_LOCK_FIELD != null)
return readWriteLock = (ReadWriteLock) FieldUtils.readField(readWriteLockField, handle, true); return readWriteLock = (ReadWriteLock) FieldUtils.readField(READ_WRITE_LOCK_FIELD, handle, true);
else else
return readWriteLock = new ReentrantReadWriteLock(); return readWriteLock = new ReentrantReadWriteLock();
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
@ -524,7 +511,7 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
protected Map<Integer, Object> getWatchableObjectMap() throws FieldAccessException { protected Map<Integer, Object> getWatchableObjectMap() throws FieldAccessException {
if (watchableObjects == null) { if (watchableObjects == null) {
try { try {
watchableObjects = (Map<Integer, Object>) FieldUtils.readField(valueMapField, handle, true); watchableObjects = (Map<Integer, Object>) FieldUtils.readField(VALUE_MAP_FIELD, handle, true);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw new FieldAccessException("Cannot read watchable object field.", e); throw new FieldAccessException("Cannot read watchable object field.", e);
} }
@ -539,14 +526,14 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
* @throws FieldAccessException Reflection failed. * @throws FieldAccessException Reflection failed.
*/ */
public static WrappedDataWatcher getEntityWatcher(Entity entity) throws FieldAccessException { public static WrappedDataWatcher getEntityWatcher(Entity entity) throws FieldAccessException {
if (entityDataField == null) if (ENTITY_DATA_FIELD == null)
entityDataField = FuzzyReflection.fromClass(MinecraftReflection.getEntityClass(), true). ENTITY_DATA_FIELD = FuzzyReflection.fromClass(MinecraftReflection.getEntityClass(), true).
getFieldByType("datawatcher", MinecraftReflection.getDataWatcherClass()); getFieldByType("datawatcher", MinecraftReflection.getDataWatcherClass());
BukkitUnwrapper unwrapper = new BukkitUnwrapper(); BukkitUnwrapper unwrapper = new BukkitUnwrapper();
try { try {
Object nsmWatcher = FieldUtils.readField(entityDataField, unwrapper.unwrapItem(entity), true); Object nsmWatcher = FieldUtils.readField(ENTITY_DATA_FIELD, unwrapper.unwrapItem(entity), true);
if (nsmWatcher != null) if (nsmWatcher != null)
return new WrappedDataWatcher(nsmWatcher); return new WrappedDataWatcher(nsmWatcher);
@ -564,8 +551,8 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static void initialize() throws FieldAccessException { private static void initialize() throws FieldAccessException {
// This method should only be run once, even if an exception is thrown // This method should only be run once, even if an exception is thrown
if (!hasInitialized) if (!HAS_INITIALIZED)
hasInitialized = true; HAS_INITIALIZED = true;
else else
return; return;
@ -575,27 +562,27 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
if (Modifier.isStatic(lookup.getModifiers())) { if (Modifier.isStatic(lookup.getModifiers())) {
// This must be the type map // This must be the type map
try { try {
typeMap = (Map<Class<?>, Integer>) FieldUtils.readStaticField(lookup, true); TYPE_MAP = (Map<Class<?>, Integer>) FieldUtils.readStaticField(lookup, true);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw new FieldAccessException("Cannot access type map field.", e); throw new FieldAccessException("Cannot access type map field.", e);
} }
} else { } else {
// If not, then we're probably dealing with the value map // If not, then we're probably dealing with the value map
valueMapField = lookup; VALUE_MAP_FIELD = lookup;
} }
} }
try { try {
readWriteLockField = fuzzy.getFieldByType("readWriteLock", ReadWriteLock.class); READ_WRITE_LOCK_FIELD = fuzzy.getFieldByType("readWriteLock", ReadWriteLock.class);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// It's not a big deal // It's not a big deal
} }
// Check for the entity field as well // Check for the entity field as well
if (MinecraftReflection.isUsingNetty()) { if (MinecraftReflection.isUsingNetty()) {
entityField = fuzzy.getFieldByType("entity", MinecraftReflection.getEntityClass()); ENTITY_FIELD = fuzzy.getFieldByType("entity", MinecraftReflection.getEntityClass());
entityField.setAccessible(true); ENTITY_FIELD.setAccessible(true);
} }
initializeMethods(fuzzy); initializeMethods(fuzzy);
} }
@ -606,9 +593,9 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
// Load the get-method // Load the get-method
try { try {
getKeyValueMethod = fuzzy.getMethodByParameters( GET_KEY_VALUE_METHOD = fuzzy.getMethodByParameters(
"getWatchableObject", MinecraftReflection.getWatchableObjectClass(), new Class[] { int.class }); "getWatchableObject", MinecraftReflection.getWatchableObjectClass(), new Class[] { int.class });
getKeyValueMethod.setAccessible(true); GET_KEY_VALUE_METHOD.setAccessible(true);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// Use the fallback method // Use the fallback method
@ -616,18 +603,18 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
for (Method method : candidates) { for (Method method : candidates) {
if (!method.getName().startsWith("watch")) { if (!method.getName().startsWith("watch")) {
createKeyValueMethod = method; CREATE_KEY_VALUE_METHOD = method;
} else { } else {
updateKeyValueMethod = method; UPDATE_KEY_VALUE_METHOD = method;
} }
} }
// Did we succeed? // Did we succeed?
if (updateKeyValueMethod == null || createKeyValueMethod == null) { if (UPDATE_KEY_VALUE_METHOD == null || CREATE_KEY_VALUE_METHOD == null) {
// Go by index instead // Go by index instead
if (candidates.size() > 1) { if (candidates.size() > 1) {
createKeyValueMethod = candidates.get(0); CREATE_KEY_VALUE_METHOD = candidates.get(0);
updateKeyValueMethod = candidates.get(1); UPDATE_KEY_VALUE_METHOD = candidates.get(1);
} else { } else {
throw new IllegalStateException("Unable to find create and update watchable object. Update ProtocolLib."); throw new IllegalStateException("Unable to find create and update watchable object. Update ProtocolLib.");
} }
@ -643,8 +630,8 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
} }
} catch (Exception e) { } catch (Exception e) {
// Nope // Nope
updateKeyValueMethod = candidates.get(0); UPDATE_KEY_VALUE_METHOD = candidates.get(0);
createKeyValueMethod = candidates.get(1); CREATE_KEY_VALUE_METHOD = candidates.get(1);
} }
} }
} }
@ -709,7 +696,7 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
throw new IllegalStateException("This method is only supported on 1.7.2 and above."); throw new IllegalStateException("This method is only supported on 1.7.2 and above.");
try { try {
return (Entity) MinecraftReflection.getBukkitEntity(entityField.get(handle)); return (Entity) MinecraftReflection.getBukkitEntity(ENTITY_FIELD.get(handle));
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Unable to retrieve entity.", e); throw new RuntimeException("Unable to retrieve entity.", e);
} }
@ -726,7 +713,7 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
throw new IllegalStateException("This method is only supported on 1.7.2 and above."); throw new IllegalStateException("This method is only supported on 1.7.2 and above.");
try { try {
entityField.set(handle, BukkitUnwrapper.getInstance().unwrapItem(entity)); ENTITY_FIELD.set(handle, BukkitUnwrapper.getInstance().unwrapItem(entity));
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Unable to set entity.", e); throw new RuntimeException("Unable to set entity.", e);
} }

Datei anzeigen

@ -6,16 +6,11 @@ import net.minecraft.util.com.mojang.authlib.GameProfile;
* Represents a wrapper for a game profile. * Represents a wrapper for a game profile.
* @author Kristian * @author Kristian
*/ */
public class WrappedGameProfile { public class WrappedGameProfile extends AbstractWrapper {
private GameProfile profile;
// Profile from a handle // Profile from a handle
private WrappedGameProfile(Object profile) { private WrappedGameProfile(Object profile) {
if (profile == null) super(GameProfile.class);
throw new IllegalArgumentException("Profile cannot be NULL."); setHandle(profile);
if (!(profile instanceof GameProfile))
throw new IllegalArgumentException(profile + " is not a GameProfile");
this.profile = (GameProfile) profile;
} }
/** /**
@ -34,21 +29,13 @@ public class WrappedGameProfile {
public static WrappedGameProfile fromHandle(Object handle) { public static WrappedGameProfile fromHandle(Object handle) {
return new WrappedGameProfile(handle); return new WrappedGameProfile(handle);
} }
/**
* Retrieve the underlying game profile.
* @return The profile.
*/
public Object getHandle() {
return profile;
}
/** /**
* Retrieve the UUID of the player. * Retrieve the UUID of the player.
* @return The UUID of the player, or NULL if not computed. * @return The UUID of the player, or NULL if not computed.
*/ */
public String getId() { public String getId() {
return profile.getId(); return getProfile().getId();
} }
/** /**
@ -56,7 +43,11 @@ public class WrappedGameProfile {
* @return The player name. * @return The player name.
*/ */
public String getName() { public String getName() {
return profile.getName(); return getProfile().getName();
}
private GameProfile getProfile() {
return (GameProfile) handle;
} }
/** /**
@ -82,12 +73,12 @@ public class WrappedGameProfile {
* @return TRUE if it does, FALSE otherwise. * @return TRUE if it does, FALSE otherwise.
*/ */
public boolean isComplete() { public boolean isComplete() {
return profile.isComplete(); return getProfile().isComplete();
} }
@Override @Override
public int hashCode() { public int hashCode() {
return profile.hashCode(); return getProfile().hashCode();
} }
@Override @Override
@ -97,7 +88,7 @@ public class WrappedGameProfile {
if (obj instanceof WrappedGameProfile) { if (obj instanceof WrappedGameProfile) {
WrappedGameProfile other = (WrappedGameProfile) obj; WrappedGameProfile other = (WrappedGameProfile) obj;
return profile.equals(other.profile); return getProfile().equals(other.getProfile());
} }
return false; return false;
} }

Datei anzeigen

@ -15,21 +15,18 @@ import com.google.common.base.Preconditions;
* Represents a wrapper for the internal IntHashMap in Minecraft. * Represents a wrapper for the internal IntHashMap in Minecraft.
* @author Kristian * @author Kristian
*/ */
public class WrappedIntHashMap { public class WrappedIntHashMap extends AbstractWrapper {
private static final Class<?> INT_HASH_MAP = MinecraftReflection.getIntHashMapClass();
private static Method PUT_METHOD; private static Method PUT_METHOD;
private static Method GET_METHOD; private static Method GET_METHOD;
private static Method REMOVE_METHOD; private static Method REMOVE_METHOD;
private Object handle;
/** /**
* Construct an IntHashMap wrapper around an instance. * Construct an IntHashMap wrapper around an instance.
* @param handle - the NMS instance. * @param handle - the NMS instance.
*/ */
private WrappedIntHashMap(Object handle) { private WrappedIntHashMap(Object handle) {
this.handle = handle; super(MinecraftReflection.getIntHashMapClass());
setHandle(handle);
} }
/** /**
@ -38,7 +35,7 @@ public class WrappedIntHashMap {
*/ */
public static WrappedIntHashMap newMap() { public static WrappedIntHashMap newMap() {
try { try {
return new WrappedIntHashMap(INT_HASH_MAP.newInstance()); return new WrappedIntHashMap(MinecraftReflection.getIntHashMapClass().newInstance());
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Unable to construct IntHashMap.", e); throw new RuntimeException("Unable to construct IntHashMap.", e);
} }
@ -51,10 +48,6 @@ public class WrappedIntHashMap {
* @throws IllegalArgumentException If the handle is not an IntHasMap. * @throws IllegalArgumentException If the handle is not an IntHasMap.
*/ */
public static WrappedIntHashMap fromHandle(@Nonnull Object handle) { public static WrappedIntHashMap fromHandle(@Nonnull Object handle) {
Preconditions.checkNotNull(handle, "handle cannot be NULL");
Preconditions.checkState(MinecraftReflection.isIntHashMap(handle),
"handle is a " + handle.getClass() + ", not an IntHashMap.");
return new WrappedIntHashMap(handle); return new WrappedIntHashMap(handle);
} }
@ -138,7 +131,7 @@ public class WrappedIntHashMap {
private void initializePutMethod() { private void initializePutMethod() {
if (PUT_METHOD == null) { if (PUT_METHOD == null) {
// Fairly straight forward // Fairly straight forward
PUT_METHOD = FuzzyReflection.fromClass(INT_HASH_MAP).getMethod( PUT_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getIntHashMapClass()).getMethod(
FuzzyMethodContract.newBuilder(). FuzzyMethodContract.newBuilder().
banModifier(Modifier.STATIC). banModifier(Modifier.STATIC).
parameterCount(2). parameterCount(2).
@ -154,7 +147,7 @@ public class WrappedIntHashMap {
String expected = "hello"; String expected = "hello";
// Determine which method to trust // Determine which method to trust
for (Method method : FuzzyReflection.fromClass(INT_HASH_MAP). for (Method method : FuzzyReflection.fromClass(MinecraftReflection.getIntHashMapClass()).
getMethodListByParameters(Object.class, new Class<?>[] { int.class })) { getMethodListByParameters(Object.class, new Class<?>[] { int.class })) {
// Initialize a value // Initialize a value
@ -183,12 +176,4 @@ public class WrappedIntHashMap {
throw new IllegalStateException("Unable to find appropriate GET_METHOD for IntHashMap."); throw new IllegalStateException("Unable to find appropriate GET_METHOD for IntHashMap.");
} }
} }
/**
* Retrieve the underlying IntHashMap object.
* @return The underlying object.
*/
public Object getHandle() {
return handle;
}
} }

Datei anzeigen

@ -33,8 +33,7 @@ import com.google.common.base.Objects;
* *
* @author Kristian * @author Kristian
*/ */
public class WrappedWatchableObject { public class WrappedWatchableObject extends AbstractWrapper {
// Whether or not the reflection machinery has been initialized // Whether or not the reflection machinery has been initialized
private static boolean hasInitialized; private static boolean hasInitialized;
@ -47,7 +46,6 @@ public class WrappedWatchableObject {
// The watchable object class type // The watchable object class type
private static Class<?> watchableObjectClass; private static Class<?> watchableObjectClass;
protected Object handle;
protected StructureModifier<Object> modifier; protected StructureModifier<Object> modifier;
// Type of the stored value // Type of the stored value
@ -58,6 +56,7 @@ public class WrappedWatchableObject {
* @param handle - the raw watchable object to wrap. * @param handle - the raw watchable object to wrap.
*/ */
public WrappedWatchableObject(Object handle) { public WrappedWatchableObject(Object handle) {
super(MinecraftReflection.getWatchableObjectClass());
load(handle); load(handle);
} }
@ -67,6 +66,8 @@ public class WrappedWatchableObject {
* @param value - non-null value of specific types. * @param value - non-null value of specific types.
*/ */
public WrappedWatchableObject(int index, Object value) { public WrappedWatchableObject(int index, Object value) {
super(MinecraftReflection.getWatchableObjectClass());
if (value == null) if (value == null)
throw new IllegalArgumentException("Value cannot be NULL."); throw new IllegalArgumentException("Value cannot be NULL.");
@ -107,14 +108,6 @@ public class WrappedWatchableObject {
} }
} }
/**
* Retrieves the underlying watchable object.
* @return The underlying watchable object.
*/
public Object getHandle() {
return handle;
}
/** /**
* Initialize reflection machinery. * Initialize reflection machinery.
*/ */

Datei anzeigen

@ -0,0 +1,24 @@
package com.comphenix.protocol.wrappers;
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.Test;
import com.comphenix.protocol.BukkitInitialization;
public class WrappedChunkCoordinateTest {
@BeforeClass
public static void initializeBukkit() throws IllegalAccessException {
BukkitInitialization.initializePackage();
}
@Test
public void test() {
WrappedChunkCoordinate coordinate = new WrappedChunkCoordinate(1, 2, 3);
assertEquals(1, coordinate.getX());
assertEquals(2, coordinate.getY());
assertEquals(3, coordinate.getZ());
}
}

Datei anzeigen

@ -0,0 +1,24 @@
package com.comphenix.protocol.wrappers;
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.Test;
import com.comphenix.protocol.BukkitInitialization;
public class WrappedIntHashMapTest {
@BeforeClass
public static void initializeBukkit() throws IllegalAccessException {
BukkitInitialization.initializePackage();
}
@Test
public void testIntMap() {
WrappedIntHashMap test = WrappedIntHashMap.newMap();
test.put(1, "hello");
assertNull(test.get(0));
assertEquals(test.get(1), "hello");
}
}