80 lines
1.9 KiB
Kotlin
80 lines
1.9 KiB
Kotlin
package ru.dbotthepony.kstarbound.lua
|
|
|
|
import com.google.gson.JsonArray
|
|
import com.google.gson.JsonElement
|
|
import org.apache.logging.log4j.LogManager
|
|
import ru.dbotthepony.kstarbound.util.ActionPacer
|
|
import ru.dbotthepony.kstarbound.util.sbIntern
|
|
|
|
class LuaMessageHandlerComponent(val lua: LuaThread, val nameProvider: () -> String) {
|
|
private val handlers = HashMap<String, LuaHandle>()
|
|
|
|
private fun setHandler(args: LuaThread.ArgStack): Int {
|
|
val name = args.nextString()
|
|
val peek = args.peek()
|
|
|
|
if (peek.isNothing) {
|
|
handlers.remove(name)?.close()
|
|
} else if (peek == LuaType.FUNCTION) {
|
|
args.lua.dup(2)
|
|
val handle = args.lua.createHandle()
|
|
handlers.put(name.sbIntern(), handle)?.close()
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
init {
|
|
lua.pushTable()
|
|
lua.dup()
|
|
lua.storeGlobal("message")
|
|
lua.setTableValue("setHandler", ::setHandler)
|
|
lua.pop()
|
|
}
|
|
|
|
val logPacer = ActionPacer(1, 5)
|
|
|
|
fun lookupHandler(name: String): LuaHandle? {
|
|
return handlers[name]
|
|
}
|
|
|
|
inline fun handle(message: String, isLocal: Boolean, arguments: LuaThread.() -> Int): JsonElement? {
|
|
val handler = lookupHandler(message) ?: return null
|
|
val top = lua.stackTop
|
|
|
|
try {
|
|
lua.push(handler)
|
|
lua.push(isLocal)
|
|
val amountOfArguments = arguments(lua)
|
|
check(amountOfArguments >= 0) { "Invalid amount of arguments to pass to Lua handler: $amountOfArguments" }
|
|
|
|
lua.call(amountOfArguments + 1, 1)
|
|
|
|
return lua.getJson()
|
|
} catch (err: Throwable) {
|
|
if (logPacer.consumeAndReturnDeadline() <= 0L)
|
|
LOGGER.error("${nameProvider.invoke()}: Exception while handling message '$message'", err)
|
|
|
|
throw err
|
|
} finally {
|
|
lua.setTop(top)
|
|
}
|
|
}
|
|
|
|
fun handle(message: String, isLocal: Boolean, arguments: JsonArray): JsonElement? {
|
|
return handle(message, isLocal) {
|
|
ensureExtraCapacity(arguments.size() + 4)
|
|
|
|
for (argument in arguments) {
|
|
push(argument)
|
|
}
|
|
|
|
arguments.size()
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
val LOGGER = LogManager.getLogger()
|
|
}
|
|
}
|