From ad120cccba5e982b19c81e53d6b79183bf3b6724 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Mon, 16 Dec 2024 20:17:55 +0700 Subject: [PATCH] Implement invokeGlobal and eval --- .../dbotthepony/kstarbound/lua/LuaThread.kt | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaThread.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaThread.kt index 2a21511f..07a09f1b 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaThread.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaThread.kt @@ -18,6 +18,7 @@ import org.lwjgl.system.MemoryStack import org.lwjgl.system.MemoryUtil import ru.dbotthepony.kommons.gson.set import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.KOptional import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.defs.AssetPath import ru.dbotthepony.kstarbound.json.InternedJsonElementAdapter @@ -213,6 +214,73 @@ class LuaThread private constructor( return status } + /** + * Returns boolean indicating whenever function exists + */ + inline fun invokeGlobal(name: String, arguments: LuaThread.() -> Int): Boolean { + val top = stackTop + + try { + val type = loadGlobal(name) + if (type != LuaType.FUNCTION) + return false + + val numArguments = arguments(this) + check(numArguments >= 0) { "Invalid amount of arguments provided to Lua function" } + call(numArguments) + return true + } finally { + setTop(top) + } + } + + /** + * Returns empty [KOptional] if function does not exist + */ + inline fun invokeGlobal(name: String, numResults: Int, arguments: LuaThread.() -> Int, results: LuaThread.(firstValue: Int) -> T): KOptional { + require(numResults > 0) { "Invalid amount of results: $numResults" } + val top = stackTop + + try { + val type = loadGlobal(name) + if (type != LuaType.FUNCTION) + return KOptional() + + val numArguments = arguments(this) + call(numArguments, numResults) + return KOptional(results(this, top + 1)) + } finally { + setTop(top) + } + } + + inline fun eval(chunk: String, name: String = "eval", numResults: Int, arguments: LuaThread.() -> Int, results: LuaThread.(firstValue: Int) -> T): T { + require(numResults > 0) { "Invalid amount of results: $numResults" } + + val top = stackTop + + try { + val numArguments = arguments(this) + load(chunk, name) + call(numArguments, numResults) + return results(this, top + 1) + } finally { + setTop(top) + } + } + + inline fun eval(chunk: String, name: String = "eval", arguments: LuaThread.() -> Int) { + val top = stackTop + + try { + val numArguments = arguments(this) + load(chunk, name) + call(numArguments, 0) + } finally { + setTop(top) + } + } + private val attachedScripts = ArrayList() private var initCalled = false @@ -1122,7 +1190,7 @@ class LuaThread private constructor( } companion object { - private val LOGGER = LogManager.getLogger() + val LOGGER = LogManager.getLogger() fun loadInternalScript(name: String): String { return LuaThread::class.java.getResourceAsStream("/scripts/$name.lua")?.readAllBytes()?.toString(Charsets.UTF_8) ?: throw RuntimeException("/scripts/$name.lua is missing!")