fix polymorphic serialization, and update the names of some schema objects
This commit is contained in:
parent
e5feabf7eb
commit
2208c91652
11 changed files with 109 additions and 55 deletions
|
|
@ -1,17 +1,17 @@
|
|||
package dev.adamko.kafkatorio.events.schema
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
|
||||
|
||||
@Serializable
|
||||
@SerialName("CONFIG")
|
||||
data class FactorioConfigurationUpdate(
|
||||
override val modVersion: String,
|
||||
val factorioData: FactorioGameDataUpdate,
|
||||
val allMods: List<FactorioModInfo>,
|
||||
val prototypes: List<FactorioPrototype>,
|
||||
) : KafkatorioPacket() {
|
||||
@Transient
|
||||
override val packetType = PacketType.CONFIG
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,20 @@
|
|||
package dev.adamko.kafkatorio.events.schema
|
||||
|
||||
|
||||
import dev.adamko.kafkatorio.events.schema.FactorioObjectData.ObjectName
|
||||
import kotlinx.serialization.DeserializationStrategy
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import kotlinx.serialization.json.JsonContentPolymorphicSerializer
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.contentOrNull
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
|
||||
|
||||
@Serializable
|
||||
@SerialName("EVENT")
|
||||
data class FactorioEvent<out T : FactorioObjectData>(
|
||||
override val modVersion: String,
|
||||
/** the initial Factorio event (`defines.events`) trigger */
|
||||
|
|
@ -14,6 +23,40 @@ data class FactorioEvent<out T : FactorioObjectData>(
|
|||
val tick: UInt,
|
||||
val data: T,
|
||||
) : KafkatorioPacket() {
|
||||
@Transient
|
||||
override val packetType: PacketType = PacketType.EVENT
|
||||
|
||||
companion object {
|
||||
val kxsModule = SerializersModule {
|
||||
contextual(FactorioEvent::class) { types -> serializer(types[0]) }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
object FactorioEventSerializer : JsonContentPolymorphicSerializer<FactorioEvent<*>>(
|
||||
FactorioEvent::class
|
||||
) {
|
||||
|
||||
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out FactorioEvent<*>> {
|
||||
|
||||
val objectName: ObjectName? = element
|
||||
.jsonObject[FactorioEvent<*>::data.name]
|
||||
?.jsonObject
|
||||
?.get(FactorioObjectData.discriminatorKey)
|
||||
?.jsonPrimitive
|
||||
?.contentOrNull
|
||||
?.let(ObjectName::valueOf)
|
||||
|
||||
val sub = when (objectName) {
|
||||
ObjectName.LuaPlayer -> PlayerData.serializer()
|
||||
ObjectName.LuaEntity -> EntityData.serializer()
|
||||
ObjectName.LuaSurface -> SurfaceData.serializer()
|
||||
ObjectName.MapChunk -> MapChunk.serializer()
|
||||
ObjectName.LuaTile -> MapTile.serializer()
|
||||
ObjectName.ConsoleChatMessage -> ConsoleChatMessage.serializer()
|
||||
null -> throw IllegalStateException("unknown type $objectName")
|
||||
}
|
||||
return FactorioEvent.serializer(sub)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package dev.adamko.kafkatorio.events.schema
|
|||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import kotlinx.serialization.json.JsonClassDiscriminator
|
||||
|
||||
@Serializable
|
||||
|
|
@ -33,7 +32,7 @@ sealed class FactorioObjectData {
|
|||
LuaPlayer,
|
||||
LuaEntity,
|
||||
LuaSurface,
|
||||
FactorioMapChunk,
|
||||
MapChunk,
|
||||
LuaTile,
|
||||
ConsoleChatMessage,
|
||||
}
|
||||
|
|
@ -57,7 +56,6 @@ data class PlayerData(
|
|||
val chatColour: Colour,
|
||||
val lastOnline: UInt,
|
||||
) : FactorioObjectData() {
|
||||
@Transient
|
||||
override val objectName = ObjectName.LuaPlayer
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +72,6 @@ data class EntityData(
|
|||
val unitNumber: UInt? = null,
|
||||
val playerIndex: UInt? = null,
|
||||
) : FactorioObjectData() {
|
||||
@Transient
|
||||
override val objectName = ObjectName.LuaEntity
|
||||
}
|
||||
|
||||
|
|
@ -85,36 +82,33 @@ data class SurfaceData(
|
|||
val index: UInt,
|
||||
val name: String,
|
||||
) : FactorioObjectData() {
|
||||
@Transient
|
||||
override val objectName = ObjectName.LuaSurface
|
||||
}
|
||||
|
||||
/** Quasi-object. This isn't a Factorio Lua type, but a helpful collection of [FactorioMapTile]s */
|
||||
/** Quasi-object. This isn't a Factorio Lua type, but a helpful collection of [MapTile]s */
|
||||
@Serializable
|
||||
@SerialName("FactorioMapChunk")
|
||||
data class FactorioMapChunk(
|
||||
val tiles: List<FactorioMapTile>,
|
||||
@SerialName("MapChunk")
|
||||
data class MapChunk(
|
||||
val tiles: List<MapTile>,
|
||||
) : FactorioObjectData() {
|
||||
@Transient
|
||||
override val objectName = ObjectName.FactorioMapChunk
|
||||
override val objectName = ObjectName.MapChunk
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("LuaTile")
|
||||
data class FactorioMapTile(
|
||||
data class MapTile(
|
||||
val prototypeName: String,
|
||||
val position: PositionData,
|
||||
val surfaceIndex: Int,
|
||||
) : FactorioObjectData() {
|
||||
@Transient
|
||||
override val objectName = ObjectName.LuaTile
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("ConsoleChatMessage")
|
||||
data class ConsoleChatMessage(
|
||||
val authorPlayerIndex: UInt?,
|
||||
val content: String,
|
||||
) : FactorioObjectData() {
|
||||
@Transient
|
||||
override val objectName = ObjectName.ConsoleChatMessage
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import kotlinx.serialization.json.JsonObject
|
|||
import kotlinx.serialization.json.JsonTransformingSerializer
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
|
||||
|
||||
/** Factorio outputs lists as Json objects - this serializer converts an object back to a list. */
|
||||
|
|
@ -27,8 +26,10 @@ internal class ListAsObjectSerializer<T>(dataSerializer: KSerializer<T>) :
|
|||
)
|
||||
}
|
||||
|
||||
internal val jsonMapper = Json {
|
||||
val jsonMapperKafkatorio = Json {
|
||||
prettyPrint = true
|
||||
prettyPrintIndent = " "
|
||||
serializersModule = SerializersModule { }
|
||||
serializersModule = FactorioEvent.kxsModule
|
||||
// serializersModule = KafkatorioPacket.kxsModule + FactorioEvent.kxsModule
|
||||
// serializersModule = SerializersModule { }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,45 @@
|
|||
package dev.adamko.kafkatorio.events.schema;
|
||||
|
||||
import kotlinx.serialization.DeserializationStrategy
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonClassDiscriminator
|
||||
import kotlinx.serialization.json.JsonContentPolymorphicSerializer
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.contentOrNull
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
|
||||
|
||||
@Serializable
|
||||
@JsonClassDiscriminator("packetType")
|
||||
@Serializable(with = KafkatorioPacketSerializer::class)
|
||||
sealed class KafkatorioPacket {
|
||||
/** Schema versioning */
|
||||
abstract val modVersion: String
|
||||
abstract val packetType: PacketType
|
||||
|
||||
enum class PacketType {
|
||||
EVENT, CONFIG,
|
||||
EVENT,
|
||||
CONFIG,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//@Serializable
|
||||
//@JsonClassDiscriminator(KafkatorioPacketData.discriminatorKey)
|
||||
//sealed class KafkatorioPacketData(
|
||||
// @SerialName(discriminatorKey)
|
||||
// val dataType: PacketDataType
|
||||
//) {
|
||||
// companion object {
|
||||
// const val discriminatorKey: String = "dataType"
|
||||
// }
|
||||
//}
|
||||
object KafkatorioPacketSerializer : JsonContentPolymorphicSerializer<KafkatorioPacket>(
|
||||
KafkatorioPacket::class
|
||||
) {
|
||||
private const val key = "packetType"
|
||||
|
||||
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out KafkatorioPacket> {
|
||||
|
||||
val type = element
|
||||
.jsonObject[key]
|
||||
?.jsonPrimitive
|
||||
?.contentOrNull
|
||||
?.let(KafkatorioPacket.PacketType::valueOf)
|
||||
|
||||
return when (type) {
|
||||
KafkatorioPacket.PacketType.EVENT -> FactorioEventSerializer
|
||||
KafkatorioPacket.PacketType.CONFIG -> FactorioConfigurationUpdate.serializer()
|
||||
else ->
|
||||
throw Exception("Unknown Packet: key '$key' ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class FactorioEventTest : BehaviorSpec({
|
|||
""".trimIndent()
|
||||
|
||||
Then("parse") {
|
||||
val actual: KafkatorioPacket = jsonMapper.decodeFromString(KafkatorioPacket.serializer(), json)
|
||||
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
|
||||
|
||||
val expected = FactorioEvent(
|
||||
data = PlayerData(
|
||||
|
|
@ -99,7 +99,7 @@ class FactorioEventTest : BehaviorSpec({
|
|||
}
|
||||
""".trimIndent()
|
||||
Then("parse") {
|
||||
val actual: KafkatorioPacket = jsonMapper.decodeFromString(json)
|
||||
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
|
||||
|
||||
val expected = FactorioEvent(
|
||||
data = SurfaceData(
|
||||
|
|
@ -144,7 +144,7 @@ class FactorioEventTest : BehaviorSpec({
|
|||
}
|
||||
""".trimIndent()
|
||||
Then("parse") {
|
||||
val actual: KafkatorioPacket = jsonMapper.decodeFromString(json)
|
||||
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
|
||||
|
||||
val expected = FactorioEvent(
|
||||
data = EntityData(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue