diff --git a/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java b/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java index 9b4a1031..1aaa9cf6 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java +++ b/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java @@ -4,6 +4,7 @@ import java.lang.reflect.Field; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.PacketType.Protocol; @@ -159,16 +160,26 @@ public abstract class EnumWrappers { SWAP_HELD_ITEMS } - public enum PlayerAction { - START_SNEAKING, - STOP_SNEAKING, + public enum PlayerAction implements AliasedEnum { + PRESS_SHIFT_KEY("START_SNEAKING"), + RELEASE_SHIFT_KEY("STOP_SNEAKING"), STOP_SLEEPING, START_SPRINTING, STOP_SPRINTING, START_RIDING_JUMP, STOP_RIDING_JUMP, OPEN_INVENTORY, - START_FALL_FLYING + START_FALL_FLYING; + + String[] aliases; + PlayerAction(String... aliases) { + this.aliases = aliases; + } + + @Override + public String[] getAliases() { + return aliases; + } } public enum ScoreboardAction { @@ -617,7 +628,7 @@ public abstract class EnumWrappers { } public static EquivalentConverter getEntityActionConverter() { - return new EnumConverter<>(getPlayerActionClass(), PlayerAction.class); + return new AliasedEnumConverter<>(getPlayerActionClass(), PlayerAction.class); } public static EquivalentConverter getUpdateScoreActionConverter() { @@ -697,6 +708,68 @@ public abstract class EnumWrappers { } } + public interface AliasedEnum { + String[] getAliases(); + } + + public static class AliasedEnumConverter & AliasedEnum> implements EquivalentConverter { + private Class genericType; + private Class specificType; + + public AliasedEnumConverter(Class genericType, Class specificType) { + this.genericType = genericType; + this.specificType = specificType; + } + + @Override + public T getSpecific(Object generic) { + String name = ((Enum) generic).name(); + + try { + return Enum.valueOf(specificType, name); + } catch (Exception ex) { + // TODO would caching help much, if at all? + for (T elem : specificType.getEnumConstants()) { + for (String alias : elem.getAliases()) { + if (alias.equals(name)) { + return elem; + } + } + } + } + + throw new IllegalArgumentException("Unknown enum constant " + name); + } + + @Override + public Object getGeneric(T specific) { + String name = specific.name(); + + try { + return Enum.valueOf((Class) genericType, specific.name()); + } catch (Exception ex) { + for (Object elem : genericType.getEnumConstants()) { + for (String alias : specific.getAliases()) { + if (alias.equals(name)) { + return elem; + } + } + } + } + + throw new IllegalArgumentException("Unknown enum constant " + name); + } + + @Override + public Class getSpecificType() { + return specificType; + } + + void setGenericType(Class genericType) { + this.genericType = genericType; + } + } + /** * Used for classes where it's an enum in everything but name * @param Generic type diff --git a/src/main/java/com/comphenix/protocol/wrappers/nbt/WrappedCompound.java b/src/main/java/com/comphenix/protocol/wrappers/nbt/WrappedCompound.java index 058bb585..dd607803 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/nbt/WrappedCompound.java +++ b/src/main/java/com/comphenix/protocol/wrappers/nbt/WrappedCompound.java @@ -201,10 +201,12 @@ class WrappedCompound implements NbtWrapper>>, NbtCompoun NbtBase nbt = getValue(key); // Create or get a compound - if (nbt == null) - put(nbt = NbtFactory.ofWrapper(type, key)); - else if (nbt.getType() != type) + if (nbt == null) { + nbt = NbtFactory.ofWrapper(type, key); + put(nbt); + } else if (nbt.getType() != type) { throw new IllegalArgumentException("Cannot get tag " + nbt + ": Not a " + type); + } return nbt; } diff --git a/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java b/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java index fce76917..86ff9ffe 100644 --- a/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java +++ b/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java @@ -453,6 +453,14 @@ public class PacketContainerTest { assertEquals(e, (byte) packet.getBytes().read(2)); } + @Test + public void testPlayerAction() { + PacketContainer container = new PacketContainer(PacketType.Play.Client.ENTITY_ACTION); + container.getPlayerActions().write(0, EnumWrappers.PlayerAction.PRESS_SHIFT_KEY); + + assertEquals(container.getPlayerActions().read(0), EnumWrappers.PlayerAction.PRESS_SHIFT_KEY); + } + @Test public void testMobEffectList() { PacketContainer container = new PacketContainer(PacketType.Play.Server.REMOVE_ENTITY_EFFECT);