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;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
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.FieldAccessor;
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.utility.MinecraftReflection;
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)));
}
/**
* 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) {
if (constructor == null) {
constructor = Accessors.getConstructorAccessor(HANDLE_TYPE, MinecraftReflection.getEntityClass());
@ -127,16 +141,10 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
private Map<Integer, Object> getMap() {
if (MAP_FIELD == null) {
FuzzyReflection fuzzy = FuzzyReflection.fromClass(handleType, true);
List<Field> candidates = fuzzy.getFieldListByType(Map.class);
for (Field candidate : candidates) {
if (Modifier.isStatic(candidate.getModifiers())) {
// 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);
}
}
MAP_FIELD = Accessors.getFieldAccessor(fuzzy.getField(FuzzyFieldContract.newBuilder()
.banModifier(Modifier.STATIC)
.typeDerivedOf(Map.class)
.build()));
}
if (MAP_FIELD == null) {
@ -329,7 +337,11 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
Validate.notNull(object, "Watcher object cannot be 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());
@ -392,18 +404,13 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
if (SETTER == null || REGISTER == null) {
FuzzyReflection fuzzy = FuzzyReflection.fromClass(handleType, true);
List<Method> methods = fuzzy.getMethodList(FuzzyMethodContract.newBuilder()
FuzzyMethodContract contract = FuzzyMethodContract.newBuilder()
.banModifier(Modifier.STATIC)
.requireModifier(Modifier.PUBLIC)
.parameterExactArray(object.getHandleType(), Object.class)
.build());
for (Method method : methods) {
if (method.getName().equals("set")) {
SETTER = Accessors.getMethodAccessor(method);
} else if (method.getName().equals("register")) {
REGISTER = Accessors.getMethodAccessor(method);
}
}
.build();
SETTER = Accessors.getMethodAccessor(fuzzy.getMethod(contract, "set"));
REGISTER = Accessors.getMethodAccessor(fuzzy.getMethod(contract, "register"));
}
if (hasIndex(object.getIndex())) {
@ -613,6 +620,19 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
public String toString() {
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
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj == null)
return false;
if (obj == this) return true;
if (obj == null) return false;
if (obj instanceof WrappedWatchableObject) {
// watcher object, value, dirty state
WrappedWatchableObject other = (WrappedWatchableObject) obj;
return other.handle.equals(handle);
return getWatcherObject().equals(other.getWatcherObject())
&& getRawValue().equals(other.getRawValue())
&& getDirtyState() == other.getDirtyState();
}
return false;

View File

@ -355,15 +355,19 @@ public class PacketContainerTest {
assertNull(watchableAccessor.read(0));
Entity entity = new EntityLightning(null, 0, 0, 0, true);
DataWatcher watcher = entity.getDataWatcher();
WrappedDataWatcher watcher = new WrappedDataWatcher();
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 = wrapper.getWatchableObjects();
List<WrappedWatchableObject> list = watcher.getWatchableObjects();
// Insert and read back
watchableAccessor.write(0, list);
assertEquals(list, watchableAccessor.read(0));
// Put it into a new data watcher
WrappedDataWatcher newWatcher = new WrappedDataWatcher(watchableAccessor.read(0));
assertEquals(newWatcher.getWatchableObjects(), list);
}
@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;
@ -11,11 +24,11 @@ import static org.junit.Assert.assertTrue;
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.ItemStack;
import org.bukkit.craftbukkit.v1_9_R1.entity.CraftLightningStrike;
import org.bukkit.entity.Entity;
import org.junit.BeforeClass;
import org.junit.Test;
@ -37,7 +50,11 @@ public class WrappedDataWatcherTest {
@Test
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);
WrappedDataWatcherObject object = watchable.getWatcherObject();
@ -45,13 +62,13 @@ public class WrappedDataWatcherTest {
assertEquals(object.getSerializer(), Registry.get(Byte.class));
// Make sure we can set existing objects
wrapper.setObject(0, (byte) 1);
assertTrue(wrapper.getByte(0) == 1);
wrapper.setObject(0, (byte) 21);
assertTrue(wrapper.getByte(0) == 21);
}
@Test
public void testStrings() {
WrappedDataWatcher wrapper = create();
WrappedDataWatcher wrapper = new WrappedDataWatcher();
// Make sure we can create watcher objects
Serializer serializer = Registry.get(String.class);
@ -63,22 +80,16 @@ public class WrappedDataWatcherTest {
@Test
public void testFloats() {
WrappedDataWatcher wrapper = create();
WrappedDataWatcher wrapper = new WrappedDataWatcher();
// Make sure we can add new entries
Serializer serializer = Registry.get(Float.class);
WrappedDataWatcherObject object = new WrappedDataWatcherObject(10, serializer);
wrapper.setObject(object, 1.0F);
wrapper.setObject(object, 21.0F);
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
public void testSerializers() {
Serializer blockPos = Registry.get(net.minecraft.server.v1_9_R1.BlockPosition.class, false);