From ecef9c5f5ef404a1ab67c28dac5af0d49a65c579 Mon Sep 17 00:00:00 2001 From: shanebeee Date: Thu, 7 Nov 2024 10:38:27 -0800 Subject: [PATCH 1/6] SoundUtils - handle Sound class for enum/interface --- .../ch/njol/skript/effects/EffPlaySound.java | 8 +- .../java/ch/njol/skript/util/SoundUtils.java | 87 ++++++++++--------- 2 files changed, 51 insertions(+), 44 deletions(-) diff --git a/src/main/java/ch/njol/skript/effects/EffPlaySound.java b/src/main/java/ch/njol/skript/effects/EffPlaySound.java index 2846d616f06..e3bdb6a7873 100644 --- a/src/main/java/ch/njol/skript/effects/EffPlaySound.java +++ b/src/main/java/ch/njol/skript/effects/EffPlaySound.java @@ -10,6 +10,7 @@ import ch.njol.skript.lang.Effect; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.SoundUtils; import ch.njol.util.Kleenean; import org.bukkit.Location; import org.bukkit.NamespacedKey; @@ -149,11 +150,8 @@ protected void execute(Event event) { // validate strings List validSounds = new ArrayList<>(); for (String sound : sounds.getArray(event)) { - NamespacedKey key = null; - try { - Sound enumSound = Sound.valueOf(sound.toUpperCase(Locale.ENGLISH)); - key = enumSound.getKey(); - } catch (IllegalArgumentException alternative) { + NamespacedKey key = SoundUtils.getSoundKeyFromEnum(sound); + if (key == null) { sound = sound.toLowerCase(Locale.ENGLISH); Matcher keyMatcher = KEY_PATTERN.matcher(sound); if (!keyMatcher.matches()) diff --git a/src/main/java/ch/njol/skript/util/SoundUtils.java b/src/main/java/ch/njol/skript/util/SoundUtils.java index bbf18e2ea1c..c90b4ee583e 100644 --- a/src/main/java/ch/njol/skript/util/SoundUtils.java +++ b/src/main/java/ch/njol/skript/util/SoundUtils.java @@ -1,49 +1,58 @@ -/** - * This file is part of Skript. - * - * Skript is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Skript is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Skript. If not, see . - * - * Copyright Peter Güttinger, SkriptLang team and contributors - */ package ch.njol.skript.util; +import org.bukkit.NamespacedKey; import org.bukkit.Sound; import org.jetbrains.annotations.Nullable; -/** - * @author Peter Güttinger - */ -public abstract class SoundUtils { - private SoundUtils() {} - +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Locale; + +public class SoundUtils { + + private static final boolean IS_INTERFACE; + private static final Method VALUE_OF_METHOD; + private static final Method GET_KEY_METHOD; + static { - assert false; + try { + Class SOUND_CLASS = Class.forName("org.bukkit.Sound"); + IS_INTERFACE = SOUND_CLASS.isInterface(); + VALUE_OF_METHOD = SOUND_CLASS.getDeclaredMethod("valueOf", String.class); + GET_KEY_METHOD = SOUND_CLASS.getDeclaredMethod("getKey"); + } catch (NoSuchMethodException | ClassNotFoundException e) { + throw new RuntimeException(e); + } } - - private final static EnumUtils util = new EnumUtils<>(Sound.class, "sounds"); - + + /** + * Get the NamespacedKey of a Bukkit Sound enum + * + * @param soundString String to check for enum + * @return Sound key if available else null + */ + @SuppressWarnings("deprecation") @Nullable - public static Sound parse(final String s) { - return util.parse(s); + public static NamespacedKey getSoundKeyFromEnum(String soundString) { + soundString = soundString.toUpperCase(Locale.ENGLISH); + // Sound.class is an Interface (rather than an enum) as of MC 1.21.3 + if (IS_INTERFACE) { + try { + Sound sound = Sound.valueOf(soundString); + return sound.getKey(); + } catch (IllegalArgumentException ignore) { + } + } else { + try { + Object sound = VALUE_OF_METHOD.invoke(null, soundString); + if (sound != null) { + return (NamespacedKey) GET_KEY_METHOD.invoke(sound); + } + } catch (IllegalAccessException | + InvocationTargetException ignore) { + } + } + return null; } - - public static String toString(final Sound s, final int flags) { - return util.toString(s, flags); - } - - public static String getAllNames() { - return util.getAllNames(); - } - + } From 389de5c7f229e4fd6ae3a2cdbde4982708396147 Mon Sep 17 00:00:00 2001 From: shanebeee Date: Thu, 7 Nov 2024 11:00:50 -0800 Subject: [PATCH 2/6] SoundUtils - fix an error with MC 1.15 --- src/main/java/ch/njol/skript/util/SoundUtils.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/ch/njol/skript/util/SoundUtils.java b/src/main/java/ch/njol/skript/util/SoundUtils.java index c90b4ee583e..fd876358ca8 100644 --- a/src/main/java/ch/njol/skript/util/SoundUtils.java +++ b/src/main/java/ch/njol/skript/util/SoundUtils.java @@ -1,5 +1,6 @@ package ch.njol.skript.util; +import ch.njol.skript.Skript; import org.bukkit.NamespacedKey; import org.bukkit.Sound; import org.jetbrains.annotations.Nullable; @@ -19,7 +20,13 @@ public class SoundUtils { Class SOUND_CLASS = Class.forName("org.bukkit.Sound"); IS_INTERFACE = SOUND_CLASS.isInterface(); VALUE_OF_METHOD = SOUND_CLASS.getDeclaredMethod("valueOf", String.class); - GET_KEY_METHOD = SOUND_CLASS.getDeclaredMethod("getKey"); + if (Skript.methodExists(SOUND_CLASS, "getKey")) { + // I believe this method was added around Bukkit 1.16 + // This is only added to make tests not fail when testing MC 1.15 and below + GET_KEY_METHOD = SOUND_CLASS.getDeclaredMethod("getKey"); + } else { + GET_KEY_METHOD = null; + } } catch (NoSuchMethodException | ClassNotFoundException e) { throw new RuntimeException(e); } @@ -42,7 +49,7 @@ public static NamespacedKey getSoundKeyFromEnum(String soundString) { return sound.getKey(); } catch (IllegalArgumentException ignore) { } - } else { + } else if (GET_KEY_METHOD != null) { try { Object sound = VALUE_OF_METHOD.invoke(null, soundString); if (sound != null) { From 09d6f7eb82d1a57d434bf9e26fcfb007280fc3b1 Mon Sep 17 00:00:00 2001 From: shanebeee Date: Thu, 7 Nov 2024 13:27:50 -0800 Subject: [PATCH 3/6] EffPlaySound.sk - add simple test to make sure syntax doesn't throw error --- src/test/skript/tests/syntaxes/effects/EffPlaySound.sk | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/test/skript/tests/syntaxes/effects/EffPlaySound.sk diff --git a/src/test/skript/tests/syntaxes/effects/EffPlaySound.sk b/src/test/skript/tests/syntaxes/effects/EffPlaySound.sk new file mode 100644 index 00000000000..5cd27437d00 --- /dev/null +++ b/src/test/skript/tests/syntaxes/effects/EffPlaySound.sk @@ -0,0 +1,3 @@ +test "play sound effect": + play sound "block.stone.break" with volume 1 at spawn of world "world" + play sound "BLOCK_STONE_BREAK" with volume 1 at spawn of world "world" From 0f8fce096fafa8cfac524de5e5657a5a9db4a788 Mon Sep 17 00:00:00 2001 From: shanebeee Date: Thu, 7 Nov 2024 13:28:11 -0800 Subject: [PATCH 4/6] EffPlaySound - remove reflection and remove to effect class --- .../ch/njol/skript/effects/EffPlaySound.java | 28 +++++++- .../java/ch/njol/skript/util/SoundUtils.java | 65 ------------------- 2 files changed, 26 insertions(+), 67 deletions(-) delete mode 100644 src/main/java/ch/njol/skript/util/SoundUtils.java diff --git a/src/main/java/ch/njol/skript/effects/EffPlaySound.java b/src/main/java/ch/njol/skript/effects/EffPlaySound.java index e3bdb6a7873..8573ba005e3 100644 --- a/src/main/java/ch/njol/skript/effects/EffPlaySound.java +++ b/src/main/java/ch/njol/skript/effects/EffPlaySound.java @@ -10,8 +10,8 @@ import ch.njol.skript.lang.Effect; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.SoundUtils; import ch.njol.util.Kleenean; +import org.bukkit.Keyed; import org.bukkit.Location; import org.bukkit.NamespacedKey; import org.bukkit.Sound; @@ -73,6 +73,7 @@ public class EffPlaySound extends Effect { private static final boolean ENTITY_EMITTER_SOUND = Skript.methodExists(Player.class, "playSound", Entity.class, Sound.class, SoundCategory.class, float.class, float.class); private static final boolean ENTITY_EMITTER_STRING = Skript.methodExists(Player.class, "playSound", Entity.class, String.class, SoundCategory.class, float.class, float.class); private static final boolean ENTITY_EMITTER = ENTITY_EMITTER_SOUND || ENTITY_EMITTER_STRING; + private static final boolean IS_INTERFACE = Sound.class.isInterface(); public static final Pattern KEY_PATTERN = Pattern.compile("([a-z0-9._-]+:)?([a-z0-9/._-]+)"); @@ -150,7 +151,7 @@ protected void execute(Event event) { // validate strings List validSounds = new ArrayList<>(); for (String sound : sounds.getArray(event)) { - NamespacedKey key = SoundUtils.getSoundKeyFromEnum(sound); + NamespacedKey key = getSoundKeyFromEnum(sound); if (key == null) { sound = sound.toLowerCase(Locale.ENGLISH); Matcher keyMatcher = KEY_PATTERN.matcher(sound); @@ -238,4 +239,27 @@ public String toString(@Nullable Event event, boolean debug) { return builder.toString(); } + @SuppressWarnings({"deprecation", "unchecked", "rawtypes"}) + @Nullable + private static NamespacedKey getSoundKeyFromEnum(String soundString) { + soundString = soundString.toUpperCase(Locale.ENGLISH); + // Sound.class is an Interface (rather than an enum) as of MC 1.21.3 + if (IS_INTERFACE) { + try { + Sound sound = Sound.valueOf(soundString); + return sound.getKey(); + } catch (IllegalArgumentException ignore) { + } + } else { + try { + Enum soundEnum = Enum.valueOf((Class) Sound.class, soundString); + if (soundEnum instanceof Keyed) { + return ((Keyed) soundEnum).getKey(); + } + } catch (IllegalArgumentException ignore) { + } + } + return null; + } + } diff --git a/src/main/java/ch/njol/skript/util/SoundUtils.java b/src/main/java/ch/njol/skript/util/SoundUtils.java deleted file mode 100644 index fd876358ca8..00000000000 --- a/src/main/java/ch/njol/skript/util/SoundUtils.java +++ /dev/null @@ -1,65 +0,0 @@ -package ch.njol.skript.util; - -import ch.njol.skript.Skript; -import org.bukkit.NamespacedKey; -import org.bukkit.Sound; -import org.jetbrains.annotations.Nullable; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Locale; - -public class SoundUtils { - - private static final boolean IS_INTERFACE; - private static final Method VALUE_OF_METHOD; - private static final Method GET_KEY_METHOD; - - static { - try { - Class SOUND_CLASS = Class.forName("org.bukkit.Sound"); - IS_INTERFACE = SOUND_CLASS.isInterface(); - VALUE_OF_METHOD = SOUND_CLASS.getDeclaredMethod("valueOf", String.class); - if (Skript.methodExists(SOUND_CLASS, "getKey")) { - // I believe this method was added around Bukkit 1.16 - // This is only added to make tests not fail when testing MC 1.15 and below - GET_KEY_METHOD = SOUND_CLASS.getDeclaredMethod("getKey"); - } else { - GET_KEY_METHOD = null; - } - } catch (NoSuchMethodException | ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - /** - * Get the NamespacedKey of a Bukkit Sound enum - * - * @param soundString String to check for enum - * @return Sound key if available else null - */ - @SuppressWarnings("deprecation") - @Nullable - public static NamespacedKey getSoundKeyFromEnum(String soundString) { - soundString = soundString.toUpperCase(Locale.ENGLISH); - // Sound.class is an Interface (rather than an enum) as of MC 1.21.3 - if (IS_INTERFACE) { - try { - Sound sound = Sound.valueOf(soundString); - return sound.getKey(); - } catch (IllegalArgumentException ignore) { - } - } else if (GET_KEY_METHOD != null) { - try { - Object sound = VALUE_OF_METHOD.invoke(null, soundString); - if (sound != null) { - return (NamespacedKey) GET_KEY_METHOD.invoke(sound); - } - } catch (IllegalAccessException | - InvocationTargetException ignore) { - } - } - return null; - } - -} From 381959fe20e1da1366251d5d59f38149787e2524 Mon Sep 17 00:00:00 2001 From: shanebeee Date: Thu, 7 Nov 2024 13:46:24 -0800 Subject: [PATCH 5/6] EffPlaySound - some changes --- src/main/java/ch/njol/skript/effects/EffPlaySound.java | 7 +++---- src/test/skript/tests/syntaxes/effects/EffPlaySound.sk | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/ch/njol/skript/effects/EffPlaySound.java b/src/main/java/ch/njol/skript/effects/EffPlaySound.java index 8573ba005e3..b0a79a39033 100644 --- a/src/main/java/ch/njol/skript/effects/EffPlaySound.java +++ b/src/main/java/ch/njol/skript/effects/EffPlaySound.java @@ -73,7 +73,7 @@ public class EffPlaySound extends Effect { private static final boolean ENTITY_EMITTER_SOUND = Skript.methodExists(Player.class, "playSound", Entity.class, Sound.class, SoundCategory.class, float.class, float.class); private static final boolean ENTITY_EMITTER_STRING = Skript.methodExists(Player.class, "playSound", Entity.class, String.class, SoundCategory.class, float.class, float.class); private static final boolean ENTITY_EMITTER = ENTITY_EMITTER_SOUND || ENTITY_EMITTER_STRING; - private static final boolean IS_INTERFACE = Sound.class.isInterface(); + private static final boolean SOUND_IS_INTERFACE = Sound.class.isInterface(); public static final Pattern KEY_PATTERN = Pattern.compile("([a-z0-9._-]+:)?([a-z0-9/._-]+)"); @@ -240,11 +240,10 @@ public String toString(@Nullable Event event, boolean debug) { } @SuppressWarnings({"deprecation", "unchecked", "rawtypes"}) - @Nullable - private static NamespacedKey getSoundKeyFromEnum(String soundString) { + private static @Nullable NamespacedKey getSoundKeyFromEnum(String soundString) { soundString = soundString.toUpperCase(Locale.ENGLISH); // Sound.class is an Interface (rather than an enum) as of MC 1.21.3 - if (IS_INTERFACE) { + if (SOUND_IS_INTERFACE) { try { Sound sound = Sound.valueOf(soundString); return sound.getKey(); diff --git a/src/test/skript/tests/syntaxes/effects/EffPlaySound.sk b/src/test/skript/tests/syntaxes/effects/EffPlaySound.sk index 5cd27437d00..2e9647c8059 100644 --- a/src/test/skript/tests/syntaxes/effects/EffPlaySound.sk +++ b/src/test/skript/tests/syntaxes/effects/EffPlaySound.sk @@ -1,3 +1,3 @@ test "play sound effect": - play sound "block.stone.break" with volume 1 at spawn of world "world" - play sound "BLOCK_STONE_BREAK" with volume 1 at spawn of world "world" + play sound "block.stone.break" with volume 1 at test-location + play sound "BLOCK_STONE_BREAK" with volume 1 at test-location From d204347cfe620b3fd931a997961e67edda9d2250 Mon Sep 17 00:00:00 2001 From: shanebeee Date: Thu, 7 Nov 2024 13:54:49 -0800 Subject: [PATCH 6/6] EffPlaySound.sk - fix tests failing --- src/test/skript/tests/syntaxes/effects/EffPlaySound.sk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/skript/tests/syntaxes/effects/EffPlaySound.sk b/src/test/skript/tests/syntaxes/effects/EffPlaySound.sk index 2e9647c8059..5cd27437d00 100644 --- a/src/test/skript/tests/syntaxes/effects/EffPlaySound.sk +++ b/src/test/skript/tests/syntaxes/effects/EffPlaySound.sk @@ -1,3 +1,3 @@ test "play sound effect": - play sound "block.stone.break" with volume 1 at test-location - play sound "BLOCK_STONE_BREAK" with volume 1 at test-location + play sound "block.stone.break" with volume 1 at spawn of world "world" + play sound "BLOCK_STONE_BREAK" with volume 1 at spawn of world "world"