KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaMessageHandler.kt

73 lines
1.8 KiB
Kotlin

package ru.dbotthepony.kstarbound.lua
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonNull
import org.apache.logging.log4j.LogManager
import org.classdump.luna.ByteString
import org.classdump.luna.exec.CallPausedException
import org.classdump.luna.runtime.LuaFunction
class LuaMessageHandler(val lua: LuaEnvironment) {
private val handlers = HashMap<String, LuaFunction<*, *, *, *, *>>()
init {
val table = lua.newTable()
table["setHandler"] = luaFunction { name: ByteString, handler: LuaFunction<*, *, *, *, *>? ->
if (handler == null) {
handlers.remove(name.decode())
} else {
handlers[name.decode()] = handler
}
}
lua.globals["message"] = table
}
fun handle(message: String, isLocal: Boolean, parameters: JsonArray): JsonElement {
if (lua.errorState)
return JsonNull.INSTANCE
val handler = handlers[message] ?: return JsonNull.INSTANCE
try {
val unpacked = arrayOfNulls<Any>(parameters.size() + 2)
unpacked[0] = ByteString.of(message)
unpacked[1] = isLocal
for ((i, v) in parameters.withIndex()) {
unpacked[i + 2] = lua.from(v)
}
val result = lua.executor.call(lua, handler, *unpacked)
if (result.isEmpty()) {
return JsonNull.INSTANCE
} else if (result.size == 1) {
return toJsonFromLua(result[0])
} else {
val array = JsonArray()
for (v in result) {
array.add(toJsonFromLua(v))
}
return array
}
} catch (err: CallPausedException) {
lua.markErrored()
LOGGER.error("Message handler for $message tried to yield", err)
return JsonNull.INSTANCE
} catch (err: Throwable) {
lua.markErrored()
LOGGER.error("Message handler for $message errored", err)
return JsonNull.INSTANCE
}
}
companion object {
private val LOGGER = LogManager.getLogger()
}
}