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
62 lines
1.9 KiB
Kotlin
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()
|
|
}
|
|
}
|