Fix an issue with cloning metadata packets
Also improved some documentation and tests
Dieser Commit ist enthalten in:
Ursprung
a39a37ec51
Commit
11ba322b5f
@ -24,6 +24,7 @@ import com.comphenix.protocol.utility.MinecraftReflection;
|
|||||||
import com.comphenix.protocol.wrappers.BlockPosition;
|
import com.comphenix.protocol.wrappers.BlockPosition;
|
||||||
import com.comphenix.protocol.wrappers.BukkitConverters;
|
import com.comphenix.protocol.wrappers.BukkitConverters;
|
||||||
import com.comphenix.protocol.wrappers.ChunkPosition;
|
import com.comphenix.protocol.wrappers.ChunkPosition;
|
||||||
|
import com.comphenix.protocol.wrappers.MinecraftKey;
|
||||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
||||||
import com.comphenix.protocol.wrappers.WrappedServerPing;
|
import com.comphenix.protocol.wrappers.WrappedServerPing;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
@ -55,6 +56,11 @@ public class BukkitCloner implements Cloner {
|
|||||||
if (MinecraftReflection.isUsingNetty()) {
|
if (MinecraftReflection.isUsingNetty()) {
|
||||||
addClass(4, MinecraftReflection.getServerPingClass());
|
addClass(4, MinecraftReflection.getServerPingClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MinecraftReflection.dataWatcherItemExists()) {
|
||||||
|
addClass(5, MinecraftReflection.getDataWatcherSerializerClass());
|
||||||
|
addClass(6, MinecraftReflection.getMinecraftKeyClass());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addClass(int id, Class<?> clazz) {
|
private void addClass(int id, Class<?> clazz) {
|
||||||
@ -102,6 +108,11 @@ public class BukkitCloner implements Cloner {
|
|||||||
case 4:
|
case 4:
|
||||||
EquivalentConverter<WrappedServerPing> serverConverter = BukkitConverters.getWrappedServerPingConverter();
|
EquivalentConverter<WrappedServerPing> serverConverter = BukkitConverters.getWrappedServerPingConverter();
|
||||||
return serverConverter.getGeneric(clonableClasses.get(4), serverConverter.getSpecific(source).deepClone());
|
return serverConverter.getGeneric(clonableClasses.get(4), serverConverter.getSpecific(source).deepClone());
|
||||||
|
case 5:
|
||||||
|
return source;
|
||||||
|
case 6:
|
||||||
|
EquivalentConverter<MinecraftKey> keyConverter = MinecraftKey.getConverter();
|
||||||
|
return keyConverter.getGeneric(clonableClasses.get(5), keyConverter.getSpecific(source));
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Cannot clone objects of type " + source.getClass());
|
throw new IllegalArgumentException("Cannot clone objects of type " + source.getClass());
|
||||||
}
|
}
|
||||||
|
@ -2077,4 +2077,8 @@ public class MinecraftReflection {
|
|||||||
throw new RuntimeException("Cannot construct packet serializer.", e);
|
throw new RuntimeException("Cannot construct packet serializer.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Class<?> getMinecraftKeyClass() {
|
||||||
|
return getMinecraftClass("MinecraftKey");
|
||||||
|
}
|
||||||
}
|
}
|
@ -16,7 +16,11 @@
|
|||||||
*/
|
*/
|
||||||
package com.comphenix.protocol.wrappers;
|
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.reflect.StructureModifier;
|
||||||
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dmulloy2
|
* @author dmulloy2
|
||||||
@ -59,4 +63,37 @@ public class MinecraftKey {
|
|||||||
public String getEnumFormat() {
|
public String getEnumFormat() {
|
||||||
return key.toUpperCase().replace(".", "_");
|
return key.toUpperCase().replace(".", "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Constructor<?> constructor = null;
|
||||||
|
|
||||||
|
public static EquivalentConverter<MinecraftKey> getConverter() {
|
||||||
|
return new EquivalentConverter<MinecraftKey>() {
|
||||||
|
@Override
|
||||||
|
public MinecraftKey getSpecific(Object generic) {
|
||||||
|
return MinecraftKey.fromHandle(generic);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getGeneric(Class<?> genericType, MinecraftKey specific) {
|
||||||
|
if (constructor == null) {
|
||||||
|
try {
|
||||||
|
constructor = MinecraftReflection.getMinecraftKeyClass().getConstructor(String.class, String.class);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new RuntimeException("Failed to obtain MinecraftKey constructor", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return constructor.newInstance(specific.getPrefix(), specific.getKey());
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new RuntimeException("Failed to create new MinecraftKey", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<MinecraftKey> getSpecificType() {
|
||||||
|
return MinecraftKey.class;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
@ -47,6 +47,7 @@ import com.google.common.base.Optional;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a DataWatcher in 1.9
|
* Represents a DataWatcher in 1.9
|
||||||
|
*
|
||||||
* @author dmulloy2
|
* @author dmulloy2
|
||||||
*/
|
*/
|
||||||
public class WrappedDataWatcher extends AbstractWrapper implements Iterable<WrappedWatchableObject> {
|
public class WrappedDataWatcher extends AbstractWrapper implements Iterable<WrappedWatchableObject> {
|
||||||
@ -173,6 +174,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the watchable object at a given index.
|
* Gets the watchable object at a given index.
|
||||||
|
*
|
||||||
* @param index Index
|
* @param index Index
|
||||||
* @return The watchable object, or null if none exists
|
* @return The watchable object, or null if none exists
|
||||||
*/
|
*/
|
||||||
@ -187,6 +189,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not this DataWatcher has an object at a given index.
|
* Whether or not this DataWatcher has an object at a given index.
|
||||||
|
*
|
||||||
* @param index Index
|
* @param index Index
|
||||||
* @return True if it does, false if not
|
* @return True if it does, false if not
|
||||||
*/
|
*/
|
||||||
@ -196,111 +199,126 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
// ---- Object Getters
|
// ---- Object Getters
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a watched byte.
|
* Get a watched byte.
|
||||||
* @param index - index of the watched byte.
|
*
|
||||||
* @return The watched byte, or NULL if this value doesn't exist.
|
* @param index - index of the watched byte.
|
||||||
* @throws FieldAccessException Cannot read underlying field.
|
* @return The watched byte, or NULL if this value doesn't exist.
|
||||||
*/
|
* @throws FieldAccessException Cannot read underlying field.
|
||||||
public Byte getByte(int index) throws FieldAccessException {
|
*/
|
||||||
return (Byte) getObject(index);
|
public Byte getByte(int index) throws FieldAccessException {
|
||||||
}
|
return (Byte) getObject(index);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a watched short.
|
|
||||||
* @param index - index of the watched short.
|
|
||||||
* @return The watched short, or NULL if this value doesn't exist.
|
|
||||||
* @throws FieldAccessException Cannot read underlying field.
|
|
||||||
*/
|
|
||||||
public Short getShort(int index) throws FieldAccessException {
|
|
||||||
return (Short) getObject(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a watched integer.
|
|
||||||
* @param index - index of the watched integer.
|
|
||||||
* @return The watched integer, or NULL if this value doesn't exist.
|
|
||||||
* @throws FieldAccessException Cannot read underlying field.
|
|
||||||
*/
|
|
||||||
public Integer getInteger(int index) throws FieldAccessException {
|
|
||||||
return (Integer) getObject(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a watched float.
|
|
||||||
* @param index - index of the watched float.
|
|
||||||
* @return The watched float, or NULL if this value doesn't exist.
|
|
||||||
* @throws FieldAccessException Cannot read underlying field.
|
|
||||||
*/
|
|
||||||
public Float getFloat(int index) throws FieldAccessException {
|
|
||||||
return (Float) getObject(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a watched string.
|
|
||||||
* @param index - index of the watched string.
|
|
||||||
* @return The watched string, or NULL if this value doesn't exist.
|
|
||||||
* @throws FieldAccessException Cannot read underlying field.
|
|
||||||
*/
|
|
||||||
public String getString(int index) throws FieldAccessException {
|
|
||||||
return (String) getObject(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a watched string.
|
|
||||||
* @param index - index of the watched string.
|
|
||||||
* @return The watched string, or NULL if this value doesn't exist.
|
|
||||||
* @throws FieldAccessException Cannot read underlying field.
|
|
||||||
*/
|
|
||||||
public ItemStack getItemStack(int index) throws FieldAccessException {
|
|
||||||
return (ItemStack) getObject(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a watched string.
|
|
||||||
* @param index - index of the watched string.
|
|
||||||
* @return The watched string, or NULL if this value doesn't exist.
|
|
||||||
* @throws FieldAccessException Cannot read underlying field.
|
|
||||||
*/
|
|
||||||
public WrappedChunkCoordinate getChunkCoordinate(int index) throws FieldAccessException {
|
|
||||||
return (WrappedChunkCoordinate) getObject(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a watchable object by index.
|
|
||||||
* @param index - index of the object to retrieve.
|
|
||||||
* @return The watched object.
|
|
||||||
* @throws FieldAccessException Cannot read underlying field.
|
|
||||||
*/
|
|
||||||
public Object getObject(int index) throws FieldAccessException {
|
|
||||||
return WrappedWatchableObject.getWrapped(getWatchedObject(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object getWatchedObject(int index) {
|
|
||||||
return getWatcherObject(new WrappedDataWatcherObject(index, null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getWatcherObject(WrappedDataWatcherObject watcherObject) {
|
/**
|
||||||
|
* Get a watched short.
|
||||||
|
*
|
||||||
|
* @param index - index of the watched short.
|
||||||
|
* @return The watched short, or NULL if this value doesn't exist.
|
||||||
|
* @throws FieldAccessException Cannot read underlying field.
|
||||||
|
*/
|
||||||
|
public Short getShort(int index) throws FieldAccessException {
|
||||||
|
return (Short) getObject(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a watched integer.
|
||||||
|
*
|
||||||
|
* @param index - index of the watched integer.
|
||||||
|
* @return The watched integer, or NULL if this value doesn't exist.
|
||||||
|
* @throws FieldAccessException Cannot read underlying field.
|
||||||
|
*/
|
||||||
|
public Integer getInteger(int index) throws FieldAccessException {
|
||||||
|
return (Integer) getObject(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a watched float.
|
||||||
|
*
|
||||||
|
* @param index - index of the watched float.
|
||||||
|
* @return The watched float, or NULL if this value doesn't exist.
|
||||||
|
* @throws FieldAccessException Cannot read underlying field.
|
||||||
|
*/
|
||||||
|
public Float getFloat(int index) throws FieldAccessException {
|
||||||
|
return (Float) getObject(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a watched string.
|
||||||
|
*
|
||||||
|
* @param index - index of the watched string.
|
||||||
|
* @return The watched string, or NULL if this value doesn't exist.
|
||||||
|
* @throws FieldAccessException Cannot read underlying field.
|
||||||
|
*/
|
||||||
|
public String getString(int index) throws FieldAccessException {
|
||||||
|
return (String) getObject(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a watched string.
|
||||||
|
*
|
||||||
|
* @param index - index of the watched string.
|
||||||
|
* @return The watched string, or NULL if this value doesn't exist.
|
||||||
|
* @throws FieldAccessException Cannot read underlying field.
|
||||||
|
*/
|
||||||
|
public ItemStack getItemStack(int index) throws FieldAccessException {
|
||||||
|
return (ItemStack) getObject(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a watched string.
|
||||||
|
*
|
||||||
|
* @param index - index of the watched string.
|
||||||
|
* @return The watched string, or NULL if this value doesn't exist.
|
||||||
|
* @throws FieldAccessException Cannot read underlying field.
|
||||||
|
*/
|
||||||
|
public WrappedChunkCoordinate getChunkCoordinate(int index) throws FieldAccessException {
|
||||||
|
return (WrappedChunkCoordinate) getObject(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a watchable object by index.
|
||||||
|
*
|
||||||
|
* @param index - index of the object to retrieve.
|
||||||
|
* @return The watched object.
|
||||||
|
* @throws FieldAccessException Cannot read underlying field.
|
||||||
|
*/
|
||||||
|
public Object getObject(int index) throws FieldAccessException {
|
||||||
|
return getObject(new WrappedDataWatcherObject(index, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a watchable object by watcher object.
|
||||||
|
*
|
||||||
|
* @param object The watcher object
|
||||||
|
* @return The watched object
|
||||||
|
*/
|
||||||
|
public Object getObject(WrappedDataWatcherObject object) {
|
||||||
|
Validate.notNull(object, "Watcher object cannot be null!");
|
||||||
|
|
||||||
if (GETTER == null) {
|
if (GETTER == null) {
|
||||||
GETTER = Accessors.getMethodAccessor(handleType, "get", watcherObject.getHandleType());
|
GETTER = Accessors.getMethodAccessor(handleType, "get", object.getHandleType());
|
||||||
}
|
}
|
||||||
|
|
||||||
return GETTER.invoke(handle, watcherObject.getHandle());
|
Object value = GETTER.invoke(handle, object.getHandle());
|
||||||
}
|
return WrappedWatchableObject.getWrapped(value);
|
||||||
|
}
|
||||||
|
|
||||||
// ---- Object Setters
|
// ---- Object Setters
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the DataWatcher Item at a given index to a new value.
|
* Sets the DataWatcher Item at a given index to a new value.
|
||||||
* @param index Index
|
*
|
||||||
* @param value New value
|
* @param index Index
|
||||||
*/
|
* @param value New value
|
||||||
|
*/
|
||||||
public void setObject(int index, Object value) {
|
public void setObject(int index, Object value) {
|
||||||
setObject(new WrappedDataWatcherObject(index, null), value);
|
setObject(new WrappedDataWatcherObject(index, null), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the DataWatcher Item associated with a given watcher object to a new value.
|
* Sets the DataWatcher Item associated with a given watcher object to a new value.
|
||||||
|
*
|
||||||
* @param object Associated watcher object
|
* @param object Associated watcher object
|
||||||
* @param value New value
|
* @param value New value
|
||||||
*/
|
*/
|
||||||
@ -319,8 +337,6 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
SETTER = Accessors.getMethodAccessor(method);
|
SETTER = Accessors.getMethodAccessor(method);
|
||||||
} else if (method.getName().equals("register")) {
|
} else if (method.getName().equals("register")) {
|
||||||
REGISTER = Accessors.getMethodAccessor(method);
|
REGISTER = Accessors.getMethodAccessor(method);
|
||||||
} else {
|
|
||||||
System.out.println(method);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,6 +439,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* No longer supported in 1.9 due to the removal of a consistent type <-> ID map.
|
* No longer supported in 1.9 due to the removal of a consistent type <-> ID map.
|
||||||
|
*
|
||||||
* @param clazz
|
* @param clazz
|
||||||
* @return Null
|
* @return Null
|
||||||
*/
|
*/
|
||||||
@ -433,6 +450,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* No longer supported in 1.9 due to the removal of a consistent type <-> ID map.
|
* No longer supported in 1.9 due to the removal of a consistent type <-> ID map.
|
||||||
|
*
|
||||||
* @param typeID
|
* @param typeID
|
||||||
* @return Null
|
* @return Null
|
||||||
*/
|
*/
|
||||||
@ -473,6 +491,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a DataWatcherObject in 1.9.
|
* Represents a DataWatcherObject in 1.9.
|
||||||
|
*
|
||||||
* @author dmulloy2
|
* @author dmulloy2
|
||||||
*/
|
*/
|
||||||
public static class WrappedDataWatcherObject extends AbstractWrapper {
|
public static class WrappedDataWatcherObject extends AbstractWrapper {
|
||||||
@ -484,6 +503,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new watcher object from a NMS handle
|
* Creates a new watcher object from a NMS handle
|
||||||
|
*
|
||||||
* @param handle NMS handle
|
* @param handle NMS handle
|
||||||
*/
|
*/
|
||||||
public WrappedDataWatcherObject(Object handle) {
|
public WrappedDataWatcherObject(Object handle) {
|
||||||
@ -495,6 +515,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new watcher object from an index and serializer
|
* Creates a new watcher object from an index and serializer
|
||||||
|
*
|
||||||
* @param index Index
|
* @param index Index
|
||||||
* @param serializer Serializer, see {@link Registry}
|
* @param serializer Serializer, see {@link Registry}
|
||||||
*/
|
*/
|
||||||
@ -512,17 +533,23 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets this watcher object's index
|
* Gets this watcher object's index.
|
||||||
|
*
|
||||||
* @return The index
|
* @return The index
|
||||||
*/
|
*/
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return (int) modifier.read(0);
|
return (int) modifier.read(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets this watcher object's serializer.
|
||||||
|
*
|
||||||
|
* @return The serializer
|
||||||
|
*/
|
||||||
public Serializer getSerializer() {
|
public Serializer getSerializer() {
|
||||||
if (getSerializer == null) {
|
if (getSerializer == null) {
|
||||||
getSerializer = Accessors.getMethodAccessor(FuzzyReflection.fromClass(HANDLE_TYPE, true).getMethodByParameters(
|
getSerializer = Accessors.getMethodAccessor(FuzzyReflection.fromClass(HANDLE_TYPE, true)
|
||||||
"getSerializer", MinecraftReflection.getDataWatcherSerializerClass(), new Class[0]));
|
.getMethodByParameters("getSerializer", MinecraftReflection.getDataWatcherSerializerClass(), new Class[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Object serializer = getSerializer.invoke(handle);
|
Object serializer = getSerializer.invoke(handle);
|
||||||
@ -534,10 +561,16 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
return new Serializer(null, serializer, false);
|
return new Serializer(null, serializer, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "DataWatcherObject[index=" + getIndex() + ", serializer=" + getSerializer() + "]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a DataWatcherSerializer in 1.9.
|
* Represents a DataWatcherSerializer in 1.9.
|
||||||
|
*
|
||||||
* @author dmulloy2
|
* @author dmulloy2
|
||||||
*/
|
*/
|
||||||
public static class Serializer extends AbstractWrapper {
|
public static class Serializer extends AbstractWrapper {
|
||||||
@ -548,6 +581,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new Serializer
|
* Constructs a new Serializer
|
||||||
|
*
|
||||||
* @param type Type it serializes
|
* @param type Type it serializes
|
||||||
* @param handle NMS handle
|
* @param handle NMS handle
|
||||||
* @param optional Whether or not it's {@link Optional}
|
* @param optional Whether or not it's {@link Optional}
|
||||||
@ -562,6 +596,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the type this serializer serializes.
|
* Gets the type this serializer serializes.
|
||||||
|
*
|
||||||
* @return The type
|
* @return The type
|
||||||
*/
|
*/
|
||||||
public Class<?> getType() {
|
public Class<?> getType() {
|
||||||
@ -569,8 +604,8 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not this serializer is optional, that is whether or not
|
* Whether or not this serializer is optional, that is whether or not the return type is wrapped in a {@link Optional}.
|
||||||
* the return type is wrapped in a {@link Optional}.
|
*
|
||||||
* @return True if it is, false if not
|
* @return True if it is, false if not
|
||||||
*/
|
*/
|
||||||
public boolean isOptional() {
|
public boolean isOptional() {
|
||||||
@ -585,6 +620,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a DataWatcherRegistry containing the supported {@link Serializer}s in 1.9.
|
* Represents a DataWatcherRegistry containing the supported {@link Serializer}s in 1.9.
|
||||||
|
*
|
||||||
* @author dmulloy2
|
* @author dmulloy2
|
||||||
*/
|
*/
|
||||||
public static class Registry {
|
public static class Registry {
|
||||||
@ -603,6 +639,11 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
return REGISTRY.get(clazz);
|
return REGISTRY.get(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the serializer associated with a given NMS handle.
|
||||||
|
* @param handle The NMS handle
|
||||||
|
* @return The serializer, or null if none exists
|
||||||
|
*/
|
||||||
public static Serializer fromHandle(Object handle) {
|
public static Serializer fromHandle(Object handle) {
|
||||||
initialize();
|
initialize();
|
||||||
|
|
||||||
@ -623,7 +664,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Field> candidates = FuzzyReflection.fromClass(MinecraftReflection.getMinecraftClass("DataWatcherRegistry"), true)
|
List<Field> candidates = FuzzyReflection.fromClass(MinecraftReflection.getMinecraftClass("DataWatcherRegistry"), true)
|
||||||
.getFieldListByType(MinecraftReflection.getDataWatcherSerializerClass());
|
.getFieldListByType(MinecraftReflection.getDataWatcherSerializerClass());
|
||||||
for (Field candidate : candidates) {
|
for (Field candidate : candidates) {
|
||||||
Type generic = candidate.getGenericType();
|
Type generic = candidate.getGenericType();
|
||||||
if (generic instanceof ParameterizedType) {
|
if (generic instanceof ParameterizedType) {
|
||||||
|
@ -223,4 +223,9 @@ public class WrappedWatchableObject extends AbstractWrapper {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "DataWatcherItem[object=" + getWatcherObject() + ", value=" + getValue() + ", dirty=" + getDirtyState() + "]";
|
||||||
|
}
|
||||||
}
|
}
|
@ -36,6 +36,7 @@ import net.minecraft.server.v1_9_R1.PacketPlayOutUpdateAttributes;
|
|||||||
import net.minecraft.server.v1_9_R1.PacketPlayOutUpdateAttributes.AttributeSnapshot;
|
import net.minecraft.server.v1_9_R1.PacketPlayOutUpdateAttributes.AttributeSnapshot;
|
||||||
|
|
||||||
import org.apache.commons.lang.SerializationUtils;
|
import org.apache.commons.lang.SerializationUtils;
|
||||||
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.DyeColor;
|
import org.bukkit.DyeColor;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@ -59,6 +60,8 @@ import com.comphenix.protocol.wrappers.BukkitConverters;
|
|||||||
import com.comphenix.protocol.wrappers.WrappedBlockData;
|
import com.comphenix.protocol.wrappers.WrappedBlockData;
|
||||||
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
||||||
|
import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry;
|
||||||
|
import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject;
|
||||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||||
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
|
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
||||||
@ -465,7 +468,7 @@ public class PacketContainerTest {
|
|||||||
|
|
||||||
private static final List<PacketType> BLACKLISTED = Util.asList(
|
private static final List<PacketType> BLACKLISTED = Util.asList(
|
||||||
PacketType.Play.Client.CUSTOM_PAYLOAD, PacketType.Play.Server.CUSTOM_PAYLOAD,
|
PacketType.Play.Client.CUSTOM_PAYLOAD, PacketType.Play.Server.CUSTOM_PAYLOAD,
|
||||||
PacketType.Play.Server.SET_COOLDOWN, PacketType.Play.Server.NAMED_SOUND_EFFECT
|
PacketType.Play.Server.SET_COOLDOWN
|
||||||
);
|
);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -489,6 +492,15 @@ public class PacketContainerTest {
|
|||||||
// Initialize default values
|
// Initialize default values
|
||||||
constructed.getModifier().writeDefaults();
|
constructed.getModifier().writeDefaults();
|
||||||
|
|
||||||
|
// Make sure watchable collections can be cloned
|
||||||
|
if (type == PacketType.Play.Server.ENTITY_METADATA) {
|
||||||
|
constructed.getWatchableCollectionModifier().write(0, Util.asList(
|
||||||
|
new WrappedWatchableObject(new WrappedDataWatcherObject(0, Registry.get(Byte.class)), (byte) 1),
|
||||||
|
new WrappedWatchableObject(new WrappedDataWatcherObject(0, Registry.get(String.class)), "String"),
|
||||||
|
new WrappedWatchableObject(new WrappedDataWatcherObject(0, Registry.get(Float.class)), 1.0F)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// Clone the packet
|
// Clone the packet
|
||||||
PacketContainer cloned = constructed.deepClone();
|
PacketContainer cloned = constructed.deepClone();
|
||||||
|
|
||||||
@ -549,6 +561,10 @@ public class PacketContainerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (EqualsBuilder.reflectionEquals(a, b)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assertEquals(a, b);
|
assertEquals(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren