From ecef9c5f5ef404a1ab67c28dac5af0d49a65c579 Mon Sep 17 00:00:00 2001
From: shanebeee <shanebolenback@me.com>
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<NamespacedKey> 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 <http://www.gnu.org/licenses/>.
- *
- * 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<Sound> 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 <shanebolenback@me.com>
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 <shanebolenback@me.com>
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 <shanebolenback@me.com>
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<NamespacedKey> 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 <shanebolenback@me.com>
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 <shanebolenback@me.com>
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"