(Improvement) Implement playing sound by string ID (#5201)

* (improvement) implement playing sound by string ID

I've replaced enum-based sound playing events with string-based equivalents, which should open the door for server customization and other enhancements in the future

- Added SoundLookup class with different registry lookup methods depending on server version.
- Added the ability to configure what sounds are played depending on event, with a fallback built into SoundType.
- Removed getCrippleSound as SoundLookup can now fall back to the original default sound if the mace sound doesn't exist on the server's Minecraft version.
- Added a EnableCustomSounds config variable that will skip SoundLookup ID checking and just pass the sound string directly to the client, mainly due to the fact that it isn't possible to verify if resource pack values exist.
 - Cleaned up a few switch statements to match how the original getSound had it formatted.

I'd love to see/do a further expansion of sound configuration for each ability now that we can just fall back to generic, but that may be for another PR.

* Fix getIsEnabled using wrong key

* always use registry, simplify custom sound enabling logic, optimize reflection calls

* forgot we need this for legacy versions

---------

Co-authored-by: nossr50 <nossr50@gmail.com>
This commit is contained in:
Nathan V.
2025-08-30 14:15:26 -04:00
committed by GitHub
parent 99f7437d9d
commit df69410e67
5 changed files with 229 additions and 45 deletions

View File

@@ -0,0 +1,92 @@
package com.gmail.nossr50.util.sounds;
import static java.lang.String.format;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.AttributeMapper;
import com.gmail.nossr50.util.LogUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Locale;
import org.bukkit.NamespacedKey;
import org.bukkit.Sound;
import org.jetbrains.annotations.Nullable;
public final class SoundRegistryUtils {
private static Method registryLookup;
private static Object soundReg;
public static final String PAPER_SOUND_REGISTRY_FIELD = "SOUND_EVENT";
public static final String SPIGOT_SOUND_REGISTRY_FIELD = "SOUNDS";
public static final String METHOD_GET_OR_THROW_NAME = "getOrThrow";
public static final String METHOD_GET_NAME = "get";
static {
boolean foundRegistry = false;
Class<?> registry;
try {
registry = Class.forName(AttributeMapper.ORG_BUKKIT_REGISTRY);
try {
// First check for Paper's sound registry, held by field SOUND_EVENT
soundReg = registry.getField(PAPER_SOUND_REGISTRY_FIELD).get(null);
foundRegistry = true;
} catch (NoSuchFieldException | IllegalAccessException e) {
try {
soundReg = registry.getField(SPIGOT_SOUND_REGISTRY_FIELD);
foundRegistry = true;
} catch (NoSuchFieldException ex) {
// ignored
}
}
} catch (ClassNotFoundException e) {
// ignored
}
if (foundRegistry) {
try {
// getOrThrow isn't in all API versions, but we use it if it exists
registryLookup = soundReg.getClass().getMethod(METHOD_GET_OR_THROW_NAME,
NamespacedKey.class);
} catch (NoSuchMethodException e) {
try {
registryLookup = soundReg.getClass().getMethod(METHOD_GET_NAME,
NamespacedKey.class);
} catch (NoSuchMethodException ex) {
// ignored exception
registryLookup = null;
}
}
}
}
public static boolean useLegacyLookup() {
return registryLookup == null;
}
public static @Nullable Sound getSound(String id, String fallBackId) {
if (registryLookup != null) {
try {
return (Sound) registryLookup.invoke(soundReg, NamespacedKey.fromString(id));
} catch(InvocationTargetException | IllegalAccessException
| IllegalArgumentException e) {
if (fallBackId != null) {
LogUtils.debug(mcMMO.p.getLogger(),
format("Could not find sound with ID '%s', trying fallback ID '%s'", id,
fallBackId));
try {
return (Sound) registryLookup.invoke(soundReg,
NamespacedKey.fromString(fallBackId));
} catch (IllegalAccessException | InvocationTargetException ex) {
mcMMO.p.getLogger().severe(format("Could not find sound with ID %s,"
+ " fallback ID of %s also failed.", id, fallBackId));
}
} else {
mcMMO.p.getLogger().severe(format("Could not find sound with ID %s.", id));
}
throw new RuntimeException(e);
}
}
return null;
}
}