Add wrapper for MinecraftKey, more work on data watchers
Dieser Commit ist enthalten in:
Ursprung
5efc4ffee3
Commit
ec8fa0d1fe
@ -216,7 +216,9 @@ class EntityUtilities {
|
||||
throw new FieldAccessException("Cannot access 'trackedEntities' field due to security limitations.", e);
|
||||
}
|
||||
|
||||
return WrappedIntHashMap.fromHandle(trackedEntities).get(entityID);
|
||||
Object trackerEntry = WrappedIntHashMap.fromHandle(trackedEntities).get(entityID);
|
||||
Class<?> entryClass = MinecraftReflection.getEntityTrackerClass();
|
||||
return entryClass.cast(trackerEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,6 +31,7 @@ import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldType;
|
||||
import org.bukkit.entity.Entity;
|
||||
@ -963,6 +964,43 @@ public class BukkitConverters {
|
||||
};
|
||||
}
|
||||
|
||||
private static MethodAccessor soundGetter = null;
|
||||
private static FieldAccessor soundKey = null;
|
||||
|
||||
public static EquivalentConverter<Sound> getSoundConverter() {
|
||||
return new IgnoreNullConverter<Sound>() {
|
||||
|
||||
@Override
|
||||
public Class<Sound> getSpecificType() {
|
||||
return Sound.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getGenericValue(Class<?> genericType, Sound specific) {
|
||||
if (soundGetter == null) {
|
||||
Class<?> soundEffects = MinecraftReflection.getMinecraftClass("SoundEffects");
|
||||
FuzzyReflection fuzzy = FuzzyReflection.fromClass(soundEffects, true);
|
||||
soundGetter = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("getSound", MinecraftReflection.getMinecraftClass("SoundEffect"), String.class));
|
||||
}
|
||||
|
||||
MinecraftKey key = MinecraftKey.fromEnum(specific);
|
||||
return soundGetter.invoke(null, key.getFullKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sound getSpecificValue(Object generic) {
|
||||
if (soundKey == null) {
|
||||
Class<?> soundEffect = generic.getClass();
|
||||
FuzzyReflection fuzzy = FuzzyReflection.fromClass(soundEffect, true);
|
||||
soundKey = Accessors.getFieldAccessor(fuzzy.getFieldByType("key", MinecraftReflection.getMinecraftClass("MinecraftKey")));
|
||||
}
|
||||
|
||||
MinecraftKey key = MinecraftKey.fromHandle(soundKey.get(generic));
|
||||
return Sound.valueOf(key.getEnumFormat());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a given equivalent converter in NULL checks, ensuring that such values are ignored.
|
||||
* @param <TType> Type
|
||||
|
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class MinecraftKey {
|
||||
private final String prefix;
|
||||
private final String key;
|
||||
|
||||
public MinecraftKey(String prefix, String key) {
|
||||
this.prefix = prefix;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public MinecraftKey(String key) {
|
||||
this("minecraft", key);
|
||||
}
|
||||
|
||||
public static MinecraftKey fromHandle(Object handle) {
|
||||
StructureModifier<String> modifier = new StructureModifier<String>(handle.getClass()).withTarget(handle).withType(String.class);
|
||||
return new MinecraftKey(modifier.read(0), modifier.read(1));
|
||||
}
|
||||
|
||||
public static MinecraftKey fromEnum(Enum<?> value) {
|
||||
return new MinecraftKey(value.name().toLowerCase().replace("_", "."));
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getFullKey() {
|
||||
return prefix + ":" + key;
|
||||
}
|
||||
|
||||
public String getEnumFormat() {
|
||||
return key.toUpperCase().replace(".", "_");
|
||||
}
|
||||
}
|
@ -52,9 +52,9 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
private static MethodAccessor GETTER = null;
|
||||
private static MethodAccessor SETTER = null;
|
||||
|
||||
private static FieldAccessor ENTITY_FIELD = null;
|
||||
private static FieldAccessor MAP_FIELD = null;
|
||||
private static Field ENTITY_DATA_FIELD = null;
|
||||
private static Field ENTITY_FIELD = null;
|
||||
|
||||
private static ConstructorAccessor constructor = null;
|
||||
private static ConstructorAccessor lightningConstructor = null;
|
||||
@ -77,7 +77,14 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
*/
|
||||
public WrappedDataWatcher() {
|
||||
this(newHandle(fakeEntity()));
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new DataWatcher using a real entity.
|
||||
* @param entity The entity
|
||||
*/
|
||||
public WrappedDataWatcher(Entity entity) {
|
||||
this(newHandle(BukkitUnwrapper.getInstance().unwrapItem(entity)));
|
||||
}
|
||||
|
||||
private static Object newHandle(Object entity) {
|
||||
@ -160,10 +167,6 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
return getMap().size();
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
getMap().clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the watchable object at a given index.
|
||||
* @param index Index
|
||||
@ -313,8 +316,13 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
* @return A cloned data watcher.
|
||||
*/
|
||||
public WrappedDataWatcher deepClone() {
|
||||
// TODO This
|
||||
return null;
|
||||
WrappedDataWatcher clone = new WrappedDataWatcher(getEntity());
|
||||
|
||||
for (Entry<Integer, WrappedWatchableObject> entry : asMap().entrySet()) {
|
||||
clone.setObject(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -354,6 +362,10 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
if (!MinecraftReflection.isUsingNetty())
|
||||
throw new IllegalStateException("This method is only supported on 1.7.2 and above.");
|
||||
|
||||
if (ENTITY_FIELD == null) {
|
||||
ENTITY_FIELD = Accessors.getFieldAccessor(HANDLE_TYPE, MinecraftReflection.getEntityClass(), true);
|
||||
}
|
||||
|
||||
try {
|
||||
return (Entity) MinecraftReflection.getBukkitEntity(ENTITY_FIELD.get(handle));
|
||||
} catch (Exception e) {
|
||||
@ -372,6 +384,10 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
if (!MinecraftReflection.isUsingNetty())
|
||||
throw new IllegalStateException("This method is only supported on 1.7.2 and above.");
|
||||
|
||||
if (ENTITY_FIELD == null) {
|
||||
ENTITY_FIELD = Accessors.getFieldAccessor(HANDLE_TYPE, MinecraftReflection.getEntityClass(), true);
|
||||
}
|
||||
|
||||
try {
|
||||
ENTITY_FIELD.set(handle, BukkitUnwrapper.getInstance().unwrapItem(entity));
|
||||
} catch (Exception e) {
|
||||
|
@ -19,6 +19,8 @@ package com.comphenix.protocol.wrappers;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
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.WrappedDataWatcher.WrappedDataWatcherObject;
|
||||
|
||||
@ -28,6 +30,9 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObje
|
||||
*/
|
||||
|
||||
public class WrappedWatchableObject extends AbstractWrapper {
|
||||
private static final Class<?> HANDLE_TYPE = MinecraftReflection.getDataWatcherItemClass();
|
||||
private static ConstructorAccessor constructor;
|
||||
|
||||
private final StructureModifier<Object> modifier;
|
||||
|
||||
/**
|
||||
@ -35,12 +40,28 @@ public class WrappedWatchableObject extends AbstractWrapper {
|
||||
* @param handle Data watcher item
|
||||
*/
|
||||
public WrappedWatchableObject(Object handle) {
|
||||
super(MinecraftReflection.getDataWatcherItemClass());
|
||||
|
||||
super(HANDLE_TYPE);
|
||||
setHandle(handle);
|
||||
this.modifier = new StructureModifier<Object>(handleType).withTarget(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a wrapped watchable object with a given watcher object and initial value.
|
||||
* @param watcherObject Watcher object
|
||||
* @param value Initial value
|
||||
*/
|
||||
public WrappedWatchableObject(WrappedDataWatcherObject watcherObject, Object value) {
|
||||
this(newHandle(watcherObject, value));
|
||||
}
|
||||
|
||||
private static Object newHandle(WrappedDataWatcherObject watcherObject, Object value) {
|
||||
if (constructor == null) {
|
||||
constructor = Accessors.getConstructorAccessor(HANDLE_TYPE.getConstructors()[0]);
|
||||
}
|
||||
|
||||
return constructor.invoke(watcherObject.getHandle(), value);
|
||||
}
|
||||
|
||||
// ---- Getter methods
|
||||
|
||||
/**
|
||||
|
@ -20,9 +20,12 @@ import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import net.minecraft.server.v1_9_R1.AttributeModifier;
|
||||
@ -47,10 +50,12 @@ import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.utility.Util;
|
||||
import com.comphenix.protocol.wrappers.BlockPosition;
|
||||
import com.comphenix.protocol.wrappers.BukkitConverters;
|
||||
import com.comphenix.protocol.wrappers.WrappedBlockData;
|
||||
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
||||
@ -66,8 +71,8 @@ import com.google.common.collect.Lists;
|
||||
//@PrepareForTest(CraftItemFactory.class)
|
||||
public class PacketContainerTest {
|
||||
// Helper converters
|
||||
// private EquivalentConverter<WrappedDataWatcher> watchConvert = BukkitConverters.getDataWatcherConverter();
|
||||
// private EquivalentConverter<ItemStack> itemConvert = BukkitConverters.getItemStackConverter();
|
||||
private EquivalentConverter<WrappedDataWatcher> watchConvert = BukkitConverters.getDataWatcherConverter();
|
||||
private EquivalentConverter<ItemStack> itemConvert = BukkitConverters.getItemStackConverter();
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeBukkit() throws IllegalAccessException {
|
||||
@ -458,14 +463,11 @@ public class PacketContainerTest {
|
||||
assertEquals(effect.hasParticles(), packet.getBytes().read(2) == (effect.hasParticles() ? 1 : 0));
|
||||
}*/
|
||||
|
||||
// This is usually the last one, since it requires all the API stuff to be worked out
|
||||
|
||||
/*private static final List<PacketType> BLACKLISTED = Util.asList(
|
||||
PacketType.Play.Client.CUSTOM_PAYLOAD, PacketType.Play.Server.CUSTOM_PAYLOAD, PacketType.Play.Server.MAP_CHUNK,
|
||||
PacketType.Play.Server.UPDATE_ATTRIBUTES
|
||||
private static final List<PacketType> BLACKLISTED = Util.asList(
|
||||
PacketType.Play.Client.CUSTOM_PAYLOAD, PacketType.Play.Server.CUSTOM_PAYLOAD,
|
||||
PacketType.Play.Server.SET_COOLDOWN, PacketType.Play.Server.NAMED_SOUND_EFFECT
|
||||
);
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeepClone() {
|
||||
// Try constructing all the packets
|
||||
@ -518,7 +520,7 @@ public class PacketContainerTest {
|
||||
throw new RuntimeException("Failed to serialize packet " + type, e);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPacketType() {
|
||||
@ -526,7 +528,7 @@ public class PacketContainerTest {
|
||||
}
|
||||
|
||||
// Convert to objects that support equals()
|
||||
/*private void testEquality(Object a, Object b) {
|
||||
private void testEquality(Object a, Object b) {
|
||||
if (a != null && b != null) {
|
||||
if (MinecraftReflection.isDataWatcher(a)) {
|
||||
a = watchConvert.getSpecific(a);
|
||||
@ -542,20 +544,20 @@ public class PacketContainerTest {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (a.equals(b) || Objects.equal(a, b) || a.toString().equals(b.toString())) {
|
||||
if (a.equals(b) || Objects.equals(a, b) || a.toString().equals(b.toString())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(a, b);
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying array as an object array.
|
||||
* @param val - array wrapped as an Object.
|
||||
* @return An object array.
|
||||
*/
|
||||
/*private Object[] getArray(Object val) {
|
||||
private Object[] getArray(Object val) {
|
||||
if (val instanceof Object[])
|
||||
return (Object[]) val;
|
||||
if (val == null)
|
||||
@ -567,5 +569,5 @@ public class PacketContainerTest {
|
||||
for (int i = 0; i < arrlength; ++i)
|
||||
outputArray[i] = Array.get(val, i);
|
||||
return outputArray;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren