From 80a47312eeb47a1a11a781d64d5f94b05e0ef92c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Mon, 10 Mar 2025 01:17:12 -0500 Subject: [PATCH 01/26] I think it works --- build.gradle.kts | 1 + .../dev/znci/rocket/commands/RocketCommand.kt | 20 +- .../znci/rocket/scripting/ScriptManager.kt | 16 +- .../rocket/scripting/events/EventListener.kt | 199 ++++++++++-------- 4 files changed, 148 insertions(+), 88 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index f480d46..63ce6e1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,6 +37,7 @@ dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") implementation("org.luaj:luaj-jse:3.0.1") implementation("net.luckperms:api:5.4") + implementation("com.google.guava:guava:32.0.1-jre") } val targetJavaVersion = 21 diff --git a/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt b/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt index 269f9f4..a17b2d8 100644 --- a/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt +++ b/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt @@ -51,6 +51,13 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.config_reloaded")) return true + } else if (scriptName.lowercase() == "all") { + val results = ScriptManager.loadAll() + if (results.isNotEmpty()) { + results.forEach { error -> + sender.sendMessage(LocaleManager.getMessageAsComponent("generic_error", error ?: "Unknown error")) + } + } } val scriptFile = File(scriptsFolder, scriptName) @@ -59,8 +66,7 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { return true } - val content = scriptFile.readText() - val result = ScriptManager.runScript(content) + val result = ScriptManager.loadScript(scriptFile) if (result !== "") { sender.sendMessage(LocaleManager.getMessageAsComponent("generic_error", result ?: "Unknown error")) @@ -89,6 +95,8 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { return true } + + @Suppress("SENSELESS_COMPARISON") override fun onTabComplete( sender: CommandSender, @@ -101,9 +109,11 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { if (args.size == 1) { return mutableListOf("reload", "disable") } else if (args.size == 2) { - return if (args[0] == "reload") ScriptManager.getAllScripts().toMutableList() - else if (args[0] == "disable") ScriptManager.getAllScripts(false).toMutableList() - else null + val list: MutableList? = + if (args[0] == "reload") ScriptManager.getAllScripts().toMutableList().also { it.add("config") } + else if (args[0] == "disable") ScriptManager.getAllScripts(false).toMutableList().also { it.add("config") } + else null + return list } return null diff --git a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt index 1e4a98f..04d1c1e 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt @@ -51,12 +51,26 @@ object ScriptManager { scriptsFolder.walkTopDown().forEach { file -> if (file.isFile) { if (includeDisabled && file.startsWith("-")) return@forEach - list.add(file.path.removePrefix("plugins/rocket/scripts/")) + list.add(file.path.removePrefix(if (file.path.startsWith("plugins/rocket/scripts/")) "plugins/rocket/scripts/" else "plugins\\rocket\\scripts\\")) } } return list } + fun loadAll(): List { + val results = mutableListOf() + getAllScripts(false).forEach { script -> + results.add(loadScript(File("plugins/rocket/scripts/", script))) + } + return results + } + + fun loadScript(scriptFile: File): String? { + val content = scriptFile.readText() + val result = runScript(content) + return result + } + fun runScript(text: String): String? { try { globals.set("players", LuaPlayers()) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index 94350af..dac5f83 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -15,20 +15,23 @@ */ package dev.znci.rocket.scripting.events +import com.google.common.reflect.ClassPath import dev.znci.rocket.scripting.PlayerManager import dev.znci.rocket.scripting.ScriptManager +import net.kyori.adventure.text.Component import org.bukkit.Bukkit import org.bukkit.event.Cancellable import org.bukkit.event.Event -import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority import org.bukkit.event.Listener -import org.bukkit.event.block.BlockBreakEvent import org.bukkit.plugin.Plugin +import org.luaj.vm2.Lua import org.luaj.vm2.LuaBoolean import org.luaj.vm2.LuaTable import org.luaj.vm2.LuaValue +import org.luaj.vm2.lib.TwoArgFunction import org.luaj.vm2.lib.ZeroArgFunction +import java.util.stream.Collectors object EventListener : Listener { @@ -68,15 +71,21 @@ object EventListener : Listener { } private fun getSupportedEvents(): List> { - return listOf( - org.bukkit.event.player.PlayerJoinEvent::class.java, - org.bukkit.event.block.BlockBreakEvent::class.java, - org.bukkit.event.block.BlockPlaceEvent::class.java, - org.bukkit.event.player.PlayerMoveEvent::class.java, - org.bukkit.event.player.PlayerQuitEvent::class.java, - org.bukkit.event.player.PlayerInteractEvent::class.java, - io.papermc.paper.event.player.AsyncChatEvent::class.java - ) + return getBukkitEventClasses() + } + + @Suppress("UNCHECKED_CAST") + private fun getBukkitEventClasses(): List> { + return getClasses("org.bukkit.event") + .filter { Event::class.java.isAssignableFrom(it) && it != Event::class.java } + .map { it as Class } + } + + private fun getClasses(packageName: String): List> { + return ClassPath.from(this::class.java.classLoader) + .allClasses + .filter { it.packageName.startsWith(packageName, ignoreCase = true) } + .map { it.load() } } fun getEventByName(name: String): Class? { @@ -84,79 +93,105 @@ object EventListener : Listener { } private fun convertEventToLua(event: Event): LuaTable { - val luaTable = LuaTable() - - // Player fields & checking - var player: org.bukkit.entity.Player? = null - - // Check if there is a field for player - val playerField = event.javaClass.declaredFields.find { it.name == "player" } - if (playerField != null) { - playerField.isAccessible = true - val fieldPlayer = playerField.get(event) - if (fieldPlayer is org.bukkit.entity.Player) { - player = fieldPlayer - } - } - - // If there is no field for player, check if there is a method for player - if (player == null) { - val playerProperty = event.javaClass.methods.find { it.name == "getPlayer" } - if (playerProperty != null) { - val playerFromProperty = playerProperty.invoke(event) as? org.bukkit.entity.Player - player = playerFromProperty - } - } - - if (player != null) { - luaTable.set("player", PlayerManager.getPlayerOverallTable(player)) - } - - // Interaction event - if (event is org.bukkit.event.player.PlayerInteractEvent) { - val hand = event.hand - luaTable.set("hand", hand.toString()) - } - - // Quit event - if (event is org.bukkit.event.player.PlayerQuitEvent) { - val quitMessage = event.quitMessage() - luaTable.set("quitMessage", quitMessage.toString()) - - val reason = event.reason - luaTable.set("reason", reason.toString()) - } - - // Move event - val fields = event.javaClass.declaredFields.map { it.name } - if ("from" in fields) { - val fromField = event.javaClass.getDeclaredField("from") - fromField.isAccessible = true - val from = fromField.get(event) - if (from is org.bukkit.Location) { - // TODO: Finish this when mibers creates PR which adds new location class - } - } - - if ("to" in fields) { - val toField = event.javaClass.getDeclaredField("to") - toField.isAccessible = true - val to = toField.get(event) - if (to is org.bukkit.Location) { - // TODO: Finish this when mibers creates PR which adds new location class - } - } - - // Cancellable events - if (event is Cancellable) { - luaTable.set("cancel", object : ZeroArgFunction() { - override fun call(): LuaValue { - event.isCancelled = true - return LuaBoolean.valueOf(event.isCancelled) + val metaTable = LuaTable().apply { + set("__index", object : TwoArgFunction() { + override fun call(table: LuaValue, key: LuaValue): LuaValue { + // Player fields & checking + return when (key.tojstring()) { + "player" -> { + var player: org.bukkit.entity.Player? = null + + // Check if there is a field for player + val playerField = event.javaClass.declaredFields.find { it.name == "player" } + if (playerField != null) { + playerField.isAccessible = true + val fieldPlayer = playerField.get(event) + if (fieldPlayer is org.bukkit.entity.Player) { + player = fieldPlayer + } + } + + // If there is no field for player, check if there is a method for player + if (player == null) { + val playerProperty = event.javaClass.methods.find { it.name == "getPlayer" } + if (playerProperty != null) { + val playerFromProperty = playerProperty.invoke(event) as? org.bukkit.entity.Player + player = playerFromProperty + } + } + + if (player != null) { + return PlayerManager.getPlayerOverallTable(player) + } + + return LuaValue.NIL + } + "hand" -> { + // Interaction event + return when (event) { + is org.bukkit.event.player.PlayerInteractEvent -> LuaValue.valueOf(event.hand.toString()) + else -> LuaValue.NIL + } + } + "message" -> { + var message: Component = Component.text("") + return when (event) { + is org.bukkit.event.player.PlayerQuitEvent -> LuaValue.valueOf(event.quitMessage().toString()) + is org.bukkit.event.player.PlayerJoinEvent -> LuaValue.valueOf(event.joinMessage().toString()) + is io.papermc.paper.event.player.AsyncChatEvent -> LuaValue.valueOf(event.message().toString()) + else -> LuaValue.NIL + } + } + "reason" -> { + var reason: String? = null + when (event) { + is org.bukkit.event.player.PlayerQuitEvent -> LuaValue.valueOf(event.reason.toString()) + else -> LuaValue.NIL + } + + } + + // FIXME: I may have broken the next two since I'm not sure how they work + // I'm just trying to make it sort of fit the method this uses + + "from" -> { + val fromField = event.javaClass.getDeclaredField("from") + fromField.isAccessible = true + val from = fromField.get(event) + if (from is org.bukkit.Location) { + // TODO: Finish this when mibers creates PR which adds new location class + } + LuaValue.NIL + } + "to" -> { + val toField = event.javaClass.getDeclaredField("to") + toField.isAccessible = true + val to = toField.get(event) + if (to is org.bukkit.Location) { + // TODO: Finish this when mibers creates PR which adds new location class + } + LuaValue.NIL + } + "cancel" -> { + // Cancellable events + when (event) { + is Cancellable -> { + return object : ZeroArgFunction() { + override fun call(): LuaValue { + event.isCancelled = true + return LuaBoolean.valueOf(event.isCancelled) + } + } + } + + else -> LuaValue.NIL + } + } + else -> NIL + } } }) } - - return luaTable + return metaTable } } \ No newline at end of file From b67f31cd8ba8acc5b45a3744436555e5b3fc768f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Mon, 10 Mar 2025 01:38:48 -0500 Subject: [PATCH 02/26] Failed attempts at debugging (will keep trying) --- .../dev/znci/rocket/scripting/events/EventListener.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index dac5f83..0e0daf2 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -97,6 +97,7 @@ object EventListener : Listener { set("__index", object : TwoArgFunction() { override fun call(table: LuaValue, key: LuaValue): LuaValue { // Player fields & checking + println(key.tojstring()) return when (key.tojstring()) { "player" -> { var player: org.bukkit.entity.Player? = null @@ -134,10 +135,14 @@ object EventListener : Listener { } } "message" -> { - var message: Component = Component.text("") + println(event.javaClass.simpleName) return when (event) { is org.bukkit.event.player.PlayerQuitEvent -> LuaValue.valueOf(event.quitMessage().toString()) is org.bukkit.event.player.PlayerJoinEvent -> LuaValue.valueOf(event.joinMessage().toString()) + is org.bukkit.event.player.AsyncPlayerChatEvent -> LuaValue.valueOf(event.message).also { + println(true) + println(event.message) + } is io.papermc.paper.event.player.AsyncChatEvent -> LuaValue.valueOf(event.message().toString()) else -> LuaValue.NIL } From 969ad038e9535b7f8b5ad15b79fb8319ab0853f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Mon, 10 Mar 2025 22:39:03 -0500 Subject: [PATCH 03/26] Made it more dynamic with the previous way of retrieving values Co-authored-by: zNotChill Co-authored-by: mibers --- .../rocket/scripting/events/EventListener.kt | 207 ++++++++++-------- 1 file changed, 116 insertions(+), 91 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index 0e0daf2..b6027b7 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -18,20 +18,22 @@ package dev.znci.rocket.scripting.events import com.google.common.reflect.ClassPath import dev.znci.rocket.scripting.PlayerManager import dev.znci.rocket.scripting.ScriptManager +import dev.znci.rocket.scripting.functions.LuaLocation import net.kyori.adventure.text.Component import org.bukkit.Bukkit +import org.bukkit.Location +import org.bukkit.entity.Player import org.bukkit.event.Cancellable import org.bukkit.event.Event import org.bukkit.event.EventPriority import org.bukkit.event.Listener +import org.bukkit.inventory.EquipmentSlot import org.bukkit.plugin.Plugin -import org.luaj.vm2.Lua import org.luaj.vm2.LuaBoolean import org.luaj.vm2.LuaTable import org.luaj.vm2.LuaValue import org.luaj.vm2.lib.TwoArgFunction import org.luaj.vm2.lib.ZeroArgFunction -import java.util.stream.Collectors object EventListener : Listener { @@ -65,6 +67,7 @@ object EventListener : Listener { ScriptManager.usedEvents.forEach { (eventClass, callback) -> if (eventClass.isInstance(event)) { val luaTable = convertEventToLua(event) + println(callback) callback.call(luaTable) } } @@ -92,111 +95,133 @@ object EventListener : Listener { return getSupportedEvents().find { it.simpleName.equals(name, true) } } - private fun convertEventToLua(event: Event): LuaTable { - val metaTable = LuaTable().apply { - set("__index", object : TwoArgFunction() { - override fun call(table: LuaValue, key: LuaValue): LuaValue { - // Player fields & checking - println(key.tojstring()) - return when (key.tojstring()) { - "player" -> { - var player: org.bukkit.entity.Player? = null - - // Check if there is a field for player - val playerField = event.javaClass.declaredFields.find { it.name == "player" } - if (playerField != null) { - playerField.isAccessible = true - val fieldPlayer = playerField.get(event) - if (fieldPlayer is org.bukkit.entity.Player) { - player = fieldPlayer - } - } + private inline fun getValueFromField(event: Event, valuesToTry: Array): V? { + valuesToTry.forEach { value -> + val field = event.javaClass.declaredFields.find { it.name == value } + if (field != null) { + field.isAccessible = true + val valueFromField = field.get(event) + if (valueFromField is V) { + return valueFromField + } + } + } + return null + } - // If there is no field for player, check if there is a method for player - if (player == null) { - val playerProperty = event.javaClass.methods.find { it.name == "getPlayer" } - if (playerProperty != null) { - val playerFromProperty = playerProperty.invoke(event) as? org.bukkit.entity.Player - player = playerFromProperty - } - } + private inline fun getValueFromFunction(event: Event, valuesToTry: Array): V? { + valuesToTry.forEach { value -> + val valueProperty = event.javaClass.methods.find { it.name == value } + if (valueProperty != null) { + val valueFromProperty = valueProperty.invoke(event) as? V + return valueFromProperty + } + } + return null + } - if (player != null) { - return PlayerManager.getPlayerOverallTable(player) - } + private inline fun getValueFromEvent(event: Event, vararg valuesToTry: String): V? { - return LuaValue.NIL - } - "hand" -> { - // Interaction event - return when (event) { - is org.bukkit.event.player.PlayerInteractEvent -> LuaValue.valueOf(event.hand.toString()) - else -> LuaValue.NIL - } + var valueObj: V? = getValueFromField(event, valuesToTry) + if (valueObj == null) { + valueObj = getValueFromFunction(event, valuesToTry) + } + return valueObj + } + + private fun convertEventToLua(event: Event): LuaTable { + val table = LuaTable() + val meta = table.getmetatable() ?: LuaTable() + val indexFunction = meta.get("__index") as? TwoArgFunction + meta.set("__index", object : TwoArgFunction() { + override fun call(table: LuaValue, key: LuaValue): LuaValue { + return when (key.tojstring()) { + "player" -> { + val player: Player? = getValueFromEvent(event, "player", "getPlayer") + if (player != null) { + return PlayerManager.getPlayerOverallTable(player) } - "message" -> { - println(event.javaClass.simpleName) - return when (event) { - is org.bukkit.event.player.PlayerQuitEvent -> LuaValue.valueOf(event.quitMessage().toString()) - is org.bukkit.event.player.PlayerJoinEvent -> LuaValue.valueOf(event.joinMessage().toString()) - is org.bukkit.event.player.AsyncPlayerChatEvent -> LuaValue.valueOf(event.message).also { - println(true) - println(event.message) - } - is io.papermc.paper.event.player.AsyncChatEvent -> LuaValue.valueOf(event.message().toString()) - else -> LuaValue.NIL - } + return LuaValue.NIL.also { + error("No player in a '${event.eventName}' event!") } - "reason" -> { - var reason: String? = null - when (event) { - is org.bukkit.event.player.PlayerQuitEvent -> LuaValue.valueOf(event.reason.toString()) - else -> LuaValue.NIL - } + } + "hand" -> { + val hand: EquipmentSlot? = getValueFromEvent(event, "hand") + if (hand != null) { + return LuaValue.valueOf(hand.toString()) } + return LuaValue.NIL.also { + error("No hand in a '${event.eventName}' event!") + } + } - // FIXME: I may have broken the next two since I'm not sure how they work - // I'm just trying to make it sort of fit the method this uses - - "from" -> { - val fromField = event.javaClass.getDeclaredField("from") - fromField.isAccessible = true - val from = fromField.get(event) - if (from is org.bukkit.Location) { - // TODO: Finish this when mibers creates PR which adds new location class + "message" -> { + val message: Any? = getValueFromEvent( + event, + "message", + "getMessage", + "getJoinMessage", + "getDeathMessage", + "getQuitMessage", + "getKickMessage" + ) + if (message != null) { + if (message is String || message is Component) return LuaValue.valueOf(message.toString()) + return LuaValue.NIL.also { + error("Non-string/component object found in place of a message. Found '$message'") } - LuaValue.NIL } - "to" -> { - val toField = event.javaClass.getDeclaredField("to") - toField.isAccessible = true - val to = toField.get(event) - if (to is org.bukkit.Location) { - // TODO: Finish this when mibers creates PR which adds new location class - } - LuaValue.NIL + return LuaValue.NIL.also { + error("No message in a '${event.eventName}' event!") } - "cancel" -> { - // Cancellable events - when (event) { - is Cancellable -> { - return object : ZeroArgFunction() { - override fun call(): LuaValue { - event.isCancelled = true - return LuaBoolean.valueOf(event.isCancelled) - } + } + + // FIXME: I may have broken the next two since I'm not sure how they work + // I'm just trying to make it sort of fit the method this uses + + "from" -> { + val location: Location? = getValueFromEvent(event, "from", "getFrom") + return LuaLocation.fromBukkit(location?:return LuaValue.NIL.also { + error("Value 'from' of a '${event.eventName}' event returned null") + }) + } + + "to" -> { + val location: Location? = getValueFromEvent(event, "to", "getTo") + return LuaLocation.fromBukkit(location?:return LuaValue.NIL.also { + error("Value 'to' of a '${event.eventName}' event returned null") + }) + } + + "cancel" -> { + when (event) { + is Cancellable -> { + return object : ZeroArgFunction() { + override fun call(): LuaValue { + event.isCancelled = true + return LuaBoolean.valueOf(event.isCancelled) } } - - else -> LuaValue.NIL } + else -> LuaValue.NIL.also { + error("Cannot access or modify 'cancel' field in an uncancellable '${event.eventName}' event") + } + } + } + + else -> { + indexFunction?.call(table, key) ?: LuaValue.NIL.also { + error("No applicable index found: found '${key.tojstring()}'") } - else -> NIL } } - }) - } - return metaTable + + } + + }) + table.setmetatable(meta) + return table } + } \ No newline at end of file From 3524629bbb0415c84948b717e2cbdece87314536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Mon, 10 Mar 2025 22:46:01 -0500 Subject: [PATCH 04/26] A couple of small fixes --- .../kotlin/dev/znci/rocket/scripting/events/EventListener.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index b6027b7..ddfaf7e 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -139,7 +139,7 @@ object EventListener : Listener { "player" -> { val player: Player? = getValueFromEvent(event, "player", "getPlayer") if (player != null) { - return PlayerManager.getPlayerOverallTable(player) + return PlayerManager.getPlayerTable(player) } return LuaValue.NIL.also { error("No player in a '${event.eventName}' event!") @@ -177,9 +177,6 @@ object EventListener : Listener { } } - // FIXME: I may have broken the next two since I'm not sure how they work - // I'm just trying to make it sort of fit the method this uses - "from" -> { val location: Location? = getValueFromEvent(event, "from", "getFrom") return LuaLocation.fromBukkit(location?:return LuaValue.NIL.also { From fceb00b7f0084a8278d0ea54b0a513d3ccd8c204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Fri, 14 Mar 2025 00:44:29 -0400 Subject: [PATCH 05/26] No idea if this works, mainly just putting this onto GitHub --- .../dev/znci/rocket/scripting/events/EventListener.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index ddfaf7e..1f677ca 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -34,6 +34,7 @@ import org.luaj.vm2.LuaTable import org.luaj.vm2.LuaValue import org.luaj.vm2.lib.TwoArgFunction import org.luaj.vm2.lib.ZeroArgFunction +import java.util.* object EventListener : Listener { @@ -208,8 +209,16 @@ object EventListener : Listener { } else -> { + + val value: Any? = getValueFromEvent(event, key.tojstring(), + "get${ + key.tojstring() + .replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } + }") + if (value != null) return LuaValue.valueOf(value.toString()) + indexFunction?.call(table, key) ?: LuaValue.NIL.also { - error("No applicable index found: found '${key.tojstring()}'") + error("A '${event.eventName}' event has no member '${key.tojstring()}'") } } } From 902996f08b8374f86b337de796cc379391fa939b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Fri, 14 Mar 2025 19:10:20 +0100 Subject: [PATCH 06/26] Dynamic registry (expand for details) When first experimenting with this type of event handling, I found that there was an issue where every event was called regardless of whether it appeared in any scripts. This fixes this. Note that currently, disabling does not yet remove events from the handler, so that will be next --- src/main/kotlin/dev/znci/rocket/Rocket.kt | 10 ++- .../rocket/scripting/events/EventListener.kt | 68 ++++++++++++------- .../znci/rocket/scripting/functions/Events.kt | 6 ++ 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/Rocket.kt b/src/main/kotlin/dev/znci/rocket/Rocket.kt index e2ac822..24900a3 100644 --- a/src/main/kotlin/dev/znci/rocket/Rocket.kt +++ b/src/main/kotlin/dev/znci/rocket/Rocket.kt @@ -26,6 +26,8 @@ class Rocket : JavaPlugin() { private var defaultLocale: String = "en_GB" override fun onEnable() { + INSTANCE = this + // Create the plugin data folder saveDefaultConfig() @@ -53,10 +55,16 @@ class Rocket : JavaPlugin() { // Register all events logger.info("Rocket plugin enabled") - EventListener.registerAllEvents() + EventListener.cacheEvents() } override fun onDisable() { logger.info("Rocket plugin disabled") } + + companion object { + lateinit var INSTANCE: JavaPlugin + private set + } + } diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index 1f677ca..3f63bc4 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -35,37 +35,46 @@ import org.luaj.vm2.LuaValue import org.luaj.vm2.lib.TwoArgFunction import org.luaj.vm2.lib.ZeroArgFunction import java.util.* - +import kotlin.collections.HashSet object EventListener : Listener { private val plugin: Plugin? = Bukkit.getPluginManager().getPlugin("rocket") - fun registerAllEvents() { - val eventClasses = getSupportedEvents() - - plugin?.logger?.info("Found ${eventClasses.size} events") - for (eventClass in eventClasses) { - try { - if (plugin != null) { - plugin.logger.info("Registering event: ${eventClass.simpleName}") - Bukkit.getPluginManager().registerEvent( - eventClass, - this, - EventPriority.NORMAL, - { _, event -> - handleEvent(event) - }, - plugin - ) - } - } catch (e: Exception) { - e.printStackTrace() + // TODO: Add a cache of all currently loaded events, or modify the usedEvents to remove unused events + // Expected way of use: Map> + + lateinit var SUPPORTED_EVENTS: HashSet> + private set + + fun registerEvent(eventClass: Class) { + try { + if (plugin != null) { + plugin.logger.info("Registering event: ${eventClass.simpleName}") + Bukkit.getPluginManager().registerEvent( + eventClass, + this, + EventPriority.NORMAL, + { _, event -> + handleEvent(event) + }, + plugin + ) } + } catch (e: Exception) { + e.printStackTrace() } } + fun cacheEvents() { + SUPPORTED_EVENTS = getSupportedEvents() + } + private fun handleEvent(event: Event) { ScriptManager.usedEvents.forEach { (eventClass, callback) -> + // FIXME Remove debug + plugin!!.logger.info(ScriptManager.usedEvents.size.toString()) + plugin.logger.info(event.eventName) + plugin.logger.info("${eventClass.simpleName} a") if (eventClass.isInstance(event)) { val luaTable = convertEventToLua(event) println(callback) @@ -74,8 +83,15 @@ object EventListener : Listener { } } - private fun getSupportedEvents(): List> { - return getBukkitEventClasses() + private fun getSupportedEvents(): HashSet> { + val set = hashSetOf>() + for (eventClass in getBukkitEventClasses()) { + // TODO Add a debug setting to show these kinds of things + // (Similar to Skript's) + println("Caching event ${eventClass.simpleName}") + set.add(eventClass) + } + return set } @Suppress("UNCHECKED_CAST") @@ -93,7 +109,7 @@ object EventListener : Listener { } fun getEventByName(name: String): Class? { - return getSupportedEvents().find { it.simpleName.equals(name, true) } + return SUPPORTED_EVENTS.find { it.simpleName.equals(name, true) } } private inline fun getValueFromField(event: Event, valuesToTry: Array): V? { @@ -130,6 +146,10 @@ object EventListener : Listener { return valueObj } + /** + * Todo: Create a registry for extras, default to casting + */ + private fun convertEventToLua(event: Event): LuaTable { val table = LuaTable() val meta = table.getmetatable() ?: LuaTable() diff --git a/src/main/kotlin/dev/znci/rocket/scripting/functions/Events.kt b/src/main/kotlin/dev/znci/rocket/scripting/functions/Events.kt index 1d0ac0e..e87b370 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/functions/Events.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/functions/Events.kt @@ -15,6 +15,7 @@ */ package dev.znci.rocket.scripting.functions +import dev.znci.rocket.Rocket.Companion.INSTANCE import dev.znci.rocket.scripting.ScriptManager import dev.znci.rocket.scripting.events.EventListener import org.luaj.vm2.LuaTable @@ -27,8 +28,13 @@ class LuaEvents : LuaTable() { override fun call(eventName: LuaValue, callback: LuaValue): LuaValue { val eventClass = EventListener.getEventByName(eventName.tojstring()) + println(eventClass?.simpleName) + if (eventClass != null) { + if (!EventListener.SUPPORTED_EVENTS.contains(eventClass)) return LuaValue.NIL.also { println("Not contained") } + EventListener.registerEvent(eventClass) ScriptManager.usedEvents[eventClass] = callback.checkfunction() + INSTANCE.logger.info(ScriptManager.usedEvents.size.toString()) } return LuaValue.NIL From 9271572dfe576f3b20803e5d2300611b15fd2c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Sun, 16 Mar 2025 07:20:29 +0100 Subject: [PATCH 07/26] Move to a new system to *finally* give tracking to events and other functions (future) --- .../znci/rocket/scripting/ScriptManager.kt | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt index 04d1c1e..bb6edff 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt @@ -21,7 +21,7 @@ import org.bukkit.event.Event import java.io.File import org.luaj.vm2.Globals import org.luaj.vm2.LuaError -import org.luaj.vm2.LuaValue +import org.luaj.vm2.LuaFunction import org.luaj.vm2.lib.jse.JsePlatform import java.util.ArrayList @@ -29,7 +29,10 @@ object ScriptManager { var scriptsFolder: File = File("") val globals: Globals = JsePlatform.standardGlobals() - val usedEvents = mutableMapOf, LuaValue>() + val usedEvents = mutableMapOf, MutableList>() + val eventScript = mutableMapOf>() + val loadedScriptFiles = mutableMapOf>() + val enabledCommands = mutableMapOf() fun setFolder(folder: File) { @@ -66,19 +69,38 @@ object ScriptManager { } fun loadScript(scriptFile: File): String? { - val content = scriptFile.readText() - val result = runScript(content) + println("Reloading from file: '${scriptFile.absolutePath}'") + if (loadedScriptFiles[scriptFile.absolutePath] != null) { + disableFile(scriptFile) + } + val result = runScript(scriptFile) return result } - fun runScript(text: String): String? { + fun disableFile(scriptFile: File): String { + println("Unloading functions from file: '${scriptFile.absolutePath}'") + val functions = loadedScriptFiles[scriptFile.absolutePath]!! + for (function in functions) { + val eventClass = eventScript[function]!! + for (eventCallback in usedEvents[eventClass]?:continue) { + if (eventCallback == function) usedEvents.remove(eventClass) + } + eventScript.remove(function) + } + return "" + } + + fun runScript(scriptFile: File): String? { + + val content = scriptFile.readText() + try { globals.set("players", LuaPlayers()) globals.set("events", LuaEvents()) globals.set("commands", LuaCommands()) globals.set("http", LuaHTTPClient()) globals.set("location", LuaLocations()) - val scriptResult = globals.load(text, "script", globals) + val scriptResult = globals.load(content, "::${scriptFile.absolutePath}::", globals) scriptResult.call() } catch (error: LuaError) { From 4894ddefa190ec4ebd968d208ef542fa437fa153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Sun, 16 Mar 2025 07:23:57 +0100 Subject: [PATCH 08/26] Adjust LuaEvents to use new system --- .../znci/rocket/scripting/functions/Events.kt | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/functions/Events.kt b/src/main/kotlin/dev/znci/rocket/scripting/functions/Events.kt index e87b370..83a883c 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/functions/Events.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/functions/Events.kt @@ -18,6 +18,7 @@ package dev.znci.rocket.scripting.functions import dev.znci.rocket.Rocket.Companion.INSTANCE import dev.znci.rocket.scripting.ScriptManager import dev.znci.rocket.scripting.events.EventListener +import org.luaj.vm2.LuaFunction import org.luaj.vm2.LuaTable import org.luaj.vm2.LuaValue import org.luaj.vm2.lib.TwoArgFunction @@ -28,17 +29,53 @@ class LuaEvents : LuaTable() { override fun call(eventName: LuaValue, callback: LuaValue): LuaValue { val eventClass = EventListener.getEventByName(eventName.tojstring()) - println(eventClass?.simpleName) - if (eventClass != null) { if (!EventListener.SUPPORTED_EVENTS.contains(eventClass)) return LuaValue.NIL.also { println("Not contained") } - EventListener.registerEvent(eventClass) - ScriptManager.usedEvents[eventClass] = callback.checkfunction() - INSTANCE.logger.info(ScriptManager.usedEvents.size.toString()) + + if (ScriptManager.usedEvents[eventClass] == null) EventListener.registerEvent(eventClass) + + // Cache all information about the loaded script + // Ensures that we can retrieve the relevant information when dealing with unloading + + if (ScriptManager.usedEvents[eventClass] == null) { + ScriptManager.usedEvents[eventClass] = mutableListOf() + } + val function = callback.checkfunction() + ScriptManager.usedEvents[eventClass]!!.add(function) + + ScriptManager.eventScript[function] = eventClass + + val fileName = getFileNameFromLuaFunction(function) + + println(fileName) + + if (ScriptManager.loadedScriptFiles[fileName] == null) { + println("not set yet") + ScriptManager.loadedScriptFiles[fileName] = mutableListOf() + } + println("adding") + ScriptManager.loadedScriptFiles[fileName]!!.add(function) } return LuaValue.NIL } }) } + + /** + * Scuffed stuff, let's find a better way if we can + * @see ScriptManager.runScript + */ + + private fun getFileNameFromLuaFunction(function: LuaFunction?): String { + var fileName = "" + var previousChar: Char? = null + var record = false + for (char in function.toString()) { + if ((previousChar ?: ' ') == ':' && char == ':') if (record == false) record = true else break + if (record) fileName = "$fileName$char" + previousChar = char + } + return fileName.subSequence(1, fileName.length-1).toString() + } } \ No newline at end of file From 2c98a1c9918a6ffe962a4f70a19f9327d33a6b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Sun, 16 Mar 2025 07:24:52 +0100 Subject: [PATCH 09/26] Adjust EventListener to use new system --- .../znci/rocket/scripting/events/EventListener.kt | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index 3f63bc4..aa4f3a8 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -70,16 +70,11 @@ object EventListener : Listener { } private fun handleEvent(event: Event) { - ScriptManager.usedEvents.forEach { (eventClass, callback) -> - // FIXME Remove debug - plugin!!.logger.info(ScriptManager.usedEvents.size.toString()) - plugin.logger.info(event.eventName) - plugin.logger.info("${eventClass.simpleName} a") - if (eventClass.isInstance(event)) { - val luaTable = convertEventToLua(event) - println(callback) - callback.call(luaTable) - } + val eventCallbacks = ScriptManager.usedEvents[getEventByName(event.eventName)] ?: return + eventCallbacks.forEach { callback -> + val luaTable = convertEventToLua(event) + callback.call(luaTable) + println(callback) } } From ddc17e6af234ca672e0840002912cafa20dd5d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Sun, 16 Mar 2025 07:25:46 +0100 Subject: [PATCH 10/26] Make the disable subcommand work --- src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt b/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt index a17b2d8..53b82e2 100644 --- a/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt +++ b/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt @@ -17,6 +17,7 @@ package dev.znci.rocket.commands import dev.znci.rocket.i18n.LocaleManager import dev.znci.rocket.scripting.ScriptManager +import dev.znci.rocket.scripting.ScriptManager.disableFile import dev.znci.rocket.scripting.ScriptManager.scriptsFolder import org.bukkit.command.Command import org.bukkit.command.CommandSender @@ -86,6 +87,11 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { return true } + // TODO: Add disabling of file (with '-') + // For another PR though + + disableFile(scriptFile) + sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.script_disabled", scriptName)) } else -> { From 2448a5e2f0715e919214ebf14c5f678735404d2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Sun, 16 Mar 2025 07:25:59 +0100 Subject: [PATCH 11/26] Fix config reloading (maybe) --- .../kotlin/dev/znci/rocket/commands/RocketCommand.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt b/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt index 53b82e2..06217d6 100644 --- a/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt +++ b/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt @@ -33,7 +33,8 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { } val action = args[0].lowercase() - val scriptName = if (!args[1].endsWith(".lua")) "${args[1]}.lua" else args[1] + val rawScriptName = args[1] + val scriptName = if (!rawScriptName.endsWith(".lua")) "${rawScriptName}.lua" else rawScriptName if (!scriptsFolder.exists() || !scriptsFolder.isDirectory) { sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.scripts_folder_not_found")) @@ -42,7 +43,7 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { when (action) { "reload" -> { - if (scriptName.lowercase() == "config") { + if (rawScriptName.lowercase() == "config") { plugin.reloadConfig() val defaultLocale = plugin.config.getString("locale", "en_GB").toString() @@ -52,16 +53,18 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.config_reloaded")) return true - } else if (scriptName.lowercase() == "all") { + } else if (rawScriptName.lowercase() == "all") { val results = ScriptManager.loadAll() if (results.isNotEmpty()) { results.forEach { error -> sender.sendMessage(LocaleManager.getMessageAsComponent("generic_error", error ?: "Unknown error")) } } + return true } val scriptFile = File(scriptsFolder, scriptName) + if (!scriptFile.exists()) { sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.script_not_found", scriptName)) return true From e681fd0b7a56e42ee6d339cd94f4501408472dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Sun, 16 Mar 2025 07:26:56 +0100 Subject: [PATCH 12/26] Very rudimentary debug system (see details) Someone should work on this in the future, I'll try to remember to make an issue for it --- .../dev/znci/rocket/scripting/events/EventListener.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index aa4f3a8..8dc822e 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -37,6 +37,8 @@ import org.luaj.vm2.lib.ZeroArgFunction import java.util.* import kotlin.collections.HashSet +const val DEBUG = true + object EventListener : Listener { private val plugin: Plugin? = Bukkit.getPluginManager().getPlugin("rocket") @@ -49,7 +51,9 @@ object EventListener : Listener { fun registerEvent(eventClass: Class) { try { if (plugin != null) { - plugin.logger.info("Registering event: ${eventClass.simpleName}") + + if (DEBUG) plugin.logger.info("Registering event: ${eventClass.simpleName}") + Bukkit.getPluginManager().registerEvent( eventClass, this, @@ -83,7 +87,7 @@ object EventListener : Listener { for (eventClass in getBukkitEventClasses()) { // TODO Add a debug setting to show these kinds of things // (Similar to Skript's) - println("Caching event ${eventClass.simpleName}") + if (DEBUG) println("Caching event ${eventClass.simpleName}") set.add(eventClass) } return set From 5880019d0fccfdbf83cbc481ae3ea8c37094eb5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Sun, 16 Mar 2025 07:28:08 +0100 Subject: [PATCH 13/26] Remove todo because it's added (yay!) --- .../kotlin/dev/znci/rocket/scripting/events/EventListener.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index 8dc822e..9ebb1b0 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -42,9 +42,6 @@ const val DEBUG = true object EventListener : Listener { private val plugin: Plugin? = Bukkit.getPluginManager().getPlugin("rocket") - // TODO: Add a cache of all currently loaded events, or modify the usedEvents to remove unused events - // Expected way of use: Map> - lateinit var SUPPORTED_EVENTS: HashSet> private set From 405274e9f770cebe7c846e9bc4c7a528cdaa42e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Sun, 16 Mar 2025 07:29:05 +0100 Subject: [PATCH 14/26] Adjust TODO message --- .../kotlin/dev/znci/rocket/scripting/events/EventListener.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index 9ebb1b0..60497a1 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -144,6 +144,7 @@ object EventListener : Listener { /** * Todo: Create a registry for extras, default to casting + * Maybe for a different PR, it depends on what znci is feeling */ private fun convertEventToLua(event: Event): LuaTable { From f05586370d3aeb4c0402ae862340f381de367dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Sun, 16 Mar 2025 16:16:19 +0100 Subject: [PATCH 15/26] Not sure what happened here --- .../kotlin/dev/znci/rocket/commands/RocketCommand.kt | 1 - .../kotlin/dev/znci/rocket/scripting/ScriptManager.kt | 9 ++++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt b/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt index 20a0e69..3c24a0e 100644 --- a/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt +++ b/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt @@ -44,7 +44,6 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { when (action) { "reload" -> { if (rawScriptName.lowercase() == "config") { - plugin.reloadConfig() val defaultLocale = plugin.config.getString("locale", "en_GB").toString() diff --git a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt index 1e92604..affe3c0 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt @@ -26,21 +26,20 @@ import org.luaj.vm2.lib.jse.JsePlatform import java.util.ArrayList object ScriptManager { - private val globals: Globals = JsePlatform.standardGlobals() + var scriptsFolder: File = File("") + val globals: Globals = JsePlatform.standardGlobals() val loadedScriptFiles = mutableMapOf>() - + val usedEvents = mutableMapOf, MutableList>() val eventScript = mutableMapOf>() - + val enabledCommands = mutableMapOf() - @Suppress("unused") // TODO: Will be used in the future when custom configuration folders are implemented fun setFolder(folder: File) { scriptsFolder = folder } - @Suppress("unused") // TODO: Is this still required? fun loadScripts() { scriptsFolder.walkTopDown().forEach { file -> if (file.isFile && !file.startsWith("-")) { From 2ae331600b61b14d3d0e9beaff621fe4510d68b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Tue, 18 Mar 2025 21:22:36 +0100 Subject: [PATCH 16/26] Revert "Very rudimentary debug system (see details)" This reverts commit e681fd0b7a56e42ee6d339cd94f4501408472dd3. --- .../dev/znci/rocket/scripting/events/EventListener.kt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index 8c08a34..9867cf2 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -37,8 +37,6 @@ import org.luaj.vm2.lib.ZeroArgFunction import java.util.* import kotlin.collections.HashSet -const val DEBUG = true - object EventListener : Listener { private val plugin: Plugin? = Bukkit.getPluginManager().getPlugin("rocket") @@ -48,9 +46,7 @@ object EventListener : Listener { fun registerEvent(eventClass: Class) { try { if (plugin != null) { - - if (DEBUG) plugin.logger.info("Registering event: ${eventClass.simpleName}") - + plugin.logger.info("Registering event: ${eventClass.simpleName}") Bukkit.getPluginManager().registerEvent( eventClass, this, @@ -84,7 +80,7 @@ object EventListener : Listener { for (eventClass in getBukkitEventClasses()) { // TODO Add a debug setting to show these kinds of things // (Similar to Skript's) - if (DEBUG) println("Caching event ${eventClass.simpleName}") + println("Caching event ${eventClass.simpleName}") set.add(eventClass) } return set From bbce335a76d1c211a07ebc82a51bf1773bb34340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Tue, 18 Mar 2025 21:25:08 +0100 Subject: [PATCH 17/26] Remove unnecessary debugs --- src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt index affe3c0..cff6645 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt @@ -44,8 +44,6 @@ object ScriptManager { scriptsFolder.walkTopDown().forEach { file -> if (file.isFile && !file.startsWith("-")) { val content = file.readText() - - println(content) } } } @@ -70,7 +68,6 @@ object ScriptManager { } fun loadScript(scriptFile: File): String? { - println("Reloading from file: '${scriptFile.absolutePath}'") if (loadedScriptFiles[scriptFile.absolutePath] != null) { disableFile(scriptFile) } @@ -79,7 +76,6 @@ object ScriptManager { } fun disableFile(scriptFile: File): String { - println("Unloading functions from file: '${scriptFile.absolutePath}'") val functions = loadedScriptFiles[scriptFile.absolutePath]!! for (function in functions) { val eventClass = eventScript[function]!! From dc9e582e05547c13c8b1f3d73120d042f996ef11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Thu, 20 Mar 2025 05:45:49 +0100 Subject: [PATCH 18/26] Use the spread operator ya dingus --- .../dev/znci/rocket/scripting/events/EventListener.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index 9867cf2..f3629b7 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -104,7 +104,7 @@ object EventListener : Listener { return SUPPORTED_EVENTS.find { it.simpleName.equals(name, true) } } - private inline fun getValueFromField(event: Event, valuesToTry: Array): V? { + private inline fun getValueFromField(event: Event, vararg valuesToTry: String): V? { valuesToTry.forEach { value -> val field = event.javaClass.declaredFields.find { it.name == value } if (field != null) { @@ -118,7 +118,7 @@ object EventListener : Listener { return null } - private inline fun getValueFromFunction(event: Event, valuesToTry: Array): V? { + private inline fun getValueFromFunction(event: Event, vararg valuesToTry: String): V? { valuesToTry.forEach { value -> val valueProperty = event.javaClass.methods.find { it.name == value } if (valueProperty != null) { @@ -131,9 +131,9 @@ object EventListener : Listener { private inline fun getValueFromEvent(event: Event, vararg valuesToTry: String): V? { - var valueObj: V? = getValueFromField(event, valuesToTry) + var valueObj: V? = getValueFromField(event, *valuesToTry) if (valueObj == null) { - valueObj = getValueFromFunction(event, valuesToTry) + valueObj = getValueFromFunction(event, *valuesToTry) } return valueObj } From ce85a90d96dcbe3757ba67bb1ecc84203e4bb8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Tue, 8 Apr 2025 16:15:16 -0400 Subject: [PATCH 19/26] Finish fixing conflicts --- .../znci/rocket/scripting/ScriptManager.kt | 30 ++++++++++++------- .../rocket/scripting/events/EventListener.kt | 2 +- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt index dabd95c..e209f63 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt @@ -22,11 +22,8 @@ import dev.znci.rocket.scripting.api.RocketTable import dev.znci.rocket.scripting.api.RocketValueBase import dev.znci.rocket.scripting.classes.Command import org.bukkit.event.Event +import org.luaj.vm2.* import java.io.File -import org.luaj.vm2.Globals -import org.luaj.vm2.LuaError -import org.luaj.vm2.LuaTable -import org.luaj.vm2.LuaValue import org.luaj.vm2.lib.jse.JsePlatform import java.util.ArrayList @@ -53,11 +50,22 @@ object ScriptManager { */ var scriptsFolder: File = File("") + /** + * A map of loaded scripts associated by file path + */ + val loadedScriptFiles = mutableMapOf>() + + /** + * A map associating Lua event sections with a class. + * This mainly helps with disabling scripts + */ + val eventScript = mutableMapOf>() + /** * A map of events and their associated Lua handlers. * It stores the events triggered in the system and the corresponding Lua functions that handle them. */ - val usedEvents = mutableMapOf, LuaValue>() + val usedEvents = mutableMapOf, MutableList>() /** * A map of enabled commands by their names. @@ -108,11 +116,14 @@ object ScriptManager { /** * Recursively loads all scripts located in the scripts folder + * @return A list of error messages where execution failed. The list will be empty if there were no errors */ fun loadAll(): List { val results = mutableListOf() getAllScripts(false).forEach { script -> - results.add(loadScript(File("plugins/rocket/scripts/", script))) + val result = loadScript(File("plugins/rocket/scripts/", script)) + if (result != "") + results.add(result) } return results } @@ -121,8 +132,7 @@ object ScriptManager { * Loads a script based off of a [File] object * * @param scriptFile The script to load - * @return a string if there's been an error - * @return null if this method succeeds + * @return An error message if execution fails, or an empty string if the script ran successfully. */ fun loadScript(scriptFile: File): String? { if (loadedScriptFiles[scriptFile.absolutePath] != null) { @@ -154,13 +164,13 @@ object ScriptManager { * @param scriptFile The Lua script content to execute. * @return An error message if execution fails, or an empty string if the script ran successfully. */ - fun runScript(scriptFile: String): String? { + fun runScript(scriptFile: File): String? { val content = scriptFile.readText() try { applyGlobals(globals) - val scriptResult = globals.load(scriptFile, "::${scriptFile.absolutePath}::", globals) + val scriptResult = globals.load(content, "::${scriptFile.absolutePath}::", globals) scriptResult.call() } catch (error: LuaError) { diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index f3629b7..0e56e48 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -18,7 +18,7 @@ package dev.znci.rocket.scripting.events import com.google.common.reflect.ClassPath import dev.znci.rocket.scripting.PlayerManager import dev.znci.rocket.scripting.ScriptManager -import dev.znci.rocket.scripting.functions.LuaLocation +import dev.znci.rocket.scripting.globals.tables.LuaLocation import net.kyori.adventure.text.Component import org.bukkit.Bukkit import org.bukkit.Location From 00525cedecad050955b698e243c1b21fe105f022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Tue, 8 Apr 2025 16:34:10 -0400 Subject: [PATCH 20/26] Minor fixes to use Rocket API --- .../kotlin/dev/znci/rocket/scripting/events/EventListener.kt | 5 +++-- .../dev/znci/rocket/scripting/globals/tables/Events.kt | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index 0e56e48..b09be99 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -18,6 +18,7 @@ package dev.znci.rocket.scripting.events import com.google.common.reflect.ClassPath import dev.znci.rocket.scripting.PlayerManager import dev.znci.rocket.scripting.ScriptManager +import dev.znci.rocket.scripting.api.RocketTable import dev.znci.rocket.scripting.globals.tables.LuaLocation import net.kyori.adventure.text.Component import org.bukkit.Bukkit @@ -143,8 +144,8 @@ object EventListener : Listener { * Maybe for a different PR, it depends on what znci is feeling */ - private fun convertEventToLua(event: Event): LuaTable { - val table = LuaTable() + private fun convertEventToLua(event: Event): RocketTable { + val table = RocketTable("luaEvent") val meta = table.getmetatable() ?: LuaTable() val indexFunction = meta.get("__index") as? TwoArgFunction meta.set("__index", object : TwoArgFunction() { diff --git a/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt b/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt index acdb598..78af43f 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt @@ -47,13 +47,9 @@ class LuaEvents : LuaTable() { val fileName = getFileNameFromLuaFunction(function) - println(fileName) - if (ScriptManager.loadedScriptFiles[fileName] == null) { - println("not set yet") ScriptManager.loadedScriptFiles[fileName] = mutableListOf() } - println("adding") ScriptManager.loadedScriptFiles[fileName]!!.add(function) } From 3ef5d79f7242d350bda01e08a18acdce6db963ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Thu, 10 Apr 2025 11:48:25 -0400 Subject: [PATCH 21/26] Qodana warnings --- .../kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt b/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt index 78af43f..5bbc3f8 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt @@ -68,7 +68,7 @@ class LuaEvents : LuaTable() { var previousChar: Char? = null var record = false for (char in function.toString()) { - if ((previousChar ?: ' ') == ':' && char == ':') if (record == false) record = true else break + if ((previousChar ?: ' ') == ':' && char == ':') if (!record) record = true else break if (record) fileName = "$fileName$char" previousChar = char } From fd51bb87c089158ae28614211711b373095640a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Thu, 10 Apr 2025 12:03:01 -0400 Subject: [PATCH 22/26] Switch scriptName variables --- .../dev/znci/rocket/commands/RocketCommand.kt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt b/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt index 3c24a0e..d087612 100644 --- a/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt +++ b/src/main/kotlin/dev/znci/rocket/commands/RocketCommand.kt @@ -33,8 +33,8 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { } val action = args[0].lowercase() - val rawScriptName = args[1] - val scriptName = if (!rawScriptName.endsWith(".lua")) "${rawScriptName}.lua" else rawScriptName + val scriptName = args[1] + val rawScriptName = if (!scriptName.endsWith(".lua")) "${scriptName}.lua" else scriptName if (!scriptsFolder.exists() || !scriptsFolder.isDirectory) { sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.scripts_folder_not_found")) @@ -43,7 +43,7 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { when (action) { "reload" -> { - if (rawScriptName.lowercase() == "config") { + if (scriptName.lowercase() == "config") { plugin.reloadConfig() val defaultLocale = plugin.config.getString("locale", "en_GB").toString() @@ -53,7 +53,7 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.config_reloaded")) return true - } else if (rawScriptName.lowercase() == "all") { + } else if (scriptName.lowercase() == "all") { val results = ScriptManager.loadAll() if (results.isNotEmpty()) { results.forEach { error -> @@ -63,10 +63,10 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { return true } - val scriptFile = File(scriptsFolder, scriptName) + val scriptFile = File(scriptsFolder, rawScriptName) if (!scriptFile.exists()) { - sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.script_not_found", scriptName)) + sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.script_not_found", rawScriptName)) return true } @@ -78,15 +78,15 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { sender.sendMessage( LocaleManager.getMessageAsComponent( "rocket_command.script_reloaded", - scriptName + rawScriptName ) ) } } "disable" -> { - val scriptFile = File(scriptsFolder, scriptName) + val scriptFile = File(scriptsFolder, rawScriptName) if (!scriptFile.exists()) { - sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.script_not_found", scriptName)) + sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.script_not_found", rawScriptName)) return true } @@ -95,7 +95,7 @@ class RocketCommand(private val plugin: JavaPlugin) : TabExecutor { disableFile(scriptFile) - sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.script_disabled", scriptName)) + sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.script_disabled", rawScriptName)) } else -> { sender.sendMessage(LocaleManager.getMessageAsComponent("rocket_command.usage")) From a5b8f83b56ba7ff137345f910be3667deebb0ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Thu, 10 Apr 2025 12:04:25 -0400 Subject: [PATCH 23/26] Remove unused INSTANCE variable --- src/main/kotlin/dev/znci/rocket/Rocket.kt | 7 ------- .../dev/znci/rocket/scripting/globals/tables/Events.kt | 1 - 2 files changed, 8 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/Rocket.kt b/src/main/kotlin/dev/znci/rocket/Rocket.kt index 824b548..622f5cb 100644 --- a/src/main/kotlin/dev/znci/rocket/Rocket.kt +++ b/src/main/kotlin/dev/znci/rocket/Rocket.kt @@ -27,8 +27,6 @@ class Rocket : JavaPlugin() { private var defaultLocale: String = "en_GB" override fun onEnable() { - INSTANCE = this - // Create the plugin data folder saveDefaultConfig() @@ -73,9 +71,4 @@ class Rocket : JavaPlugin() { logger.info("Rocket plugin disabled") } - companion object { - lateinit var INSTANCE: JavaPlugin - private set - } - } diff --git a/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt b/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt index 5bbc3f8..a84f37b 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt @@ -15,7 +15,6 @@ */ package dev.znci.rocket.scripting.globals.tables -import dev.znci.rocket.Rocket.Companion.INSTANCE import dev.znci.rocket.scripting.ScriptManager import dev.znci.rocket.scripting.events.EventListener import org.luaj.vm2.LuaFunction From b7e18eb5885069f0360adcc9b5ed8d02ce2a15b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Tue, 13 May 2025 02:58:51 +0200 Subject: [PATCH 24/26] Twine --- .../kotlin/dev/znci/rocket/scripting/events/EventListener.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index bf8dde8..8f0d9de 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -21,6 +21,7 @@ import dev.znci.rocket.scripting.ScriptManager import dev.znci.rocket.scripting.api.RocketTable import dev.znci.rocket.scripting.globals.tables.LuaLocation import dev.znci.rocket.scripting.globals.tables.LuaPlayer +import dev.znci.twine.TwineTable import net.kyori.adventure.text.Component import org.bukkit.Bukkit import org.bukkit.Location @@ -145,8 +146,8 @@ object EventListener : Listener { * Maybe for a different PR, it depends on what znci is feeling */ - private fun convertEventToLua(event: Event): RocketTable { - val table = RocketTable("luaEvent") + private fun convertEventToLua(event: Event): TwineTable { + val table = TwineTable("luaEvent") val meta = table.getmetatable() ?: LuaTable() val indexFunction = meta.get("__index") as? TwoArgFunction meta.set("__index", object : TwoArgFunction() { From 3774d6db2fb5ce64f5d095f465cd061fffd8046d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Tue, 13 May 2025 02:59:30 +0200 Subject: [PATCH 25/26] Removed invalid imports --- .../kotlin/dev/znci/rocket/scripting/events/EventListener.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index 8f0d9de..5be6880 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -16,9 +16,7 @@ package dev.znci.rocket.scripting.events import com.google.common.reflect.ClassPath -import dev.znci.rocket.scripting.PlayerManager import dev.znci.rocket.scripting.ScriptManager -import dev.znci.rocket.scripting.api.RocketTable import dev.znci.rocket.scripting.globals.tables.LuaLocation import dev.znci.rocket.scripting.globals.tables.LuaPlayer import dev.znci.twine.TwineTable @@ -32,13 +30,11 @@ import org.bukkit.event.EventPriority import org.bukkit.event.Listener import org.bukkit.inventory.EquipmentSlot import org.bukkit.plugin.Plugin -import org.luaj.vm2.LuaBoolean import org.luaj.vm2.LuaTable import org.luaj.vm2.LuaValue import org.luaj.vm2.lib.TwoArgFunction import org.luaj.vm2.lib.ZeroArgFunction import java.util.* -import kotlin.collections.HashSet object EventListener : Listener { private val plugin: Plugin? = Bukkit.getPluginManager().getPlugin("rocket") From 0b0321336a24ed753051b0786bfa73751a009088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lex=C3=AE=20Nuutra=C3=AE?= Date: Fri, 30 May 2025 05:04:45 +0200 Subject: [PATCH 26/26] Begin switch to Twine --- .../znci/rocket/scripting/ScriptManager.kt | 9 +- .../rocket/scripting/events/EventListener.kt | 2 +- .../rocket/scripting/globals/tables/Events.kt | 82 +++++++++++++------ 3 files changed, 62 insertions(+), 31 deletions(-) diff --git a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt index 7fb46bf..81b9410 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/ScriptManager.kt @@ -49,19 +49,19 @@ object ScriptManager { /** * A map of loaded scripts associated by file path */ - val loadedScriptFiles = mutableMapOf>() + val loadedScriptFiles = mutableMapOf>>() /** * A map associating Lua event sections with a class. * This mainly helps with disabling scripts */ - val eventScript = mutableMapOf>() + val eventScript = mutableMapOf, Class>() /** * A map of events and their associated Lua handlers. * It stores the events triggered in the system and the corresponding Lua functions that handle them. */ - val usedEvents = mutableMapOf, MutableList>() + val usedEvents = mutableMapOf, MutableList>>() /** * A map of enabled commands by their names. @@ -92,8 +92,7 @@ object ScriptManager { fun loadScripts() { scriptsFolder.walkTopDown().forEach { file -> if (file.isFile && !file.startsWith("-")) { - val content = file.readText() - runScript(content) + runScript(file) } } } diff --git a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt index 5be6880..2db75aa 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/events/EventListener.kt @@ -69,7 +69,7 @@ object EventListener : Listener { val eventCallbacks = ScriptManager.usedEvents[getEventByName(event.eventName)] ?: return eventCallbacks.forEach { callback -> val luaTable = convertEventToLua(event) - callback.call(luaTable) + callback(luaTable) println(callback) } } diff --git a/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt b/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt index a84f37b..90b8850 100644 --- a/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt +++ b/src/main/kotlin/dev/znci/rocket/scripting/globals/tables/Events.kt @@ -17,52 +17,84 @@ package dev.znci.rocket.scripting.globals.tables import dev.znci.rocket.scripting.ScriptManager import dev.znci.rocket.scripting.events.EventListener +import dev.znci.twine.TwineNative +import dev.znci.twine.TwineTable +import dev.znci.twine.annotations.TwineNativeFunction import org.luaj.vm2.LuaFunction import org.luaj.vm2.LuaTable import org.luaj.vm2.LuaValue import org.luaj.vm2.lib.TwoArgFunction -class LuaEvents : LuaTable() { - init { - set("on", object : TwoArgFunction() { - override fun call(eventName: LuaValue, callback: LuaValue): LuaValue { - val eventClass = EventListener.getEventByName(eventName.tojstring()) +class LuaEvents : TwineNative("event") { - if (eventClass != null) { - if (!EventListener.SUPPORTED_EVENTS.contains(eventClass)) return LuaValue.NIL.also { println("Not contained") } + @TwineNativeFunction("on") + fun registerEvent(eventName: String, callback: (TwineTable) -> Unit) { + val eventClass = EventListener.getEventByName(eventName) - if (ScriptManager.usedEvents[eventClass] == null) EventListener.registerEvent(eventClass) + if (eventClass != null) { + if (!EventListener.SUPPORTED_EVENTS.contains(eventClass)) return - // Cache all information about the loaded script - // Ensures that we can retrieve the relevant information when dealing with unloading + if (ScriptManager.usedEvents[eventClass] == null) EventListener.registerEvent(eventClass) - if (ScriptManager.usedEvents[eventClass] == null) { - ScriptManager.usedEvents[eventClass] = mutableListOf() - } - val function = callback.checkfunction() - ScriptManager.usedEvents[eventClass]!!.add(function) + // Cache all information about the loaded script + // Ensures that we can retrieve the relevant information when dealing with unloading - ScriptManager.eventScript[function] = eventClass + if (ScriptManager.usedEvents[eventClass] == null) { + ScriptManager.usedEvents[eventClass] = mutableListOf() + } + ScriptManager.usedEvents[eventClass]!!.add(callback) - val fileName = getFileNameFromLuaFunction(function) + ScriptManager.eventScript[callback] = eventClass - if (ScriptManager.loadedScriptFiles[fileName] == null) { - ScriptManager.loadedScriptFiles[fileName] = mutableListOf() - } - ScriptManager.loadedScriptFiles[fileName]!!.add(function) - } + val fileName = getFileNameFromLuaFunction(callback) - return NIL + if (ScriptManager.loadedScriptFiles[fileName] == null) { + ScriptManager.loadedScriptFiles[fileName] = mutableListOf() } - }) + ScriptManager.loadedScriptFiles[fileName]!!.add(callback) + } } +// init { +// set("on", object : TwoArgFunction() { +// override fun call(eventName: LuaValue, callback: LuaValue): LuaValue { +// val eventClass = EventListener.getEventByName(eventName.tojstring()) +// +// if (eventClass != null) { +// if (!EventListener.SUPPORTED_EVENTS.contains(eventClass)) return LuaValue.NIL.also { println("Not contained") } +// +// if (ScriptManager.usedEvents[eventClass] == null) EventListener.registerEvent(eventClass) +// +// // Cache all information about the loaded script +// // Ensures that we can retrieve the relevant information when dealing with unloading +// +// if (ScriptManager.usedEvents[eventClass] == null) { +// ScriptManager.usedEvents[eventClass] = mutableListOf() +// } +// val function = callback.checkfunction() +// ScriptManager.usedEvents[eventClass]!!.add(function) +// +// ScriptManager.eventScript[function] = eventClass +// +// val fileName = getFileNameFromLuaFunction(function) +// +// if (ScriptManager.loadedScriptFiles[fileName] == null) { +// ScriptManager.loadedScriptFiles[fileName] = mutableListOf() +// } +// ScriptManager.loadedScriptFiles[fileName]!!.add(function) +// } +// +// return NIL +// } +// }) +// } + /** * Scuffed stuff, let's find a better way if we can * @see ScriptManager.runScript */ - private fun getFileNameFromLuaFunction(function: LuaFunction?): String { + private fun getFileNameFromLuaFunction(function: Function1?): String { var fileName = "" var previousChar: Char? = null var record = false