Wrap all serializable objects in data watchers
Dieser Commit ist enthalten in:
Ursprung
c13b8d4fc6
Commit
242b25eb1e
@ -124,7 +124,7 @@ public class BukkitConverters {
|
||||
* @author Kristian
|
||||
* @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
|
||||
public final Object getGeneric(Class<?> genericType, TType specific) {
|
||||
if (specific != null)
|
||||
|
110
modules/API/src/main/java/com/comphenix/protocol/wrappers/Vector3F.java
Normale Datei
110
modules/API/src/main/java/com/comphenix/protocol/wrappers/Vector3F.java
Normale Datei
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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) {
|
||||
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.
|
||||
*
|
||||
* @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) {
|
||||
Validate.notNull(object, "Watcher object cannot be null!");
|
||||
@ -344,8 +345,13 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
.build(), "get"));
|
||||
}
|
||||
|
||||
Object value = GETTER.invoke(handle, object.getHandle());
|
||||
return WrappedWatchableObject.getWrapped(value);
|
||||
try {
|
||||
Object value = GETTER.invoke(handle, object.getHandle());
|
||||
return WrappedWatchableObject.getWrapped(value);
|
||||
} catch (RuntimeException ex) {
|
||||
// Nothing exists at this index
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Object Setters
|
||||
@ -768,7 +774,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
* @return The serializer, or null if none exists
|
||||
*/
|
||||
public static Serializer fromHandle(Object handle) {
|
||||
Validate.notNull("Handle cannot be null!");
|
||||
Validate.notNull("handle cannot be null!");
|
||||
initialize();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
|
||||
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.google.common.base.Optional;
|
||||
|
||||
@ -158,7 +160,8 @@ public class WrappedWatchableObject extends AbstractWrapper {
|
||||
// ---- 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.
|
||||
* @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);
|
||||
} else if (MinecraftReflection.isChunkCoordinates(value)) {
|
||||
return new WrappedChunkCoordinate((Comparable) value);
|
||||
} else if (MinecraftReflection.isBlockPosition(value)) {
|
||||
} else if (is(MinecraftReflection.getIBlockDataClass(), value)) {
|
||||
return BukkitConverters.getWrappedBlockDataConverter().getSpecific(value);
|
||||
} else if (is (Vector3F.getMinecraftClass(), value)) {
|
||||
return Vector3F.getConverter().getSpecific(value);
|
||||
} else if (is(MinecraftReflection.getBlockPositionClass(), value)) {
|
||||
return BlockPosition.getConverter().getSpecific(value);
|
||||
} else if (MinecraftReflection.isChunkPosition(value)) {
|
||||
return ChunkPosition.getConverter().getSpecific(value);
|
||||
} else {
|
||||
return 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 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.
|
||||
* @return The raw NMS object.
|
||||
*/
|
||||
// Must be kept in sync with getWrapped!
|
||||
static Object getUnwrapped(Object wrapped) {
|
||||
if (wrapped instanceof Optional) {
|
||||
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);
|
||||
} else if (wrapped instanceof WrappedChunkCoordinate) {
|
||||
return ((WrappedChunkCoordinate) wrapped).getHandle();
|
||||
} else if (wrapped instanceof WrappedBlockData) {
|
||||
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) {
|
||||
return BlockPosition.getConverter().getGeneric(MinecraftReflection.getBlockPositionClass(), (BlockPosition) wrapped);
|
||||
} else if (wrapped instanceof ChunkPosition) {
|
||||
return ChunkPosition.getConverter().getGeneric(MinecraftReflection.getChunkPositionClass(), (ChunkPosition) wrapped);
|
||||
} else {
|
||||
return wrapped;
|
||||
} 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);
|
||||
} else if (wrapped instanceof WrappedChunkCoordinate) {
|
||||
return ((WrappedChunkCoordinate) wrapped).getHandle();
|
||||
}
|
||||
|
||||
return wrapped;
|
||||
}
|
||||
}
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren