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
|
* @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)
|
||||||
|
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.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren