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,6 +1,6 @@
|
||||||
// Generated by TypeScriptGenerator - do not edit this file manually
|
// Generated by TypeScriptGenerator - do not edit this file manually
|
||||||
|
|
||||||
type ObjectName = "LuaPlayer" | "LuaEntity" | "LuaSurface" | "FactorioMapChunk" | "LuaTile" | "ConsoleChatMessage";
|
type ObjectName = "LuaPlayer" | "LuaEntity" | "LuaSurface" | "MapChunk" | "LuaTile" | "ConsoleChatMessage";
|
||||||
|
|
||||||
interface FactorioObjectData {
|
interface FactorioObjectData {
|
||||||
objectName: ObjectName;
|
objectName: ObjectName;
|
||||||
|
|
@ -45,16 +45,16 @@ interface SurfaceData extends FactorioObjectData {
|
||||||
objectName: ObjectName;
|
objectName: ObjectName;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FactorioMapTile extends FactorioObjectData {
|
interface MapTile extends FactorioObjectData {
|
||||||
objectName: ObjectName;
|
objectName: ObjectName;
|
||||||
position: PositionData;
|
position: PositionData;
|
||||||
prototypeName: string;
|
prototypeName: string;
|
||||||
surfaceIndex: int;
|
surfaceIndex: int;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FactorioMapChunk extends FactorioObjectData {
|
interface MapChunk extends FactorioObjectData {
|
||||||
objectName: ObjectName;
|
objectName: ObjectName;
|
||||||
tiles: FactorioMapTile[];
|
tiles: MapTile[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConsoleChatMessage extends FactorioObjectData {
|
interface ConsoleChatMessage extends FactorioObjectData {
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ export namespace Converters {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertTile(tile: LuaTile): FactorioMapTile {
|
export function convertTile(tile: LuaTile): MapTile {
|
||||||
return {
|
return {
|
||||||
objectName: tile.object_name,
|
objectName: tile.object_name,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,12 +70,12 @@ export function handleChunkUpdate(
|
||||||
}
|
}
|
||||||
) ?? []
|
) ?? []
|
||||||
|
|
||||||
let convertedTiles: FactorioMapTile[] = tiles.map((tile: LuaTile) => {
|
let convertedTiles: MapTile[] = tiles.map((tile: LuaTile) => {
|
||||||
return Converters.convertTile(tile)
|
return Converters.convertTile(tile)
|
||||||
})
|
})
|
||||||
|
|
||||||
let mapChunk: FactorioMapChunk = {
|
let mapChunk: MapChunk = {
|
||||||
objectName: "FactorioMapChunk",
|
objectName: "MapChunk",
|
||||||
tiles: convertedTiles,
|
tiles: convertedTiles,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
package dev.adamko.kafkatorio.events.schema
|
package dev.adamko.kafkatorio.events.schema
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Transient
|
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@SerialName("CONFIG")
|
||||||
data class FactorioConfigurationUpdate(
|
data class FactorioConfigurationUpdate(
|
||||||
override val modVersion: String,
|
override val modVersion: String,
|
||||||
val factorioData: FactorioGameDataUpdate,
|
val factorioData: FactorioGameDataUpdate,
|
||||||
val allMods: List<FactorioModInfo>,
|
val allMods: List<FactorioModInfo>,
|
||||||
val prototypes: List<FactorioPrototype>,
|
val prototypes: List<FactorioPrototype>,
|
||||||
) : KafkatorioPacket() {
|
) : KafkatorioPacket() {
|
||||||
@Transient
|
|
||||||
override val packetType = PacketType.CONFIG
|
override val packetType = PacketType.CONFIG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,20 @@
|
||||||
package dev.adamko.kafkatorio.events.schema
|
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.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
|
@Serializable
|
||||||
|
@SerialName("EVENT")
|
||||||
data class FactorioEvent<out T : FactorioObjectData>(
|
data class FactorioEvent<out T : FactorioObjectData>(
|
||||||
override val modVersion: String,
|
override val modVersion: String,
|
||||||
/** the initial Factorio event (`defines.events`) trigger */
|
/** the initial Factorio event (`defines.events`) trigger */
|
||||||
|
|
@ -14,6 +23,40 @@ data class FactorioEvent<out T : FactorioObjectData>(
|
||||||
val tick: UInt,
|
val tick: UInt,
|
||||||
val data: T,
|
val data: T,
|
||||||
) : KafkatorioPacket() {
|
) : KafkatorioPacket() {
|
||||||
@Transient
|
|
||||||
override val packetType: PacketType = PacketType.EVENT
|
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.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Transient
|
|
||||||
import kotlinx.serialization.json.JsonClassDiscriminator
|
import kotlinx.serialization.json.JsonClassDiscriminator
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|
@ -33,7 +32,7 @@ sealed class FactorioObjectData {
|
||||||
LuaPlayer,
|
LuaPlayer,
|
||||||
LuaEntity,
|
LuaEntity,
|
||||||
LuaSurface,
|
LuaSurface,
|
||||||
FactorioMapChunk,
|
MapChunk,
|
||||||
LuaTile,
|
LuaTile,
|
||||||
ConsoleChatMessage,
|
ConsoleChatMessage,
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +56,6 @@ data class PlayerData(
|
||||||
val chatColour: Colour,
|
val chatColour: Colour,
|
||||||
val lastOnline: UInt,
|
val lastOnline: UInt,
|
||||||
) : FactorioObjectData() {
|
) : FactorioObjectData() {
|
||||||
@Transient
|
|
||||||
override val objectName = ObjectName.LuaPlayer
|
override val objectName = ObjectName.LuaPlayer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,7 +72,6 @@ data class EntityData(
|
||||||
val unitNumber: UInt? = null,
|
val unitNumber: UInt? = null,
|
||||||
val playerIndex: UInt? = null,
|
val playerIndex: UInt? = null,
|
||||||
) : FactorioObjectData() {
|
) : FactorioObjectData() {
|
||||||
@Transient
|
|
||||||
override val objectName = ObjectName.LuaEntity
|
override val objectName = ObjectName.LuaEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,36 +82,33 @@ data class SurfaceData(
|
||||||
val index: UInt,
|
val index: UInt,
|
||||||
val name: String,
|
val name: String,
|
||||||
) : FactorioObjectData() {
|
) : FactorioObjectData() {
|
||||||
@Transient
|
|
||||||
override val objectName = ObjectName.LuaSurface
|
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
|
@Serializable
|
||||||
@SerialName("FactorioMapChunk")
|
@SerialName("MapChunk")
|
||||||
data class FactorioMapChunk(
|
data class MapChunk(
|
||||||
val tiles: List<FactorioMapTile>,
|
val tiles: List<MapTile>,
|
||||||
) : FactorioObjectData() {
|
) : FactorioObjectData() {
|
||||||
@Transient
|
override val objectName = ObjectName.MapChunk
|
||||||
override val objectName = ObjectName.FactorioMapChunk
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("LuaTile")
|
@SerialName("LuaTile")
|
||||||
data class FactorioMapTile(
|
data class MapTile(
|
||||||
val prototypeName: String,
|
val prototypeName: String,
|
||||||
val position: PositionData,
|
val position: PositionData,
|
||||||
val surfaceIndex: Int,
|
val surfaceIndex: Int,
|
||||||
) : FactorioObjectData() {
|
) : FactorioObjectData() {
|
||||||
@Transient
|
|
||||||
override val objectName = ObjectName.LuaTile
|
override val objectName = ObjectName.LuaTile
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@SerialName("ConsoleChatMessage")
|
||||||
data class ConsoleChatMessage(
|
data class ConsoleChatMessage(
|
||||||
val authorPlayerIndex: UInt?,
|
val authorPlayerIndex: UInt?,
|
||||||
val content: String,
|
val content: String,
|
||||||
) : FactorioObjectData() {
|
) : FactorioObjectData() {
|
||||||
@Transient
|
|
||||||
override val objectName = ObjectName.ConsoleChatMessage
|
override val objectName = ObjectName.ConsoleChatMessage
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.JsonTransformingSerializer
|
import kotlinx.serialization.json.JsonTransformingSerializer
|
||||||
import kotlinx.serialization.json.jsonArray
|
import kotlinx.serialization.json.jsonArray
|
||||||
import kotlinx.serialization.json.jsonObject
|
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. */
|
/** 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
|
prettyPrint = true
|
||||||
prettyPrintIndent = " "
|
prettyPrintIndent = " "
|
||||||
serializersModule = SerializersModule { }
|
serializersModule = FactorioEvent.kxsModule
|
||||||
|
// serializersModule = KafkatorioPacket.kxsModule + FactorioEvent.kxsModule
|
||||||
|
// serializersModule = SerializersModule { }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,45 @@
|
||||||
package dev.adamko.kafkatorio.events.schema;
|
package dev.adamko.kafkatorio.events.schema;
|
||||||
|
|
||||||
|
import kotlinx.serialization.DeserializationStrategy
|
||||||
import kotlinx.serialization.Serializable
|
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
|
@Serializable(with = KafkatorioPacketSerializer::class)
|
||||||
@JsonClassDiscriminator("packetType")
|
|
||||||
sealed class KafkatorioPacket {
|
sealed class KafkatorioPacket {
|
||||||
/** Schema versioning */
|
/** Schema versioning */
|
||||||
abstract val modVersion: String
|
abstract val modVersion: String
|
||||||
abstract val packetType: PacketType
|
abstract val packetType: PacketType
|
||||||
|
|
||||||
enum class PacketType {
|
enum class PacketType {
|
||||||
EVENT, CONFIG,
|
EVENT,
|
||||||
|
CONFIG,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//@Serializable
|
object KafkatorioPacketSerializer : JsonContentPolymorphicSerializer<KafkatorioPacket>(
|
||||||
//@JsonClassDiscriminator(KafkatorioPacketData.discriminatorKey)
|
KafkatorioPacket::class
|
||||||
//sealed class KafkatorioPacketData(
|
) {
|
||||||
// @SerialName(discriminatorKey)
|
private const val key = "packetType"
|
||||||
// val dataType: PacketDataType
|
|
||||||
//) {
|
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out KafkatorioPacket> {
|
||||||
// companion object {
|
|
||||||
// const val discriminatorKey: String = "dataType"
|
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()
|
""".trimIndent()
|
||||||
|
|
||||||
Then("parse") {
|
Then("parse") {
|
||||||
val actual: KafkatorioPacket = jsonMapper.decodeFromString(KafkatorioPacket.serializer(), json)
|
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
|
||||||
|
|
||||||
val expected = FactorioEvent(
|
val expected = FactorioEvent(
|
||||||
data = PlayerData(
|
data = PlayerData(
|
||||||
|
|
@ -99,7 +99,7 @@ class FactorioEventTest : BehaviorSpec({
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
Then("parse") {
|
Then("parse") {
|
||||||
val actual: KafkatorioPacket = jsonMapper.decodeFromString(json)
|
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
|
||||||
|
|
||||||
val expected = FactorioEvent(
|
val expected = FactorioEvent(
|
||||||
data = SurfaceData(
|
data = SurfaceData(
|
||||||
|
|
@ -144,7 +144,7 @@ class FactorioEventTest : BehaviorSpec({
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
Then("parse") {
|
Then("parse") {
|
||||||
val actual: KafkatorioPacket = jsonMapper.decodeFromString(json)
|
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
|
||||||
|
|
||||||
val expected = FactorioEvent(
|
val expected = FactorioEvent(
|
||||||
data = EntityData(
|
data = EntityData(
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package dev.adamko.kafkatorio.processor
|
package dev.adamko.kafkatorio.processor
|
||||||
|
|
||||||
import dev.adamko.kafkatorio.events.schema.KafkatorioPacket
|
import dev.adamko.kafkatorio.events.schema.KafkatorioPacket
|
||||||
|
import dev.adamko.kafkatorio.events.schema.jsonMapperKafkatorio
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.modules.SerializersModule
|
|
||||||
import org.apache.kafka.common.serialization.Deserializer
|
import org.apache.kafka.common.serialization.Deserializer
|
||||||
import org.apache.kafka.common.serialization.Serde
|
import org.apache.kafka.common.serialization.Serde
|
||||||
import org.apache.kafka.common.serialization.Serializer
|
import org.apache.kafka.common.serialization.Serializer
|
||||||
|
|
@ -26,7 +26,7 @@ object KafkatorioPacketSerde : Serde<KafkatorioPacket> {
|
||||||
val jsonMapper = Json {
|
val jsonMapper = Json {
|
||||||
prettyPrint = true
|
prettyPrint = true
|
||||||
prettyPrintIndent = " "
|
prettyPrintIndent = " "
|
||||||
serializersModule = SerializersModule { }
|
serializersModule = jsonMapperKafkatorio.serializersModule
|
||||||
}
|
}
|
||||||
|
|
||||||
object KXS : ConfigurableKotlinxSerialization({
|
object KXS : ConfigurableKotlinxSerialization({
|
||||||
|
|
@ -34,5 +34,5 @@ object KXS : ConfigurableKotlinxSerialization({
|
||||||
prettyPrint = true
|
prettyPrint = true
|
||||||
prettyPrintIndent = " "
|
prettyPrintIndent = " "
|
||||||
asConfigurable().withStandardMappings().done()
|
asConfigurable().withStandardMappings().done()
|
||||||
serializersModule = SerializersModule { }
|
serializersModule = jsonMapperKafkatorio.serializersModule
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import dev.adamko.kafkatorio.events.schema.ConsoleChatMessage
|
||||||
import dev.adamko.kafkatorio.events.schema.EntityData
|
import dev.adamko.kafkatorio.events.schema.EntityData
|
||||||
import dev.adamko.kafkatorio.events.schema.FactorioConfigurationUpdate
|
import dev.adamko.kafkatorio.events.schema.FactorioConfigurationUpdate
|
||||||
import dev.adamko.kafkatorio.events.schema.FactorioEvent
|
import dev.adamko.kafkatorio.events.schema.FactorioEvent
|
||||||
import dev.adamko.kafkatorio.events.schema.FactorioMapChunk
|
import dev.adamko.kafkatorio.events.schema.MapChunk
|
||||||
import dev.adamko.kafkatorio.events.schema.FactorioMapTile
|
import dev.adamko.kafkatorio.events.schema.MapTile
|
||||||
import dev.adamko.kafkatorio.events.schema.KafkatorioPacket
|
import dev.adamko.kafkatorio.events.schema.KafkatorioPacket
|
||||||
import dev.adamko.kafkatorio.events.schema.PlayerData
|
import dev.adamko.kafkatorio.events.schema.PlayerData
|
||||||
import dev.adamko.kafkatorio.events.schema.SurfaceData
|
import dev.adamko.kafkatorio.events.schema.SurfaceData
|
||||||
|
|
@ -42,10 +42,10 @@ class WebsocketService(
|
||||||
is PlayerData ->
|
is PlayerData ->
|
||||||
reduxStore.dispatch(FactorioUpdate.PlayerUpdate(event, eventData))
|
reduxStore.dispatch(FactorioUpdate.PlayerUpdate(event, eventData))
|
||||||
is ConsoleChatMessage -> {}
|
is ConsoleChatMessage -> {}
|
||||||
is EntityData -> {}
|
is EntityData -> {}
|
||||||
is FactorioMapChunk -> {}
|
is MapChunk -> {}
|
||||||
is FactorioMapTile -> {}
|
is MapTile -> {}
|
||||||
is SurfaceData -> {}
|
is SurfaceData -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is FactorioConfigurationUpdate -> {}
|
is FactorioConfigurationUpdate -> {}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue