Add back a missing data watcher constructor

Also bolstered some of the unit tests
Fixes #191
This commit is contained in:
Dan Mulloy 2016-04-16 21:24:58 -04:00
parent 87c56d0248
commit e542f3c9d3
4 changed files with 81 additions and 45 deletions

View File

@ -17,7 +17,6 @@
package com.comphenix.protocol.wrappers; package com.comphenix.protocol.wrappers;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -39,6 +38,7 @@ 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.reflect.accessors.FieldAccessor; import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.reflect.accessors.MethodAccessor; import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.collection.ConvertedMap; import com.comphenix.protocol.wrappers.collection.ConvertedMap;
@ -99,6 +99,20 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
this(newHandle(BukkitUnwrapper.getInstance().unwrapItem(entity))); this(newHandle(BukkitUnwrapper.getInstance().unwrapItem(entity)));
} }
/**
* Constructs a new DataWatcher using a fake lightning entity and a given
* list of watchable objects.
*
* @param objects The list of objects
*/
public WrappedDataWatcher(List<WrappedWatchableObject> objects) {
this();
for (WrappedWatchableObject object : objects) {
setObject(object.getWatcherObject(), object);
}
}
private static Object newHandle(Object entity) { private static Object newHandle(Object entity) {
if (constructor == null) { if (constructor == null) {
constructor = Accessors.getConstructorAccessor(HANDLE_TYPE, MinecraftReflection.getEntityClass()); constructor = Accessors.getConstructorAccessor(HANDLE_TYPE, MinecraftReflection.getEntityClass());
@ -127,16 +141,10 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
private Map<Integer, Object> getMap() { private Map<Integer, Object> getMap() {
if (MAP_FIELD == null) { if (MAP_FIELD == null) {
FuzzyReflection fuzzy = FuzzyReflection.fromClass(handleType, true); FuzzyReflection fuzzy = FuzzyReflection.fromClass(handleType, true);
List<Field> candidates = fuzzy.getFieldListByType(Map.class); MAP_FIELD = Accessors.getFieldAccessor(fuzzy.getField(FuzzyFieldContract.newBuilder()
.banModifier(Modifier.STATIC)
for (Field candidate : candidates) { .typeDerivedOf(Map.class)
if (Modifier.isStatic(candidate.getModifiers())) { .build()));
// This is the entity class to current index map, which we really don't have a use for
} else {
// This is the map we're looking for
MAP_FIELD = Accessors.getFieldAccessor(candidate);
}
}
} }
if (MAP_FIELD == null) { if (MAP_FIELD == null) {
@ -329,7 +337,11 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
Validate.notNull(object, "Watcher object cannot be null!"); Validate.notNull(object, "Watcher object cannot be null!");
if (GETTER == null) { if (GETTER == null) {
GETTER = Accessors.getMethodAccessor(handleType, "get", object.getHandleType()); FuzzyReflection fuzzy = FuzzyReflection.fromClass(handleType);
GETTER = Accessors.getMethodAccessor(fuzzy.getMethod(FuzzyMethodContract.newBuilder()
.parameterExactType(object.getHandleType())
.returnTypeExact(Object.class)
.build(), "get"));
} }
Object value = GETTER.invoke(handle, object.getHandle()); Object value = GETTER.invoke(handle, object.getHandle());
@ -392,18 +404,13 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
if (SETTER == null || REGISTER == null) { if (SETTER == null || REGISTER == null) {
FuzzyReflection fuzzy = FuzzyReflection.fromClass(handleType, true); FuzzyReflection fuzzy = FuzzyReflection.fromClass(handleType, true);
List<Method> methods = fuzzy.getMethodList(FuzzyMethodContract.newBuilder() FuzzyMethodContract contract = FuzzyMethodContract.newBuilder()
.banModifier(Modifier.STATIC) .banModifier(Modifier.STATIC)
.requireModifier(Modifier.PUBLIC) .requireModifier(Modifier.PUBLIC)
.parameterExactArray(object.getHandleType(), Object.class) .parameterExactArray(object.getHandleType(), Object.class)
.build()); .build();
for (Method method : methods) { SETTER = Accessors.getMethodAccessor(fuzzy.getMethod(contract, "set"));
if (method.getName().equals("set")) { REGISTER = Accessors.getMethodAccessor(fuzzy.getMethod(contract, "register"));
SETTER = Accessors.getMethodAccessor(method);
} else if (method.getName().equals("register")) {
REGISTER = Accessors.getMethodAccessor(method);
}
}
} }
if (hasIndex(object.getIndex())) { if (hasIndex(object.getIndex())) {
@ -613,6 +620,19 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
public String toString() { public String toString() {
return "DataWatcherObject[index=" + getIndex() + ", serializer=" + getSerializer() + "]"; return "DataWatcherObject[index=" + getIndex() + ", serializer=" + getSerializer() + "]";
} }
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null) return false;
if (obj instanceof WrappedDataWatcherObject) {
WrappedDataWatcherObject other = (WrappedDataWatcherObject) obj;
return handle.equals(other.handle);
}
return false;
}
} }
/** /**

View File

@ -211,14 +211,15 @@ public class WrappedWatchableObject extends AbstractWrapper {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == this) if (obj == this) return true;
return true; if (obj == null) return false;
if (obj == null)
return false;
if (obj instanceof WrappedWatchableObject) { if (obj instanceof WrappedWatchableObject) {
// watcher object, value, dirty state
WrappedWatchableObject other = (WrappedWatchableObject) obj; WrappedWatchableObject other = (WrappedWatchableObject) obj;
return other.handle.equals(handle); return getWatcherObject().equals(other.getWatcherObject())
&& getRawValue().equals(other.getRawValue())
&& getDirtyState() == other.getDirtyState();
} }
return false; return false;

View File

@ -355,15 +355,19 @@ public class PacketContainerTest {
assertNull(watchableAccessor.read(0)); assertNull(watchableAccessor.read(0));
Entity entity = new EntityLightning(null, 0, 0, 0, true); WrappedDataWatcher watcher = new WrappedDataWatcher();
DataWatcher watcher = entity.getDataWatcher(); watcher.setObject(0, Registry.get(String.class), "Test");
watcher.setObject(1, Registry.get(Byte.class), (byte) 21);
WrappedDataWatcher wrapper = new WrappedDataWatcher(watcher); List<WrappedWatchableObject> list = watcher.getWatchableObjects();
List<WrappedWatchableObject> list = wrapper.getWatchableObjects();
// Insert and read back // Insert and read back
watchableAccessor.write(0, list); watchableAccessor.write(0, list);
assertEquals(list, watchableAccessor.read(0)); assertEquals(list, watchableAccessor.read(0));
// Put it into a new data watcher
WrappedDataWatcher newWatcher = new WrappedDataWatcher(watchableAccessor.read(0));
assertEquals(newWatcher.getWatchableObjects(), list);
} }
@Test @Test

View File

@ -1,5 +1,18 @@
/** /**
* (c) 2016 dmulloy2 * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2016 dmulloy2
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/ */
package com.comphenix.protocol.wrappers; package com.comphenix.protocol.wrappers;
@ -11,11 +24,11 @@ import static org.junit.Assert.assertTrue;
import java.util.UUID; import java.util.UUID;
import net.minecraft.server.v1_9_R1.DataWatcher;
import net.minecraft.server.v1_9_R1.Entity;
import net.minecraft.server.v1_9_R1.EntityLightning; import net.minecraft.server.v1_9_R1.EntityLightning;
import net.minecraft.server.v1_9_R1.ItemStack; import net.minecraft.server.v1_9_R1.ItemStack;
import org.bukkit.craftbukkit.v1_9_R1.entity.CraftLightningStrike;
import org.bukkit.entity.Entity;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@ -37,7 +50,11 @@ public class WrappedDataWatcherTest {
@Test @Test
public void testBytes() { public void testBytes() {
WrappedDataWatcher wrapper = create(); // Create a fake lightning strike and get its watcher
EntityLightning lightning = new EntityLightning(null, 0, 0, 0, true);
Entity entity = new CraftLightningStrike(null, lightning);
WrappedDataWatcher wrapper = WrappedDataWatcher.getEntityWatcher(entity);
WrappedWatchableObject watchable = wrapper.getWatchableObject(0); WrappedWatchableObject watchable = wrapper.getWatchableObject(0);
WrappedDataWatcherObject object = watchable.getWatcherObject(); WrappedDataWatcherObject object = watchable.getWatcherObject();
@ -45,13 +62,13 @@ public class WrappedDataWatcherTest {
assertEquals(object.getSerializer(), Registry.get(Byte.class)); assertEquals(object.getSerializer(), Registry.get(Byte.class));
// Make sure we can set existing objects // Make sure we can set existing objects
wrapper.setObject(0, (byte) 1); wrapper.setObject(0, (byte) 21);
assertTrue(wrapper.getByte(0) == 1); assertTrue(wrapper.getByte(0) == 21);
} }
@Test @Test
public void testStrings() { public void testStrings() {
WrappedDataWatcher wrapper = create(); WrappedDataWatcher wrapper = new WrappedDataWatcher();
// Make sure we can create watcher objects // Make sure we can create watcher objects
Serializer serializer = Registry.get(String.class); Serializer serializer = Registry.get(String.class);
@ -63,22 +80,16 @@ public class WrappedDataWatcherTest {
@Test @Test
public void testFloats() { public void testFloats() {
WrappedDataWatcher wrapper = create(); WrappedDataWatcher wrapper = new WrappedDataWatcher();
// Make sure we can add new entries // Make sure we can add new entries
Serializer serializer = Registry.get(Float.class); Serializer serializer = Registry.get(Float.class);
WrappedDataWatcherObject object = new WrappedDataWatcherObject(10, serializer); WrappedDataWatcherObject object = new WrappedDataWatcherObject(10, serializer);
wrapper.setObject(object, 1.0F); wrapper.setObject(object, 21.0F);
assertTrue(wrapper.hasIndex(10)); assertTrue(wrapper.hasIndex(10));
} }
private WrappedDataWatcher create() {
Entity entity = new EntityLightning(null, 0, 0, 0, true);
DataWatcher handle = entity.getDataWatcher();
return new WrappedDataWatcher(handle);
}
@Test @Test
public void testSerializers() { public void testSerializers() {
Serializer blockPos = Registry.get(net.minecraft.server.v1_9_R1.BlockPosition.class, false); Serializer blockPos = Registry.get(net.minecraft.server.v1_9_R1.BlockPosition.class, false);