Add support for entity equipment pair in 1.16

This commit is contained in:
Dan Mulloy 2020-07-05 13:29:52 -04:00
parent a7e702899a
commit f19bfc613e
6 changed files with 124 additions and 6 deletions

View File

@ -920,7 +920,7 @@ public class PacketContainer implements Serializable {
}
/**
* Retrive a read/write structure for dimension IDs in 1.13.1+
* Retrieve a read/write structure for dimension IDs in 1.13.1+
* @return A modifier for dimension IDs
*/
public StructureModifier<Integer> getDimensions() {
@ -930,6 +930,17 @@ public class PacketContainer implements Serializable {
);
}
/**
* Retrieve a read/write structure for ItemSlot/ItemStack pair lists in 1.16+
* @return The Structure Modifier
*/
public StructureModifier<List<Pair<ItemSlot, ItemStack>>> getSlotStackPairLists() {
return getLists(BukkitConverters.getPairConverter(
EnumWrappers.getItemSlotConverter(),
BukkitConverters.getItemStackConverter()
));
}
/**
* Retrieve a read/write structure for the Map class.
* @param keyConverter Converter for map keys

View File

@ -316,6 +316,36 @@ public class BukkitConverters {
});
}
@SuppressWarnings("rawtypes")
public static <A, B> EquivalentConverter<Pair<A, B>> getPairConverter(final EquivalentConverter<A> firstConverter,
final EquivalentConverter<B> secondConverter) {
return ignoreNull(new EquivalentConverter<Pair<A, B>>() {
@Override
public Object getGeneric(Pair<A, B> specific) {
Object first = firstConverter.getGeneric(specific.getFirst());
Object second = secondConverter.getGeneric(specific.getSecond());
return new com.mojang.datafixers.util.Pair(first, second);
}
@Override
public Pair<A, B> getSpecific(Object generic) {
com.mojang.datafixers.util.Pair mjPair = (com.mojang.datafixers.util.Pair) generic;
A first = firstConverter.getSpecific(mjPair.getFirst());
B second = secondConverter.getSpecific(mjPair.getSecond());
return new Pair(first, second);
}
@Override
public Class<Pair<A, B>> getSpecificType() {
Class<?> dummy = Pair.class;
return (Class<Pair<A, B>>) dummy;
}
});
}
/**
* @deprecated While this solution is not as abhorrent as I had imagined, I still highly recommend switching to the
* new conversion API.

View File

@ -1,9 +1,7 @@
package com.comphenix.protocol.wrappers;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import com.comphenix.protocol.PacketType;
@ -434,6 +432,7 @@ public abstract class EnumWrappers {
private static boolean INITIALIZED = false;
private static Map<Class<?>, EquivalentConverter<?>> FROM_NATIVE = Maps.newHashMap();
private static Map<Class<?>, EquivalentConverter<?>> FROM_WRAPPER = Maps.newHashMap();
static Set<String> INVALID = new HashSet<>();
/**
* Initialize the wrappers, if we haven't already.
@ -469,7 +468,14 @@ public abstract class EnumWrappers {
SCOREBOARD_ACTION_CLASS = getEnum(PacketType.Play.Server.SCOREBOARD_SCORE.getPacketClass(), 0);
PARTICLE_CLASS = getEnum(PacketType.Play.Server.WORLD_PARTICLES.getPacketClass(), 0);
SOUND_CATEGORY_CLASS = getEnum(PacketType.Play.Server.CUSTOM_SOUND_EFFECT.getPacketClass(), 0);
ITEM_SLOT_CLASS = getEnum(PacketType.Play.Server.ENTITY_EQUIPMENT.getPacketClass(), 0);
try {
// TODO enum names are more stable than their packet associations
ITEM_SLOT_CLASS = MinecraftReflection.getMinecraftClass("EnumItemSlot");
} catch (Exception ex) {
ITEM_SLOT_CLASS = getEnum(PacketType.Play.Server.ENTITY_EQUIPMENT.getPacketClass(), 0);
}
HAND_CLASS = getEnum(PacketType.Play.Client.USE_ENTITY.getPacketClass(), 1);
DIRECTION_CLASS = getEnum(PacketType.Play.Server.SPAWN_ENTITY_PAINTING.getPacketClass(), 0);
CHAT_TYPE_CLASS = getEnum(PacketType.Play.Server.CHAT.getPacketClass(), 0);
@ -496,7 +502,7 @@ public abstract class EnumWrappers {
associate(DIRECTION_CLASS, Direction.class, getDirectionConverter());
associate(CHAT_TYPE_CLASS, ChatType.class, getChatTypeConverter());
if(ENTITY_POSE_CLASS != null) {
if (ENTITY_POSE_CLASS != null) {
associate(ENTITY_POSE_CLASS, EntityPose.class, getEntityPoseConverter());
}
@ -507,6 +513,8 @@ public abstract class EnumWrappers {
if (nativeClass != null) {
FROM_NATIVE.put(nativeClass, converter);
FROM_WRAPPER.put(wrapperClass, converter);
} else {
INVALID.add(wrapperClass.getSimpleName());
}
}

View File

@ -0,0 +1,43 @@
package com.comphenix.protocol.wrappers;
import java.util.Objects;
public class Pair<A, B> {
private A first;
private B second;
public Pair(A first, B second) {
this.first = first;
this.second = second;
}
public A getFirst() {
return first;
}
public B getSecond() {
return second;
}
public void setFirst(A first) {
this.first = first;
}
public void setSecond(B second) {
this.second = second;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair<?, ?> pair = (Pair<?, ?>) o;
return Objects.equals(first, pair.first) &&
Objects.equals(second, pair.second);
}
@Override
public int hashCode() {
return Objects.hash(first, second);
}
}

View File

@ -507,6 +507,20 @@ public class PacketContainerTest {
assertEquals((Object) 1, container.getDimensions().read(0));
}
@Test
public void testEntityEquipment() {
PacketContainer container = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT);
List<Pair<EnumWrappers.ItemSlot, ItemStack>> data = new ArrayList<>();
data.add(new Pair<>(EnumWrappers.ItemSlot.CHEST, new ItemStack(Material.NETHERITE_CHESTPLATE)));
data.add(new Pair<>(EnumWrappers.ItemSlot.LEGS, new ItemStack(Material.GOLDEN_LEGGINGS)));
container.getSlotStackPairLists().write(0, data);
List<Pair<EnumWrappers.ItemSlot, ItemStack>> written = container.getSlotStackPairLists().read(0);
assertEquals(data, written);
}
/**
* Actions from the outbound Boss packet. Used for testing generic enums.
* @author dmulloy2

View File

@ -2,6 +2,7 @@ package com.comphenix.protocol.wrappers;
import static org.junit.Assert.assertEquals;
import com.google.common.collect.Sets;
import net.minecraft.server.v1_16_R1.EnumChatVisibility;
import net.minecraft.server.v1_16_R1.EnumDifficulty;
import net.minecraft.server.v1_16_R1.EnumGamemode;
@ -17,6 +18,10 @@ import com.comphenix.protocol.reflect.EquivalentConverter;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class EnumWrappersTest {
private static class EnumClass {
public EnumProtocol protocol;
@ -58,4 +63,11 @@ public class EnumWrappersTest {
converter.getSpecific(accessor.get(target))
);
}
private static final Set<String> KNOWN_INVALID = Sets.newHashSet("Particle");
@Test
public void testValidity() {
assertEquals(EnumWrappers.INVALID, KNOWN_INVALID);
}
}