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 {
private static final Protocol PROTOCOL = Protocol.HANDSHAKING;
/**
* Incoming packets.
* @author Kristian
*/
public static class Client extends ObjectEnum<PacketType> {
private final static Sender SENDER = Sender.CLIENT;
/**
@ -92,6 +96,10 @@ public class PacketType implements Serializable {
public static class Play {
private static final Protocol PROTOCOL = Protocol.GAME;
/**
* Outgoing packets.
* @author Kristian
*/
public static class Server extends ObjectEnum<PacketType> {
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> {
private final static Sender SENDER = Sender.CLIENT;
@ -236,6 +248,10 @@ public class PacketType implements Serializable {
public static class Status {
private static final Protocol PROTOCOL = Protocol.STATUS;
/**
* Outgoing packets.
* @author Kristian
*/
public static class Server extends ObjectEnum<PacketType> {
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> {
private final static Sender SENDER = Sender.CLIENT;
@ -288,6 +308,10 @@ public class PacketType implements Serializable {
public static class Login {
private static final Protocol PROTOCOL = Protocol.LOGIN;
/**
* Outgoing packets.
* @author Kristian
*/
public static class Server extends ObjectEnum<PacketType> {
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> {
private final static Sender SENDER = Sender.CLIENT;
@ -341,6 +369,10 @@ public class PacketType implements Serializable {
public static class Legacy {
private static final Protocol PROTOCOL = Protocol.LEGACY;
/**
* Outgoing packets.
* @author Kristian
*/
// Missing server packets: [10, 11, 12, 21, 107, 252]
public static class Server extends ObjectEnum<PacketType> {
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]
public static class Client extends ObjectEnum<PacketType> {
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.
* @author Kristian
*/
public class WrappedAttribute {
public class WrappedAttribute extends AbstractWrapper {
// Shared structure modifier
private static StructureModifier<Object> ATTRIBUTE_MODIFIER;
@ -43,6 +43,22 @@ public class WrappedAttribute {
// Cached modifiers list
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.
* @param handle - handle to a NMS AttributeSnapshot.
@ -70,33 +86,6 @@ public class WrappedAttribute {
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.
* <p>

Datei anzeigen

@ -19,7 +19,7 @@ import com.google.common.base.Preconditions;
*
* @author Kristian
*/
public class WrappedAttributeModifier {
public class WrappedAttributeModifier extends AbstractWrapper {
/**
* Represents the different modifier operations.
* <p>
@ -86,10 +86,7 @@ public class WrappedAttributeModifier {
// The constructor we are interested in
private static Constructor<?> ATTRIBUTE_MODIFIER_CONSTRUCTOR;
/**
* Handle to the underlying AttributeModifier.
*/
protected Object handle;
// A modifier for the wrapped handler
protected StructureModifier<Object> modifier;
// Cached values
@ -98,6 +95,58 @@ public class WrappedAttributeModifier {
private final Operation operation;
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.
* <p>
@ -135,54 +184,7 @@ public class WrappedAttributeModifier {
public static WrappedAttributeModifier fromHandle(@Nonnull Object 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.
* @param handle - the handle.
@ -196,17 +198,6 @@ public class WrappedAttributeModifier {
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.
* @return The unique UUID.
@ -241,16 +232,6 @@ public class WrappedAttributeModifier {
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.
* @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
* @author Kristian
*/
public class WrappedChatComponent {
public class WrappedChatComponent extends AbstractWrapper {
private static final Class<?> SERIALIZER = MinecraftReflection.getChatSerializer();
private static final Class<?> COMPONENT = MinecraftReflection.getIChatBaseComponent();
private static MethodAccessor SERIALIZE_COMPONENT = null;
@ -32,11 +32,11 @@ public class WrappedChatComponent {
MinecraftReflection.getCraftChatMessage(), "fromString", String.class);
}
private Object handle;
private transient String cache;
private WrappedChatComponent(Object handle, String cache) {
this.handle = handle;
super(MinecraftReflection.getIChatBaseComponent());
setHandle(handle);
this.cache = cache;
}
@ -46,10 +46,6 @@ public class WrappedChatComponent {
* @return The wrapper.
*/
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);
}
@ -100,14 +96,6 @@ public class WrappedChatComponent {
this.handle = DESERIALIZE_COMPONENT.invoke(null, obj);
this.cache = obj;
}
/**
* Retrieve the underlying IChatBaseComponent instance.
* @return The underlying instance.
*/
public Object getHandle() {
return handle;
}
@Override
public boolean equals(Object obj) {

Datei anzeigen

@ -26,27 +26,26 @@ import com.google.common.base.Objects;
*
* @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.
*/
private static final boolean LARGER_THAN_NULL = true;
@SuppressWarnings("rawtypes")
protected Comparable handle;
// 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.
*/
@SuppressWarnings("rawtypes")
public WrappedChunkCoordinate() {
try {
this.handle = (Comparable) MinecraftReflection.getChunkCoordinatesClass().newInstance();
initializeModifier();
super(MinecraftReflection.getChunkCoordinatesClass());
try {
setHandle(getHandleType().newInstance());
} catch (Exception e) {
throw new RuntimeException("Cannot construct chunk coordinate.");
}
@ -58,17 +57,17 @@ public class WrappedChunkCoordinate implements Comparable<WrappedChunkCoordinate
*/
@SuppressWarnings("rawtypes")
public WrappedChunkCoordinate(Comparable handle) {
if (handle == null)
throw new IllegalArgumentException("handle cannot be NULL");
this.handle = handle;
initializeModifier();
super(MinecraftReflection.getChunkCoordinatesClass());
setHandle(handle);
}
// Ensure that the structure modifier is initialized
private void initializeModifier() {
if (intModifier == null) {
intModifier = new StructureModifier<Object>(handle.getClass(), null, false).withType(int.class);
}
private StructureModifier<Integer> getModifier() {
if (SHARED_MODIFIER == null)
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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
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)
return LARGER_THAN_NULL ? -1 : 1;
else
return handle.compareTo(other.handle);
return ((Comparable<Object>) handle).compareTo(other.handle);
}
@Override

Datei anzeigen

@ -52,35 +52,32 @@ import com.google.common.collect.Iterators;
*
* @author Kristian
*/
public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
public class WrappedDataWatcher extends AbstractWrapper implements Iterable<WrappedWatchableObject> {
/**
* Used to assign integer IDs to given types.
*/
private static Map<Class<?>, Integer> typeMap;
private static Map<Class<?>, Integer> TYPE_MAP;
// Fields
private static Field valueMapField;
private static Field readWriteLockField;
private static Field entityField;
private static Field VALUE_MAP_FIELD;
private static Field READ_WRITE_LOCK_FIELD;
private static Field ENTITY_FIELD;
// Methods
private static Method createKeyValueMethod;
private static Method updateKeyValueMethod;
private static Method getKeyValueMethod;
private static Method CREATE_KEY_VALUE_METHOD;
private static Method UPDATE_KEY_VALUE_METHOD;
private static Method GET_KEY_VALUE_METHOD;
// Constructors
private static Constructor<?> createDataWatcherConstructor;
private static Constructor<?> CREATE_DATA_WATCHER_CONSTRUCTOR;
// Entity methods
private volatile static Field entityDataField;
private volatile static Field ENTITY_DATA_FIELD;
/**
* Whether or not this class has already been initialized.
*/
private static boolean hasInitialized;
// The underlying DataWatcher we're modifying
protected Object handle;
private static boolean HAS_INITIALIZED;
// Lock
private ReadWriteLock readWriteLock;
@ -96,12 +93,14 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
* @throws FieldAccessException If we're unable to wrap a DataWatcher.
*/
public WrappedDataWatcher() {
super(MinecraftReflection.getDataWatcherClass());
// Just create a new watcher
try {
if (MinecraftReflection.isUsingNetty()) {
this.handle = newEntityHandle(null);
setHandle(newEntityHandle(null));
} else {
this.handle = MinecraftReflection.getDataWatcherClass().newInstance();
setHandle(getHandleType().newInstance());
}
initialize();
@ -116,12 +115,8 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
* @throws FieldAccessException If we're unable to wrap a DataWatcher.
*/
public WrappedDataWatcher(Object handle) {
if (handle == null)
throw new IllegalArgumentException("Handle cannot be NULL.");
if (!MinecraftReflection.isDataWatcher(handle))
throw new IllegalArgumentException("The value " + handle + " is not a DataWatcher.");
this.handle = handle;
super(MinecraftReflection.getDataWatcherClass());
setHandle(handle);
initialize();
}
@ -150,10 +145,10 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
Class<?> dataWatcher = MinecraftReflection.getDataWatcherClass();
try {
if (createDataWatcherConstructor == null)
createDataWatcherConstructor = dataWatcher.getConstructor(MinecraftReflection.getEntityClass());
if (CREATE_DATA_WATCHER_CONSTRUCTOR == null)
CREATE_DATA_WATCHER_CONSTRUCTOR = dataWatcher.getConstructor(MinecraftReflection.getEntityClass());
return createDataWatcherConstructor.newInstance(
return CREATE_DATA_WATCHER_CONSTRUCTOR.newInstance(
BukkitUnwrapper.getInstance().unwrapItem(entity)
);
} 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.
* @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 {
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 {
initialize();
for (Map.Entry<Class<?>, Integer> entry : typeMap.entrySet()) {
for (Map.Entry<Class<?>, Integer> entry : TYPE_MAP.entrySet()) {
if (Objects.equal(entry.getValue(), id)) {
return entry.getKey();
}
@ -462,7 +449,7 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
if (watchable != null) {
new WrappedWatchableObject(watchable).setValue(newValue, update);
} else {
createKeyValueMethod.invoke(handle, index, WrappedWatchableObject.getUnwrapped(newValue));
CREATE_KEY_VALUE_METHOD.invoke(handle, index, WrappedWatchableObject.getUnwrapped(newValue));
}
// Handle invoking the method
@ -479,9 +466,9 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
private Object getWatchedObject(int index) throws FieldAccessException {
// We use the get-method first and foremost
if (getKeyValueMethod != null) {
if (GET_KEY_VALUE_METHOD != null) {
try {
return getKeyValueMethod.invoke(handle, index);
return GET_KEY_VALUE_METHOD.invoke(handle, index);
} catch (Exception 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
if (readWriteLock != null)
return readWriteLock;
else if (readWriteLockField != null)
return readWriteLock = (ReadWriteLock) FieldUtils.readField(readWriteLockField, handle, true);
else if (READ_WRITE_LOCK_FIELD != null)
return readWriteLock = (ReadWriteLock) FieldUtils.readField(READ_WRITE_LOCK_FIELD, handle, true);
else
return readWriteLock = new ReentrantReadWriteLock();
} catch (IllegalAccessException e) {
@ -524,7 +511,7 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
protected Map<Integer, Object> getWatchableObjectMap() throws FieldAccessException {
if (watchableObjects == null) {
try {
watchableObjects = (Map<Integer, Object>) FieldUtils.readField(valueMapField, handle, true);
watchableObjects = (Map<Integer, Object>) FieldUtils.readField(VALUE_MAP_FIELD, handle, true);
} catch (IllegalAccessException e) {
throw new FieldAccessException("Cannot read watchable object field.", e);
}
@ -539,14 +526,14 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
* @throws FieldAccessException Reflection failed.
*/
public static WrappedDataWatcher getEntityWatcher(Entity entity) throws FieldAccessException {
if (entityDataField == null)
entityDataField = FuzzyReflection.fromClass(MinecraftReflection.getEntityClass(), true).
if (ENTITY_DATA_FIELD == null)
ENTITY_DATA_FIELD = FuzzyReflection.fromClass(MinecraftReflection.getEntityClass(), true).
getFieldByType("datawatcher", MinecraftReflection.getDataWatcherClass());
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
try {
Object nsmWatcher = FieldUtils.readField(entityDataField, unwrapper.unwrapItem(entity), true);
Object nsmWatcher = FieldUtils.readField(ENTITY_DATA_FIELD, unwrapper.unwrapItem(entity), true);
if (nsmWatcher != null)
return new WrappedDataWatcher(nsmWatcher);
@ -564,8 +551,8 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
@SuppressWarnings("unchecked")
private static void initialize() throws FieldAccessException {
// This method should only be run once, even if an exception is thrown
if (!hasInitialized)
hasInitialized = true;
if (!HAS_INITIALIZED)
HAS_INITIALIZED = true;
else
return;
@ -575,27 +562,27 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
if (Modifier.isStatic(lookup.getModifiers())) {
// This must be the type map
try {
typeMap = (Map<Class<?>, Integer>) FieldUtils.readStaticField(lookup, true);
TYPE_MAP = (Map<Class<?>, Integer>) FieldUtils.readStaticField(lookup, true);
} catch (IllegalAccessException e) {
throw new FieldAccessException("Cannot access type map field.", e);
}
} else {
// If not, then we're probably dealing with the value map
valueMapField = lookup;
VALUE_MAP_FIELD = lookup;
}
}
try {
readWriteLockField = fuzzy.getFieldByType("readWriteLock", ReadWriteLock.class);
READ_WRITE_LOCK_FIELD = fuzzy.getFieldByType("readWriteLock", ReadWriteLock.class);
} catch (IllegalArgumentException e) {
// It's not a big deal
}
// Check for the entity field as well
if (MinecraftReflection.isUsingNetty()) {
entityField = fuzzy.getFieldByType("entity", MinecraftReflection.getEntityClass());
entityField.setAccessible(true);
ENTITY_FIELD = fuzzy.getFieldByType("entity", MinecraftReflection.getEntityClass());
ENTITY_FIELD.setAccessible(true);
}
initializeMethods(fuzzy);
}
@ -606,9 +593,9 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
// Load the get-method
try {
getKeyValueMethod = fuzzy.getMethodByParameters(
GET_KEY_VALUE_METHOD = fuzzy.getMethodByParameters(
"getWatchableObject", MinecraftReflection.getWatchableObjectClass(), new Class[] { int.class });
getKeyValueMethod.setAccessible(true);
GET_KEY_VALUE_METHOD.setAccessible(true);
} catch (IllegalArgumentException e) {
// Use the fallback method
@ -616,18 +603,18 @@ public class WrappedDataWatcher implements Iterable<WrappedWatchableObject> {
for (Method method : candidates) {
if (!method.getName().startsWith("watch")) {
createKeyValueMethod = method;
CREATE_KEY_VALUE_METHOD = method;
} else {
updateKeyValueMethod = method;
UPDATE_KEY_VALUE_METHOD = method;
}
}
// Did we succeed?
if (updateKeyValueMethod == null || createKeyValueMethod == null) {
if (UPDATE_KEY_VALUE_METHOD == null || CREATE_KEY_VALUE_METHOD == null) {
// Go by index instead
if (candidates.size() > 1) {
createKeyValueMethod = candidates.get(0);
updateKeyValueMethod = candidates.get(1);
CREATE_KEY_VALUE_METHOD = candidates.get(0);
UPDATE_KEY_VALUE_METHOD = candidates.get(1);
} else {
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) {
// Nope
updateKeyValueMethod = candidates.get(0);
createKeyValueMethod = candidates.get(1);
UPDATE_KEY_VALUE_METHOD = candidates.get(0);
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.");
try {
return (Entity) MinecraftReflection.getBukkitEntity(entityField.get(handle));
return (Entity) MinecraftReflection.getBukkitEntity(ENTITY_FIELD.get(handle));
} catch (Exception 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.");
try {
entityField.set(handle, BukkitUnwrapper.getInstance().unwrapItem(entity));
ENTITY_FIELD.set(handle, BukkitUnwrapper.getInstance().unwrapItem(entity));
} catch (Exception 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.
* @author Kristian
*/
public class WrappedGameProfile {
private GameProfile profile;
public class WrappedGameProfile extends AbstractWrapper {
// Profile from a handle
private WrappedGameProfile(Object profile) {
if (profile == null)
throw new IllegalArgumentException("Profile cannot be NULL.");
if (!(profile instanceof GameProfile))
throw new IllegalArgumentException(profile + " is not a GameProfile");
this.profile = (GameProfile) profile;
super(GameProfile.class);
setHandle(profile);
}
/**
@ -34,21 +29,13 @@ public class WrappedGameProfile {
public static WrappedGameProfile fromHandle(Object handle) {
return new WrappedGameProfile(handle);
}
/**
* Retrieve the underlying game profile.
* @return The profile.
*/
public Object getHandle() {
return profile;
}
/**
* Retrieve the UUID of the player.
* @return The UUID of the player, or NULL if not computed.
*/
public String getId() {
return profile.getId();
return getProfile().getId();
}
/**
@ -56,7 +43,11 @@ public class WrappedGameProfile {
* @return The player name.
*/
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.
*/
public boolean isComplete() {
return profile.isComplete();
return getProfile().isComplete();
}
@Override
public int hashCode() {
return profile.hashCode();
return getProfile().hashCode();
}
@Override
@ -97,7 +88,7 @@ public class WrappedGameProfile {
if (obj instanceof WrappedGameProfile) {
WrappedGameProfile other = (WrappedGameProfile) obj;
return profile.equals(other.profile);
return getProfile().equals(other.getProfile());
}
return false;
}

Datei anzeigen

@ -15,21 +15,18 @@ import com.google.common.base.Preconditions;
* Represents a wrapper for the internal IntHashMap in Minecraft.
* @author Kristian
*/
public class WrappedIntHashMap {
private static final Class<?> INT_HASH_MAP = MinecraftReflection.getIntHashMapClass();
public class WrappedIntHashMap extends AbstractWrapper {
private static Method PUT_METHOD;
private static Method GET_METHOD;
private static Method REMOVE_METHOD;
private Object handle;
/**
* Construct an IntHashMap wrapper around an instance.
* @param handle - the NMS instance.
*/
private WrappedIntHashMap(Object handle) {
this.handle = handle;
super(MinecraftReflection.getIntHashMapClass());
setHandle(handle);
}
/**
@ -38,7 +35,7 @@ public class WrappedIntHashMap {
*/
public static WrappedIntHashMap newMap() {
try {
return new WrappedIntHashMap(INT_HASH_MAP.newInstance());
return new WrappedIntHashMap(MinecraftReflection.getIntHashMapClass().newInstance());
} catch (Exception 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.
*/
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);
}
@ -138,7 +131,7 @@ public class WrappedIntHashMap {
private void initializePutMethod() {
if (PUT_METHOD == null) {
// Fairly straight forward
PUT_METHOD = FuzzyReflection.fromClass(INT_HASH_MAP).getMethod(
PUT_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getIntHashMapClass()).getMethod(
FuzzyMethodContract.newBuilder().
banModifier(Modifier.STATIC).
parameterCount(2).
@ -154,7 +147,7 @@ public class WrappedIntHashMap {
String expected = "hello";
// 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 })) {
// Initialize a value
@ -183,12 +176,4 @@ public class WrappedIntHashMap {
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
*/
public class WrappedWatchableObject {
public class WrappedWatchableObject extends AbstractWrapper {
// Whether or not the reflection machinery has been initialized
private static boolean hasInitialized;
@ -47,7 +46,6 @@ public class WrappedWatchableObject {
// The watchable object class type
private static Class<?> watchableObjectClass;
protected Object handle;
protected StructureModifier<Object> modifier;
// Type of the stored value
@ -58,6 +56,7 @@ public class WrappedWatchableObject {
* @param handle - the raw watchable object to wrap.
*/
public WrappedWatchableObject(Object handle) {
super(MinecraftReflection.getWatchableObjectClass());
load(handle);
}
@ -67,6 +66,8 @@ public class WrappedWatchableObject {
* @param value - non-null value of specific types.
*/
public WrappedWatchableObject(int index, Object value) {
super(MinecraftReflection.getWatchableObjectClass());
if (value == 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.
*/

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");
}
}