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>() 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(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() } }