From 540a5e53c429416fd0b4b0587f1db00dd6a689eb Mon Sep 17 00:00:00 2001 From: Dan Mulloy Date: Thu, 22 Dec 2016 11:42:52 -0500 Subject: [PATCH] Make Sound handling more robust Fixes aadnk#119 --- .../protocol/utility/MinecraftReflection.java | 4 ++ .../protocol/wrappers/BukkitConverters.java | 50 +++++++++++++++---- .../protocol/wrappers/MinecraftKey.java | 4 ++ 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/modules/API/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java b/modules/API/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java index 57d3ce13..2e9a00e1 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java +++ b/modules/API/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java @@ -1847,6 +1847,10 @@ public class MinecraftReflection { return getMinecraftClass("NonNullList"); } + public static Class getCraftSoundClass() { + return getCraftBukkitClass("CraftSound"); + } + // ---- ItemStack conversions private static Method asNMSCopy = null; diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java index 2b1005d7..45a7aaad 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java @@ -29,6 +29,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import org.bukkit.Material; import org.bukkit.Sound; @@ -964,10 +965,21 @@ public class BukkitConverters { }; } - private static MethodAccessor soundGetter = null; + private static MethodAccessor getSound = null; + private static MethodAccessor getSoundEffect = null; private static FieldAccessor soundKey = null; + private static Map soundIndex = null; + public static EquivalentConverter getSoundConverter() { + if (getSound == null || getSoundEffect == null) { + Class craftSound = MinecraftReflection.getCraftSoundClass(); + FuzzyReflection fuzzy = FuzzyReflection.fromClass(craftSound, true); + getSound = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("getSound", String.class, new Class[] { Sound.class })); + getSoundEffect = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("getSoundEffect", + MinecraftReflection.getSoundEffectClass(), new Class[] { String.class })); + } + return new IgnoreNullConverter() { @Override @@ -977,26 +989,42 @@ public class BukkitConverters { @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.getSoundEffectClass(), new Class[] { String.class })); - } - - MinecraftKey key = MinecraftKey.fromEnum(specific); - return soundGetter.invoke(null, key.getFullKey()); + // Getting the SoundEffect is easy, Bukkit provides us the methods + String key = (String) getSound.invoke(null, specific); + return getSoundEffect.invoke(null, key); } @Override protected Sound getSpecificValue(Object generic) { + // Getting the Sound is a bit more complicated... if (soundKey == null) { Class soundEffect = generic.getClass(); FuzzyReflection fuzzy = FuzzyReflection.fromClass(soundEffect, true); soundKey = Accessors.getFieldAccessor(fuzzy.getFieldByType("key", MinecraftReflection.getMinecraftKeyClass())); } - MinecraftKey key = MinecraftKey.fromHandle(soundKey.get(generic)); - return Sound.valueOf(key.getEnumFormat()); + MinecraftKey minecraftKey = MinecraftKey.fromHandle(soundKey.get(generic)); + String key = minecraftKey.getKey(); + + // Use our index if it already exists + if (soundIndex != null) { + return soundIndex.get(key); + } + + // If it doesn't, try to guess the enum name + try { + return Sound.valueOf(minecraftKey.getEnumFormat()); + } catch (IllegalArgumentException ignored) { + } + + // Worst case we index all the sounds and use it later + soundIndex = new ConcurrentHashMap<>(); + for (Sound sound : Sound.values()) { + String index = (String) getSound.invoke(null, sound); + soundIndex.put(index, sound); + } + + return soundIndex.get(key); } }; } diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/MinecraftKey.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/MinecraftKey.java index ba4830c4..788c75e1 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/MinecraftKey.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/MinecraftKey.java @@ -69,7 +69,9 @@ public class MinecraftKey { * is lower case, with underscores replaced by periods. * @param value The value * @return The resulting key + * @deprecated This isn't accurate in all cases */ + @Deprecated public static MinecraftKey fromEnum(Enum value) { return new MinecraftKey(value.name().toLowerCase(Locale.ENGLISH).replace("_", ".")); } @@ -103,7 +105,9 @@ public class MinecraftKey { * Returns this key back into Enum format, upper case with periods replaced * by underscores. * @return The enum format + * @deprecated This isn't accurate in all cases */ + @Deprecated public String getEnumFormat() { return key.toUpperCase(Locale.ENGLISH).replace(".", "_"); }