Fix player action enum compatibility with 1.14 and below

This commit is contained in:
Dan Mulloy 2019-12-15 14:50:02 -05:00
parent 6f8b2377b1
commit e915fd0f9a
No known key found for this signature in database
GPG Key ID: 2B62F7DACFF133E8
2 changed files with 44 additions and 31 deletions

View File

@ -22,6 +22,7 @@ import org.bukkit.GameMode;
* Represents a generic enum converter.
* @author Kristian
*/
@SuppressWarnings({"unchecked","rawtypes"})
public abstract class EnumWrappers {
public enum ClientCommand {
PERFORM_RESPAWN,
@ -161,8 +162,8 @@ public abstract class EnumWrappers {
}
public enum PlayerAction implements AliasedEnum {
PRESS_SHIFT_KEY("START_SNEAKING"),
RELEASE_SHIFT_KEY("STOP_SNEAKING"),
START_SNEAKING("PRESS_SHIFT_KEY"),
STOP_SNEAKING("RELEASE_SHIFT_KEY"),
STOP_SLEEPING,
START_SPRINTING,
STOP_SPRINTING,
@ -677,8 +678,9 @@ public abstract class EnumWrappers {
return new EnumConverter<>(null, specificType);
}
// The common enum converter
@SuppressWarnings({ "rawtypes", "unchecked" })
/**
* The common Enum converter
*/
public static class EnumConverter<T extends Enum<T>> implements EquivalentConverter<T> {
private Class<?> genericType;
private Class<T> specificType;
@ -712,10 +714,16 @@ public abstract class EnumWrappers {
String[] getAliases();
}
/**
* Enums whose name has changed across NMS versions. Enums using this must also implement {@link AliasedEnum}
*/
public static class AliasedEnumConverter<T extends Enum<T> & AliasedEnum> implements EquivalentConverter<T> {
private Class<?> genericType;
private Class<T> specificType;
private Map<T, Object> genericMap = new ConcurrentHashMap<>();
private Map<Object, T> specificMap = new ConcurrentHashMap<>();
public AliasedEnumConverter(Class<?> genericType, Class<T> specificType) {
this.genericType = genericType;
this.specificType = specificType;
@ -723,51 +731,51 @@ public abstract class EnumWrappers {
@Override
public T getSpecific(Object generic) {
String name = ((Enum) generic).name();
return specificMap.computeIfAbsent(generic, x -> {
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;
try {
return Enum.valueOf(specificType, name);
} catch (Exception ex) {
for (T elem : specificType.getEnumConstants()) {
for (String alias : elem.getAliases()) {
if (alias.equals(name)) {
return elem;
}
}
}
}
}
throw new IllegalArgumentException("Unknown enum constant " + name);
throw new IllegalArgumentException("Unknown enum constant " + name);
});
}
@Override
public Object getGeneric(T specific) {
String name = specific.name();
return genericMap.computeIfAbsent(specific, x -> {
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;
try {
return Enum.valueOf((Class) genericType, specific.name());
} catch (Exception ex) {
for (Object rawElem : genericType.getEnumConstants()) {
Enum elem = (Enum) rawElem;
for (String alias : specific.getAliases()) {
if (alias.equals(elem.name())) {
return elem;
}
}
}
}
}
throw new IllegalArgumentException("Unknown enum constant " + name);
throw new IllegalArgumentException("Unknown enum constant " + name);
});
}
@Override
public Class<T> getSpecificType() {
return specificType;
}
void setGenericType(Class<?> genericType) {
this.genericType = genericType;
}
}
/**

View File

@ -456,9 +456,14 @@ public class PacketContainerTest {
@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);
// no change across nms versions
container.getPlayerActions().write(0, EnumWrappers.PlayerAction.OPEN_INVENTORY);
assertEquals(container.getPlayerActions().read(0), EnumWrappers.PlayerAction.OPEN_INVENTORY);
// changed in 1.15
container.getPlayerActions().write(0, EnumWrappers.PlayerAction.START_SNEAKING);
assertEquals(container.getPlayerActions().read(0), EnumWrappers.PlayerAction.START_SNEAKING);
}
@Test