Archiviert
13
0

Wrap all serializable objects in data watchers

Dieser Commit ist enthalten in:
Dan Mulloy 2016-07-06 15:47:24 -04:00
Ursprung c13b8d4fc6
Commit 242b25eb1e
4 geänderte Dateien mit 237 neuen und 23 gelöschten Zeilen

Datei anzeigen

@ -124,7 +124,7 @@ public class BukkitConverters {
* @author Kristian * @author Kristian
* @param <T> - type that can be converted. * @param <T> - type that can be converted.
*/ */
private static abstract class IgnoreNullConverter<TType> implements EquivalentConverter<TType> { public static abstract class IgnoreNullConverter<TType> implements EquivalentConverter<TType> {
@Override @Override
public final Object getGeneric(Class<?> genericType, TType specific) { public final Object getGeneric(Class<?> genericType, TType specific) {
if (specific != null) if (specific != null)

Datei anzeigen

@ -0,0 +1,110 @@
/**
* (c) 2016 dmulloy2
*/
package com.comphenix.protocol.wrappers;
import java.lang.reflect.Constructor;
import com.comphenix.protocol.reflect.EquivalentConverter;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.BukkitConverters.IgnoreNullConverter;
/**
* @author dmulloy2
*/
public class Vector3F {
protected float x;
protected float y;
protected float z;
public Vector3F() {
this(0, 0, 0);
}
public Vector3F(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
public float getX() {
return x;
}
public Vector3F setX(float x) {
this.x = x;
return this;
}
public float getY() {
return y;
}
public Vector3F setY(float y) {
this.y = y;
return this;
}
public float getZ() {
return z;
}
public Vector3F setZ(float z) {
this.z = z;
return this;
}
public boolean equals(Object object) {
if (object instanceof Vector3F) {
Vector3F that = (Vector3F) object;
return this.x == that.x && this.y == that.y && this.z == that.z;
}
return false;
}
private static Constructor<?> constructor = null;
private static Class<?> clazz = MinecraftReflection.getMinecraftClass("Vector3f");
public static Class<?> getMinecraftClass() {
return clazz;
}
public static EquivalentConverter<Vector3F> getConverter() {
return new IgnoreNullConverter<Vector3F>() {
@Override
public Class<Vector3F> getSpecificType() {
return Vector3F.class;
}
@Override
protected Object getGenericValue(Class<?> genericType, Vector3F specific) {
if (constructor == null) {
try {
constructor = clazz.getConstructor(float.class, float.class, float.class);
} catch (ReflectiveOperationException ex) {
throw new RuntimeException("Failed to find constructor for Vector3f", ex);
}
}
try {
return constructor.newInstance(specific.x, specific.y, specific.z);
} catch (ReflectiveOperationException ex) {
throw new RuntimeException("Failed to create new instance of Vector3f", ex);
}
}
@Override
protected Vector3F getSpecificValue(Object generic) {
StructureModifier<Float> modifier = new StructureModifier<Float>(generic.getClass())
.withTarget(generic).withType(float.class);
float x = modifier.read(0);
float y = modifier.read(1);
float z = modifier.read(2);
return new Vector3F(x, y, z);
}
};
}
}

Datei anzeigen

@ -25,6 +25,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -234,7 +235,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
* @return True if it does, false if not * @return True if it does, false if not
*/ */
public boolean hasIndex(int index) { public boolean hasIndex(int index) {
return getMap().containsKey(index); return getObject(index) != null;
} }
/** /**
@ -321,7 +322,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
* Retrieve a watchable object by index. * Retrieve a watchable object by index.
* *
* @param index Index of the object to retrieve. * @param index Index of the object to retrieve.
* @return The watched object. * @return The watched object or null if it doesn't exist.
*/ */
public Object getObject(int index) { public Object getObject(int index) {
return getObject(new WrappedDataWatcherObject(index, null)); return getObject(new WrappedDataWatcherObject(index, null));
@ -331,7 +332,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
* Retrieve a watchable object by watcher object. * Retrieve a watchable object by watcher object.
* *
* @param object The watcher object * @param object The watcher object
* @return The watched object * @return The watched object or null if it doesn't exist.
*/ */
public Object getObject(WrappedDataWatcherObject object) { public Object getObject(WrappedDataWatcherObject object) {
Validate.notNull(object, "Watcher object cannot be null!"); Validate.notNull(object, "Watcher object cannot be null!");
@ -344,8 +345,13 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
.build(), "get")); .build(), "get"));
} }
try {
Object value = GETTER.invoke(handle, object.getHandle()); Object value = GETTER.invoke(handle, object.getHandle());
return WrappedWatchableObject.getWrapped(value); return WrappedWatchableObject.getWrapped(value);
} catch (RuntimeException ex) {
// Nothing exists at this index
return null;
}
} }
// ---- Object Setters // ---- Object Setters
@ -768,7 +774,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
* @return The serializer, or null if none exists * @return The serializer, or null if none exists
*/ */
public static Serializer fromHandle(Object handle) { public static Serializer fromHandle(Object handle) {
Validate.notNull("Handle cannot be null!"); Validate.notNull("handle cannot be null!");
initialize(); initialize();
for (Serializer serializer : REGISTRY) { for (Serializer serializer : REGISTRY) {
@ -820,5 +826,67 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
} }
} }
} }
// ---- Helper methods
/**
* Gets the serializer for IChatBaseComponents
* @return The serializer
*/
public static Serializer getChatComponentSerializer() {
return get(MinecraftReflection.getIChatBaseComponentClass());
}
/**
* Gets the serializer for ItemStacks
* @param optional If true, objects <b>must</b> be wrapped in an {@link Optional}
* @return The serializer
*/
public static Serializer getItemStackSerializer(boolean optional) {
return get(MinecraftReflection.getItemStackClass(), optional);
}
/**
* Gets the serializer for BlockData
* @param optional If true, objects <b>must</b> be wrapped in an {@link Optional}
* @return The serializer
*/
public static Serializer getBlockDataSerializer(boolean optional) {
return get(MinecraftReflection.getIBlockDataClass(), optional);
}
/**
* Gets the serializer for Vector3Fs
* @return The serializer
*/
public static Serializer getVectorSerializer() {
return get(Vector3F.getMinecraftClass());
}
/**
* Gets the serializer for BlockPositions
* @param optional If true, objects <b>must</b> be wrapped in an {@link Optional}
* @return The serializer
*/
public static Serializer getBlockPositionSerializer(boolean optional) {
return get(MinecraftReflection.getBlockPositionClass(), optional);
}
/**
* Gets the serializer for Directions
* @return The serializer
*/
public static Serializer getDirectionSerializer() {
return get(EnumWrappers.getDirectionClass());
}
/**
* Gets the serializer for UUIDs
* @param optional If true, objects <b>must</b> be wrapped in an {@link Optional}
* @return The serializer
*/
public static Serializer getUUIDSerializer(boolean optional) {
return get(UUID.class, optional);
}
} }
} }

Datei anzeigen

@ -22,6 +22,8 @@ import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.reflect.accessors.Accessors; import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor; import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.EnumWrappers.Direction;
import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer;
import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject; import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject;
import com.google.common.base.Optional; import com.google.common.base.Optional;
@ -158,7 +160,8 @@ public class WrappedWatchableObject extends AbstractWrapper {
// ---- Wrapping // ---- Wrapping
/** /**
* Retrieve the wrapped object value, if needed. * Retrieve the wrapped object value, if needed. All non-primitive objects
* with {@link Serializer}s should be covered by this.
* *
* @param value - the raw NMS object to wrap. * @param value - the raw NMS object to wrap.
* @return The wrapped object. * @return The wrapped object.
@ -175,17 +178,37 @@ public class WrappedWatchableObject extends AbstractWrapper {
} }
} }
if (MinecraftReflection.isItemStack(value)) { // Current supported classes
if (is(MinecraftReflection.getIChatBaseComponentClass(), value)) {
return WrappedChatComponent.fromHandle(value);
} else if (is(MinecraftReflection.getItemStackClass(), value)) {
return BukkitConverters.getItemStackConverter().getSpecific(value); return BukkitConverters.getItemStackConverter().getSpecific(value);
} else if (MinecraftReflection.isChunkCoordinates(value)) { } else if (is(MinecraftReflection.getIBlockDataClass(), value)) {
return new WrappedChunkCoordinate((Comparable) value); return BukkitConverters.getWrappedBlockDataConverter().getSpecific(value);
} else if (MinecraftReflection.isBlockPosition(value)) { } else if (is (Vector3F.getMinecraftClass(), value)) {
return Vector3F.getConverter().getSpecific(value);
} else if (is(MinecraftReflection.getBlockPositionClass(), value)) {
return BlockPosition.getConverter().getSpecific(value); return BlockPosition.getConverter().getSpecific(value);
} else if (MinecraftReflection.isChunkPosition(value)) { } else if (is(EnumWrappers.getDirectionClass(), value)) {
return EnumWrappers.getDirectionConverter().getSpecific(value);
}
// Legacy classes
if (is(MinecraftReflection.getChunkCoordinatesClass(), value)) {
return new WrappedChunkCoordinate((Comparable) value);
} else if (is(MinecraftReflection.getChunkPositionClass(), value)) {
return ChunkPosition.getConverter().getSpecific(value); return ChunkPosition.getConverter().getSpecific(value);
} else { }
return value; return value;
} }
private static boolean is(Class<?> clazz, Object object) {
if (clazz == null || object == null) {
return false;
}
return clazz.isAssignableFrom(object.getClass());
} }
/** /**
@ -194,6 +217,7 @@ public class WrappedWatchableObject extends AbstractWrapper {
* @param wrapped - the wrapped position. * @param wrapped - the wrapped position.
* @return The raw NMS object. * @return The raw NMS object.
*/ */
// Must be kept in sync with getWrapped!
static Object getUnwrapped(Object wrapped) { static Object getUnwrapped(Object wrapped) {
if (wrapped instanceof Optional) { if (wrapped instanceof Optional) {
Optional<?> optional = (Optional<?>) wrapped; Optional<?> optional = (Optional<?>) wrapped;
@ -204,16 +228,28 @@ public class WrappedWatchableObject extends AbstractWrapper {
} }
} }
if (wrapped instanceof ItemStack) { // Current supported classes
if (wrapped instanceof WrappedChatComponent) {
return ((WrappedChatComponent) wrapped).getHandle();
} else if (wrapped instanceof ItemStack) {
return BukkitConverters.getItemStackConverter().getGeneric(MinecraftReflection.getItemStackClass(), (ItemStack) wrapped); return BukkitConverters.getItemStackConverter().getGeneric(MinecraftReflection.getItemStackClass(), (ItemStack) wrapped);
} else if (wrapped instanceof WrappedChunkCoordinate) { } else if (wrapped instanceof WrappedBlockData) {
return ((WrappedChunkCoordinate) wrapped).getHandle(); return BukkitConverters.getWrappedBlockDataConverter().getGeneric(MinecraftReflection.getIBlockDataClass(), (WrappedBlockData) wrapped);
} else if (wrapped instanceof Vector3F) {
return Vector3F.getConverter().getGeneric(Vector3F.getMinecraftClass(), (Vector3F) wrapped);
} else if (wrapped instanceof BlockPosition) { } else if (wrapped instanceof BlockPosition) {
return BlockPosition.getConverter().getGeneric(MinecraftReflection.getBlockPositionClass(), (BlockPosition) wrapped); return BlockPosition.getConverter().getGeneric(MinecraftReflection.getBlockPositionClass(), (BlockPosition) wrapped);
} else if (wrapped instanceof ChunkPosition) { } else if (wrapped instanceof Direction) {
return EnumWrappers.getDirectionConverter().getGeneric(EnumWrappers.getDirectionClass(), (Direction) wrapped);
}
// Legacy classes
if (wrapped instanceof ChunkPosition) {
return ChunkPosition.getConverter().getGeneric(MinecraftReflection.getChunkPositionClass(), (ChunkPosition) wrapped); return ChunkPosition.getConverter().getGeneric(MinecraftReflection.getChunkPositionClass(), (ChunkPosition) wrapped);
} else { } else if (wrapped instanceof WrappedChunkCoordinate) {
return ((WrappedChunkCoordinate) wrapped).getHandle();
}
return wrapped; return wrapped;
} }
}
} }