Fix block positions in watchers and issues with components
Fixes #170
Dieser Commit ist enthalten in:
Ursprung
9b2c8826b1
Commit
513a83c4b0
@ -1,5 +1,8 @@
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||
@ -27,8 +30,7 @@ public class WrappedChatComponent extends AbstractWrapper {
|
||||
// Retrieve the correct methods
|
||||
SERIALIZE_COMPONENT = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("serialize", /* a */
|
||||
String.class, new Class<?>[] { COMPONENT }));
|
||||
DESERIALIZE_COMPONENT = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("deserialize", /* a */
|
||||
COMPONENT, new Class<?>[] { String.class }));
|
||||
DESERIALIZE_COMPONENT = findDeserialize(fuzzy);
|
||||
|
||||
// Get a component from a standard Minecraft message
|
||||
CONSTRUCT_COMPONENT = Accessors.getMethodAccessor(MinecraftReflection.getCraftChatMessage(), "fromString", String.class);
|
||||
@ -37,6 +39,23 @@ public class WrappedChatComponent extends AbstractWrapper {
|
||||
CONSTRUCT_TEXT_COMPONENT = Accessors.getConstructorAccessor(MinecraftReflection.getChatComponentTextClass(), String.class);
|
||||
}
|
||||
|
||||
private static MethodAccessor findDeserialize(FuzzyReflection fuzzy) {
|
||||
List<Method> methods = fuzzy.getMethodListByParameters(COMPONENT, new Class<?>[] { String.class });
|
||||
if (methods.isEmpty()) {
|
||||
throw new IllegalArgumentException("Unable to find deserialize method in " + fuzzy.getSource().getName());
|
||||
}
|
||||
|
||||
// Try to find b, we want leniency
|
||||
for (Method method : methods) {
|
||||
if (method.getName().equals("b")) {
|
||||
return Accessors.getMethodAccessor(method);
|
||||
}
|
||||
}
|
||||
|
||||
// Oh well
|
||||
return Accessors.getMethodAccessor(methods.get(0));
|
||||
}
|
||||
|
||||
private transient String cache;
|
||||
|
||||
private WrappedChatComponent(Object handle, String cache) {
|
||||
@ -134,4 +153,9 @@ public class WrappedChatComponent extends AbstractWrapper {
|
||||
public int hashCode() {
|
||||
return handle.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WrappedChatComponent[json=" + getJson() + "]";
|
||||
}
|
||||
}
|
@ -22,7 +22,6 @@ import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -647,11 +646,27 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
/**
|
||||
* Represents a DataWatcherRegistry containing the supported {@link Serializer}s in 1.9.
|
||||
*
|
||||
* <ul>
|
||||
* <li>Byte</li>
|
||||
* <li>Integer</li>
|
||||
* <li>Float</li>
|
||||
* <li>String</li>
|
||||
* <li>IChatBaseComponent</li>
|
||||
* <li>Optional<ItemStack></li>
|
||||
* <li>Optional<IBlockData></li>
|
||||
* <li>Boolean</li>
|
||||
* <li>Vector3f</li>
|
||||
* <li>BlockPosition</li>
|
||||
* <li>Optional<BlockPosition></li>
|
||||
* <li>EnumDirection</li>
|
||||
* <li>Optional<UUID></li>
|
||||
* </ul>
|
||||
*
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public static class Registry {
|
||||
private static boolean INITIALIZED = false;
|
||||
private static Map<Class<?>, Serializer> REGISTRY = new HashMap<>();
|
||||
private static List<Serializer> REGISTRY = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Gets the serializer associated with a given class. </br>
|
||||
@ -660,11 +675,53 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
* @param clazz Class to find serializer for
|
||||
* @return The serializer, or null if none exists
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the first serializer associated with a given class.
|
||||
*
|
||||
* <p><b>Note</b>: If {@link Serializer#isOptional() the serializer is optional},
|
||||
* values <i>must</i> be wrapped in an {@link Optional}.</p>
|
||||
*
|
||||
* <p>If there are multiple serializers for a given class (i.e. BlockPosition),
|
||||
* you should use {@link #get(Class, boolean)} for more precision.</p>
|
||||
*
|
||||
* @param clazz Class to find serializer for
|
||||
* @return The serializer, or null if none exists
|
||||
*/
|
||||
public static Serializer get(Class<?> clazz) {
|
||||
Validate.notNull("Class cannot be null!");
|
||||
initialize();
|
||||
|
||||
return REGISTRY.get(clazz);
|
||||
for (Serializer serializer : REGISTRY) {
|
||||
if (serializer.getType().equals(clazz)) {
|
||||
return serializer;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first serializer associated with a given class and optional state.
|
||||
*
|
||||
* <p><b>Note</b>: If the serializer is optional, values <i>must<i> be wrapped in an {@link Optional}
|
||||
*
|
||||
* @param clazz Class to find serializer for
|
||||
* @param optional Optional state
|
||||
* @return The serializer, or null if none exists
|
||||
*/
|
||||
public static Serializer get(Class<?> clazz, boolean optional) {
|
||||
Validate.notNull(clazz, "Class cannot be null!");
|
||||
initialize();
|
||||
|
||||
for (Serializer serializer : REGISTRY) {
|
||||
if (serializer.getType().equals(clazz)
|
||||
&& serializer.isOptional() == optional) {
|
||||
return serializer;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -676,7 +733,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
Validate.notNull("Handle cannot be null!");
|
||||
initialize();
|
||||
|
||||
for (Serializer serializer : REGISTRY.values()) {
|
||||
for (Serializer serializer : REGISTRY) {
|
||||
if (serializer.getHandle().equals(handle)) {
|
||||
return serializer;
|
||||
}
|
||||
@ -721,7 +778,7 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
||||
throw new IllegalStateException("Failed to read field " + candidate);
|
||||
}
|
||||
|
||||
REGISTRY.put(innerClass, new Serializer(innerClass, serializer, optional));
|
||||
REGISTRY.add(new Serializer(innerClass, serializer, optional));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ import net.minecraft.server.v1_9_R1.AttributeModifier;
|
||||
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.MobEffect;
|
||||
import net.minecraft.server.v1_9_R1.MobEffectList;
|
||||
import net.minecraft.server.v1_9_R1.PacketPlayOutUpdateAttributes;
|
||||
import net.minecraft.server.v1_9_R1.PacketPlayOutUpdateAttributes.AttributeSnapshot;
|
||||
|
||||
@ -43,6 +45,8 @@ import org.bukkit.Material;
|
||||
import org.bukkit.WorldType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@ -51,6 +55,7 @@ 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.injector.PacketConstructor;
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
@ -179,12 +184,10 @@ public class PacketContainerTest {
|
||||
WrappedChatComponent.fromChatMessage("hello world"));
|
||||
}
|
||||
|
||||
// TODO Find a packet with integer arrays
|
||||
|
||||
/*@Test
|
||||
@Test
|
||||
public void testGetIntegerArrays() {
|
||||
// Contains a byte array we will test
|
||||
PacketContainer mapChunkBulk = new PacketContainer(PacketType.Play.Server.MAP_CHUNK_BULK);
|
||||
PacketContainer mapChunkBulk = new PacketContainer(PacketType.Play.Server.WORLD_PARTICLES);
|
||||
StructureModifier<int[]> integers = mapChunkBulk.getIntegerArrays();
|
||||
int[] testArray = new int[] { 1, 2, 3 };
|
||||
|
||||
@ -195,7 +198,7 @@ public class PacketContainerTest {
|
||||
|
||||
integers.write(0, testArray);
|
||||
assertArrayEquals(testArray, integers.read(0));
|
||||
}*/
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetItemModifier() {
|
||||
@ -447,24 +450,30 @@ public class PacketContainerTest {
|
||||
assertEquals(material, read.getType());
|
||||
}
|
||||
|
||||
/*@Test
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void testPotionEffect() {
|
||||
PotionEffect effect = new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 20 * 60, 1);
|
||||
MobEffect mobEffect = new MobEffect(effect.getType().getId(), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(),
|
||||
MobEffect mobEffect = new MobEffect(MobEffectList.fromId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(),
|
||||
effect.hasParticles());
|
||||
int entityId = 42;
|
||||
|
||||
// The constructor we want to call
|
||||
PacketConstructor creator = PacketConstructor.DEFAULT.withPacket(
|
||||
PacketType.Play.Server.ENTITY_EFFECT, new Class<?>[] { int.class, MobEffect.class });
|
||||
PacketContainer packet = creator.createPacket(1, mobEffect);
|
||||
PacketContainer packet = creator.createPacket(entityId, mobEffect);
|
||||
|
||||
assertEquals(1, (int) packet.getIntegers().read(0));
|
||||
assertEquals(entityId, (int) packet.getIntegers().read(0));
|
||||
assertEquals(effect.getType().getId(), (byte) packet.getBytes().read(0));
|
||||
assertEquals(effect.getAmplifier(), (byte) packet.getBytes().read(1));
|
||||
assertEquals(effect.getDuration(), (int) packet.getIntegers().read(1));
|
||||
assertEquals(effect.hasParticles(), packet.getBytes().read(2) == (effect.hasParticles() ? 1 : 0));
|
||||
}*/
|
||||
|
||||
int e = 0;
|
||||
if (effect.isAmbient()) e |= 1;
|
||||
if (effect.hasParticles()) e |= 2;
|
||||
|
||||
assertEquals(e, (byte) packet.getBytes().read(2));
|
||||
}
|
||||
|
||||
private static final List<PacketType> BLACKLISTED = Util.asList(
|
||||
PacketType.Play.Client.CUSTOM_PAYLOAD, PacketType.Play.Server.CUSTOM_PAYLOAD,
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
@ -18,7 +19,9 @@ public class WrappedChatComponentTest {
|
||||
public void testText() {
|
||||
WrappedChatComponent test = WrappedChatComponent.fromText("Hello.");
|
||||
String json = test.getJson();
|
||||
|
||||
assertNotNull(json);
|
||||
|
||||
WrappedChatComponent clone = WrappedChatComponent.fromJson(json);
|
||||
assertEquals(json, clone.getJson());
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,17 @@
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertNull;
|
||||
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.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
@ -71,4 +78,14 @@ public class WrappedDataWatcherTest {
|
||||
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);
|
||||
Serializer optionalBlockPos = Registry.get(net.minecraft.server.v1_9_R1.BlockPosition.class, true);
|
||||
assertNotSame(blockPos, optionalBlockPos);
|
||||
|
||||
assertNull(Registry.get(ItemStack.class, false));
|
||||
assertNotNull(Registry.get(UUID.class, true));
|
||||
}
|
||||
}
|
In neuem Issue referenzieren
Einen Benutzer sperren