KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaMessageHandlerComponent.kt
DBotThePony f95bc9762f
Minimally working Monster entities
PathController, PathFinder

Actor movement controller Lua bindings

Game loading no longer block Universe thread, more efficient registry population synchronization

Environmental status effects now can be stat modifiers
2024-06-28 22:44:13 +07:00

62 lines
1.9 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
import ru.dbotthepony.kommons.util.Either
import ru.dbotthepony.kstarbound.util.ActionPacer
import ru.dbotthepony.kstarbound.util.sbIntern
import ru.dbotthepony.kstarbound.world.World
class LuaMessageHandlerComponent(val lua: LuaEnvironment, val nameProvider: () -> String) {
private val handlers = HashMap<String, LuaFunction<*, *, *, *, *>>()
init {
val table = lua.newTable()
lua.globals["message"] = table
table["setHandler"] = luaFunction { message: ByteString, handler: LuaFunction<*, *, *, *, *>? ->
if (handler == null) {
handlers.remove(message.decode())
} else {
handlers[message.decode().sbIntern()] = handler
}
}
}
private val logPacer = ActionPacer(1, 5)
fun handle(message: String, isLocal: Boolean, arguments: JsonArray): JsonElement? {
val handler = handlers[message] ?: return null
try {
val unpack = arguments.map { lua.from(it) }.toTypedArray()
val result = lua.executor.call(lua, handler, isLocal, *unpack)
if (result.isEmpty()) {
return null
} else {
return toJsonFromLua(result[0])
}
} catch (err: CallPausedException) {
if (logPacer.consumeAndReturnDeadline() <= 0L)
LOGGER.error("${nameProvider.invoke()}: '$message' handler attempted to yield across C boundary", err)
throw World.MessageCallException("$message handler attempted to yield across C boundary")
} catch (err: Throwable) {
if (logPacer.consumeAndReturnDeadline() <= 0L)
LOGGER.error("${nameProvider.invoke()}: Exception while handling message '$message'", err)
throw err
}
}
companion object {
private val LOGGER = LogManager.getLogger()
}
}