Lua message handlers
This commit is contained in:
parent
639aafce50
commit
6ed51b6ae9
@ -1,73 +0,0 @@
|
|||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,61 @@
|
|||||||
|
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] ?: throw World.MessageCallException("No registered handler for $message")
|
||||||
|
|
||||||
|
try {
|
||||||
|
val unpack = arguments.map { lua.from(it) }.toTypedArray()
|
||||||
|
val result = lua.executor.call(lua, handler, isLocal, *unpack)
|
||||||
|
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
return JsonNull.INSTANCE
|
||||||
|
} 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()
|
||||||
|
}
|
||||||
|
}
|
@ -16,10 +16,6 @@ fun String.sbIntern(): String {
|
|||||||
return Starbound.STRINGS.intern(this)
|
return Starbound.STRINGS.intern(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.sbIntern2(): String {
|
|
||||||
return Starbound.STRINGS.intern(this.intern())
|
|
||||||
}
|
|
||||||
|
|
||||||
val JsonElement.asStringOrNull: String?
|
val JsonElement.asStringOrNull: String?
|
||||||
get() = if (isJsonNull) null else asString
|
get() = if (isJsonNull) null else asString
|
||||||
|
|
||||||
|
@ -644,7 +644,7 @@ class Animator() {
|
|||||||
|
|
||||||
fun setPartTag(partName: String, tagKey: String, tagValue: String) {
|
fun setPartTag(partName: String, tagKey: String, tagValue: String) {
|
||||||
partTags.computeIfAbsent(partName) {
|
partTags.computeIfAbsent(partName) {
|
||||||
LOGGER.warn("Creating part tags for $it after initialization, this can cause client-server desyncs")
|
LOGGER.warn("Creating animated part tags for '$it' after initialization, this can cause client-server desyncs")
|
||||||
NetworkedMap(InternedStringCodec, InternedStringCodec)
|
NetworkedMap(InternedStringCodec, InternedStringCodec)
|
||||||
}.put(tagKey, tagValue)
|
}.put(tagKey, tagValue)
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,9 @@ import ru.dbotthepony.kommons.io.StreamCodec
|
|||||||
import ru.dbotthepony.kommons.io.map
|
import ru.dbotthepony.kommons.io.map
|
||||||
import ru.dbotthepony.kommons.io.writeBinaryString
|
import ru.dbotthepony.kommons.io.writeBinaryString
|
||||||
import ru.dbotthepony.kstarbound.math.AABB
|
import ru.dbotthepony.kstarbound.math.AABB
|
||||||
import ru.dbotthepony.kommons.util.KOptional
|
|
||||||
import ru.dbotthepony.kommons.util.getValue
|
import ru.dbotthepony.kommons.util.getValue
|
||||||
import ru.dbotthepony.kommons.util.setValue
|
import ru.dbotthepony.kommons.util.setValue
|
||||||
import ru.dbotthepony.kstarbound.Globals
|
import ru.dbotthepony.kstarbound.Globals
|
||||||
import ru.dbotthepony.kstarbound.defs.DamageData
|
|
||||||
import ru.dbotthepony.kstarbound.defs.DamageNotification
|
import ru.dbotthepony.kstarbound.defs.DamageNotification
|
||||||
import ru.dbotthepony.kstarbound.math.vector.Vector2d
|
import ru.dbotthepony.kstarbound.math.vector.Vector2d
|
||||||
import ru.dbotthepony.kstarbound.defs.DamageSource
|
import ru.dbotthepony.kstarbound.defs.DamageSource
|
||||||
@ -66,7 +64,7 @@ import ru.dbotthepony.kstarbound.network.syncher.networkedPointer
|
|||||||
import ru.dbotthepony.kstarbound.network.syncher.networkedString
|
import ru.dbotthepony.kstarbound.network.syncher.networkedString
|
||||||
import ru.dbotthepony.kstarbound.json.writeJsonElement
|
import ru.dbotthepony.kstarbound.json.writeJsonElement
|
||||||
import ru.dbotthepony.kstarbound.lua.LuaEnvironment
|
import ru.dbotthepony.kstarbound.lua.LuaEnvironment
|
||||||
import ru.dbotthepony.kstarbound.lua.LuaMessageHandler
|
import ru.dbotthepony.kstarbound.lua.LuaMessageHandlerComponent
|
||||||
import ru.dbotthepony.kstarbound.lua.LuaUpdateComponent
|
import ru.dbotthepony.kstarbound.lua.LuaUpdateComponent
|
||||||
import ru.dbotthepony.kstarbound.lua.bindings.provideAnimatorBindings
|
import ru.dbotthepony.kstarbound.lua.bindings.provideAnimatorBindings
|
||||||
import ru.dbotthepony.kstarbound.lua.bindings.provideEntityBindings
|
import ru.dbotthepony.kstarbound.lua.bindings.provideEntityBindings
|
||||||
@ -368,7 +366,7 @@ open class WorldObject(val config: Registry.Entry<ObjectDefinition>) : TileEntit
|
|||||||
|
|
||||||
val lua = LuaEnvironment()
|
val lua = LuaEnvironment()
|
||||||
val luaUpdate = LuaUpdateComponent(lua)
|
val luaUpdate = LuaUpdateComponent(lua)
|
||||||
val luaMessageHandler = LuaMessageHandler(lua)
|
val luaMessageHandler = LuaMessageHandlerComponent(lua) { toString() }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
lua.globals["storage"] = lua.newTable()
|
lua.globals["storage"] = lua.newTable()
|
||||||
@ -796,6 +794,10 @@ open class WorldObject(val config: Registry.Entry<ObjectDefinition>) : TileEntit
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun handleMessage(connection: Int, message: String, arguments: JsonArray): JsonElement? {
|
||||||
|
return luaMessageHandler.handle(message, connectionID == connection, arguments)
|
||||||
|
}
|
||||||
|
|
||||||
override fun callScript(fnName: String, vararg arguments: Any?): Array<Any?> {
|
override fun callScript(fnName: String, vararg arguments: Any?): Array<Any?> {
|
||||||
return lua.invokeGlobal(fnName, *arguments)
|
return lua.invokeGlobal(fnName, *arguments)
|
||||||
}
|
}
|
||||||
@ -804,6 +806,10 @@ open class WorldObject(val config: Registry.Entry<ObjectDefinition>) : TileEntit
|
|||||||
return lua.eval(code)
|
return lua.eval(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
isInteractive = !interactAction.isJsonNull
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val LOGGER = LogManager.getLogger()
|
private val LOGGER = LogManager.getLogger()
|
||||||
private val lightColorPath = JsonPath("lightColor")
|
private val lightColorPath = JsonPath("lightColor")
|
||||||
|
Loading…
Reference in New Issue
Block a user