- make tests multi-platform

- fix polymorphism finally???
This commit is contained in:
Adam 2022-01-09 14:01:48 +01:00
parent 1be9841d8b
commit beb73d1584
9 changed files with 471 additions and 243 deletions

View file

@ -965,7 +965,7 @@ deep-equal@^1.0.1:
object-keys "^1.1.1"
regexp.prototype.flags "^1.2.0"
default-gateway@^6.0.3:
default-gateway@^6.0.0, default-gateway@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71"
integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==
@ -1721,17 +1721,32 @@ inherits@2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
internal-ip@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-6.2.0.tgz#d5541e79716e406b74ac6b07b856ef18dc1621c1"
integrity sha512-D8WGsR6yDt8uq7vDMu7mjcR+yRMm3dW8yufyChmszWRjcSHuxLBkR3GdS2HZAjodsaGuCvXeEJpueisXJULghg==
dependencies:
default-gateway "^6.0.0"
ipaddr.js "^1.9.1"
is-ip "^3.1.0"
p-event "^4.2.0"
interpret@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9"
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
ip-regex@^4.0.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5"
integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==
ip@^1.1.0:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
ipaddr.js@1.9.1:
ipaddr.js@1.9.1, ipaddr.js@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
@ -1792,6 +1807,13 @@ is-glob@^4.0.1, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
is-ip@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8"
integrity sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==
dependencies:
ip-regex "^4.0.0"
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
@ -2285,6 +2307,18 @@ open@^8.0.9:
is-docker "^2.1.1"
is-wsl "^2.2.0"
p-event@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5"
integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==
dependencies:
p-timeout "^3.1.0"
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
p-limit@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
@ -2328,6 +2362,13 @@ p-retry@^4.5.0:
"@types/retry" "^0.12.0"
retry "^0.13.1"
p-timeout@^3.1.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe"
integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==
dependencies:
p-finally "^1.0.0"
p-try@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
@ -2467,6 +2508,11 @@ proxy-addr@~2.0.7:
forwarded "0.2.0"
ipaddr.js "1.9.1"
punycode@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
punycode@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
@ -2482,6 +2528,11 @@ qs@6.9.6:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee"
integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==
querystring@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
@ -3072,6 +3123,14 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
url@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=
dependencies:
punycode "1.3.2"
querystring "0.2.0"
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
@ -3087,6 +3146,11 @@ uuid@^8.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
v8-compile-cache@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
vary@^1, vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
@ -3102,7 +3166,7 @@ void-elements@^2.0.0:
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
watchpack@^2.3.1:
watchpack@^2.2.0, watchpack@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25"
integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==
@ -3117,6 +3181,25 @@ wbuf@^1.1.0, wbuf@^1.7.3:
dependencies:
minimalistic-assert "^1.0.0"
webpack-cli@4.9.0:
version "4.9.0"
resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.0.tgz#dc43e6e0f80dd52e89cbf73d5294bcd7ad6eb343"
integrity sha512-n/jZZBMzVEl4PYIBs+auy2WI0WTQ74EnJDiyD98O2JZY6IVIHJNitkYp/uTXOviIOMfgzrNvC9foKv/8o8KSZw==
dependencies:
"@discoveryjs/json-ext" "^0.5.0"
"@webpack-cli/configtest" "^1.1.0"
"@webpack-cli/info" "^1.4.0"
"@webpack-cli/serve" "^1.6.0"
colorette "^2.0.14"
commander "^7.0.0"
execa "^5.0.0"
fastest-levenshtein "^1.0.12"
import-local "^3.0.2"
interpret "^2.2.0"
rechoir "^0.7.0"
v8-compile-cache "^2.2.0"
webpack-merge "^5.7.3"
webpack-cli@4.9.1:
version "4.9.1"
resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.1.tgz#b64be825e2d1b130f285c314caa3b1ba9a4632b3"
@ -3135,7 +3218,7 @@ webpack-cli@4.9.1:
rechoir "^0.7.0"
webpack-merge "^5.7.3"
webpack-dev-middleware@^5.3.0:
webpack-dev-middleware@^5.2.1, webpack-dev-middleware@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.0.tgz#8fc02dba6e72e1d373eca361623d84610f27be7c"
integrity sha512-MouJz+rXAm9B1OTOYaJnn6rtD/lWZPy2ufQCH3BPs8Rloh/Du6Jze4p7AeLYHkVi0giJnYLaSGDC7S+GM9arhg==
@ -3146,6 +3229,37 @@ webpack-dev-middleware@^5.3.0:
range-parser "^1.2.1"
schema-utils "^4.0.0"
webpack-dev-server@4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.3.1.tgz#759d3337f0fbea297fbd1e433ab04ccfc000076b"
integrity sha512-qNXQCVYo1kYhH9pgLtm8LRNkXX3XzTfHSj/zqzaqYzGPca+Qjr+81wj1jgPMCHhIhso9WEQ+kX9z23iG9PzQ7w==
dependencies:
ansi-html-community "^0.0.8"
bonjour "^3.5.0"
chokidar "^3.5.1"
colorette "^2.0.10"
compression "^1.7.4"
connect-history-api-fallback "^1.6.0"
del "^6.0.0"
express "^4.17.1"
graceful-fs "^4.2.6"
html-entities "^2.3.2"
http-proxy-middleware "^2.0.0"
internal-ip "^6.2.0"
ipaddr.js "^2.0.1"
open "^8.0.9"
p-retry "^4.5.0"
portfinder "^1.0.28"
schema-utils "^3.1.0"
selfsigned "^1.10.11"
serve-index "^1.9.1"
sockjs "^0.3.21"
spdy "^4.0.2"
strip-ansi "^7.0.0"
url "^0.11.0"
webpack-dev-middleware "^5.2.1"
ws "^8.1.0"
webpack-dev-server@4.7.2:
version "4.7.2"
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.2.tgz#324b79046491f2cf0b9d9e275381198c8246b380"
@ -3196,11 +3310,41 @@ webpack-merge@^5.7.3:
clone-deep "^4.0.1"
wildcard "^2.0.0"
webpack-sources@^3.2.2:
webpack-sources@^3.2.0, webpack-sources@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.2.tgz#d88e3741833efec57c4c789b6010db9977545260"
integrity sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==
webpack@5.57.1:
version "5.57.1"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.57.1.tgz#ead5ace2c17ecef2ae8126f143bfeaa7f55eab44"
integrity sha512-kHszukYjTPVfCOEyrUthA3jqJwduY/P3eO8I0gMNOZGIQWKAwZftxmp5hq6paophvwo9NoUrcZOecs9ulOyyTg==
dependencies:
"@types/eslint-scope" "^3.7.0"
"@types/estree" "^0.0.50"
"@webassemblyjs/ast" "1.11.1"
"@webassemblyjs/wasm-edit" "1.11.1"
"@webassemblyjs/wasm-parser" "1.11.1"
acorn "^8.4.1"
acorn-import-assertions "^1.7.6"
browserslist "^4.14.5"
chrome-trace-event "^1.0.2"
enhanced-resolve "^5.8.3"
es-module-lexer "^0.9.0"
eslint-scope "5.1.1"
events "^3.2.0"
glob-to-regexp "^0.4.1"
graceful-fs "^4.2.4"
json-parse-better-errors "^1.0.2"
loader-runner "^4.2.0"
mime-types "^2.1.27"
neo-async "^2.6.2"
schema-utils "^3.1.0"
tapable "^2.1.1"
terser-webpack-plugin "^5.1.3"
watchpack "^2.2.0"
webpack-sources "^3.2.0"
webpack@5.65.0:
version "5.65.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.65.0.tgz#ed2891d9145ba1f0d318e4ea4f89c3fa18e6f9be"

View file

@ -11,6 +11,7 @@ plugins {
kotlin {
js(IR) {
binaries.executable()
browser()
nodejs()
}
jvm {
@ -48,6 +49,7 @@ kotlin {
implementation(kotlin("test"))
implementation(project.dependencies.platform(libs.kotest.bom))
implementation("io.kotest:kotest-framework-engine")
implementation("io.kotest:kotest-assertions-core")
implementation("io.kotest:kotest-property")
implementation("io.kotest:kotest-assertions-json")

View file

@ -1,17 +1,23 @@
package dev.adamko.kafkatorio.events.schema
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.Required
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
@Serializable
@SerialName("CONFIG")
//@SerialName("CONFIG")
data class FactorioConfigurationUpdate(
override val modVersion: String,
val factorioData: FactorioGameDataUpdate,
val allMods: List<FactorioModInfo>,
val prototypes: List<FactorioPrototype>,
) : KafkatorioPacket() {
// @Transient
@EncodeDefault
override val packetType = PacketType.CONFIG
}

View file

@ -1,62 +1,56 @@
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.EncodeDefault
import kotlinx.serialization.Required
import kotlinx.serialization.Serializable
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>(
//@SerialName("EVENT")
data class FactorioEvent(
override val modVersion: String,
/** the initial Factorio event (`defines.events`) trigger */
val eventType: String,
/** game time */
val tick: UInt,
val data: T,
val data: FactorioObjectData,
) : KafkatorioPacket() {
// @Transient
@EncodeDefault
override val packetType: PacketType = PacketType.EVENT
companion object {
val kxsModule = SerializersModule {
contextual(FactorioEvent::class) { types -> serializer(types[0]) }
}
}
// 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)
}
}
//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)
// }
//}

View file

@ -1,14 +1,22 @@
package dev.adamko.kafkatorio.events.schema
import kotlinx.serialization.SerialName
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.EncodeDefault
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(FactorioObjectData.discriminatorKey)
//@Serializable
@Serializable(with = FactorioObjectDataSerializer::class)
//@JsonClassDiscriminator(FactorioObjectData.discriminatorKey)
sealed class FactorioObjectData {
/** @see FactorioObjectData.discriminatorKey */
@EncodeDefault
abstract val objectName: ObjectName
// workaround - https://github.com/Kotlin/kotlinx.serialization/issues/1664
@ -43,9 +51,39 @@ sealed class FactorioObjectData {
}
}
object FactorioObjectDataSerializer : JsonContentPolymorphicSerializer<FactorioObjectData>(
FactorioObjectData::class
) {
private val key =
FactorioObjectData::objectName.name
// "objectName"
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out FactorioObjectData> {
val type = element
.jsonObject[key]
?.jsonPrimitive
?.contentOrNull
?.let { json ->
FactorioObjectData.ObjectName.values().firstOrNull { it.name == json }
}
return when (type) {
FactorioObjectData.ObjectName.LuaPlayer -> PlayerData.serializer()
FactorioObjectData.ObjectName.LuaEntity -> EntityData.serializer()
FactorioObjectData.ObjectName.LuaSurface -> SurfaceData.serializer()
FactorioObjectData.ObjectName.MapChunk -> MapChunk.serializer()
FactorioObjectData.ObjectName.LuaTile -> MapTile.serializer()
FactorioObjectData.ObjectName.ConsoleChatMessage -> ConsoleChatMessage.serializer()
null ->
throw Exception("Unknown FactorioObjectData $key: '$type' ")
}
}
}
@Serializable
@SerialName("LuaPlayer")
//@SerialName("LuaPlayer")
data class PlayerData(
@Serializable(with = ListAsObjectSerializer::class)
val associatedCharactersUnitNumbers: List<UInt>,
@ -56,11 +94,12 @@ data class PlayerData(
val chatColour: Colour,
val lastOnline: UInt,
) : FactorioObjectData() {
@EncodeDefault
override val objectName = ObjectName.LuaPlayer
}
@Serializable
@SerialName("LuaEntity")
//@SerialName("LuaEntity")
data class EntityData(
val active: Boolean,
val health: Double?,
@ -72,43 +111,48 @@ data class EntityData(
val unitNumber: UInt? = null,
val playerIndex: UInt? = null,
) : FactorioObjectData() {
@EncodeDefault
override val objectName = ObjectName.LuaEntity
}
@Serializable
@SerialName("LuaSurface")
//@SerialName("LuaSurface")
data class SurfaceData(
val daytime: Double,
val index: UInt,
val name: String,
) : FactorioObjectData() {
@EncodeDefault
override val objectName = ObjectName.LuaSurface
}
/** Quasi-object. This isn't a Factorio Lua type, but a helpful collection of [MapTile]s */
@Serializable
@SerialName("MapChunk")
//@SerialName("MapChunk")
data class MapChunk(
val tiles: List<MapTile>,
) : FactorioObjectData() {
@EncodeDefault
override val objectName = ObjectName.MapChunk
}
@Serializable
@SerialName("LuaTile")
//@SerialName("LuaTile")
data class MapTile(
val prototypeName: String,
val position: PositionData,
val surfaceIndex: Int,
) : FactorioObjectData() {
@EncodeDefault
override val objectName = ObjectName.LuaTile
}
@Serializable
@SerialName("ConsoleChatMessage")
//@SerialName("ConsoleChatMessage")
data class ConsoleChatMessage(
val authorPlayerIndex: UInt?,
val content: String,
) : FactorioObjectData() {
@EncodeDefault
override val objectName = ObjectName.ConsoleChatMessage
}

View file

@ -29,7 +29,7 @@ internal class ListAsObjectSerializer<T>(dataSerializer: KSerializer<T>) :
val jsonMapperKafkatorio = Json {
prettyPrint = true
prettyPrintIndent = " "
serializersModule = FactorioEvent.kxsModule
// serializersModule = FactorioEvent.kxsModule
// serializersModule = KafkatorioPacket.kxsModule + FactorioEvent.kxsModule
// serializersModule = SerializersModule { }
}

View file

@ -1,6 +1,8 @@
package dev.adamko.kafkatorio.events.schema;
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.Required
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonContentPolymorphicSerializer
import kotlinx.serialization.json.JsonElement
@ -8,24 +10,34 @@ 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 {
/** Schema versioning */
abstract val modVersion: String
@EncodeDefault
abstract val packetType: PacketType
enum class PacketType {
EVENT,
CONFIG,
}
}
companion object {
// val kxsModule = SerializersModule {
// polym
// }
}
}
object KafkatorioPacketSerializer : JsonContentPolymorphicSerializer<KafkatorioPacket>(
KafkatorioPacket::class
) {
private const val key = "packetType"
private val key =
KafkatorioPacket::packetType.name
// "packetType"
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out KafkatorioPacket> {
@ -33,13 +45,15 @@ object KafkatorioPacketSerializer : JsonContentPolymorphicSerializer<KafkatorioP
.jsonObject[key]
?.jsonPrimitive
?.contentOrNull
?.let(KafkatorioPacket.PacketType::valueOf)
?.let { json ->
KafkatorioPacket.PacketType.values().firstOrNull { it.name == json }
}
return when (type) {
KafkatorioPacket.PacketType.EVENT -> FactorioEventSerializer
KafkatorioPacket.PacketType.EVENT -> FactorioEvent.serializer()
KafkatorioPacket.PacketType.CONFIG -> FactorioConfigurationUpdate.serializer()
else ->
throw Exception("Unknown Packet: key '$key' ")
null ->
throw Exception("Unknown KafkatorioPacket ${key}: '$type' ")
}
}
}

View file

@ -0,0 +1,200 @@
package dev.adamko.kafkatorio.events.schema
import io.kotest.assertions.json.shouldEqualJson
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
class FactorioEventTest : FunSpec({
context("Given: json on_player_joined_game") {
// language=JSON
val json = """
{
"data": {
"objectName": "LuaPlayer",
"name": "fredthedeadhead",
"characterUnitNumber": 1,
"associatedCharactersUnitNumbers": {},
"position": {
"type": "MAP",
"x": 30.65625,
"y": 84.07421875
},
"colour": {
"red": 0.869000017642974853515625,
"green": 0.5,
"blue": 0.12999999523162841796875,
"alpha": 0.5
},
"chatColour": {
"red": 1,
"green": 0.62999999523162841796875,
"blue": 0.259000003337860107421875,
"alpha": 1
},
"lastOnline": 2287061
},
"packetType": "EVENT",
"eventType": "on_player_joined_game",
"modVersion": "0.2.1",
"tick": 2287072
}
""".trimIndent()
context("When: decoded") {
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
test("Then: parse") {
val expected = FactorioEvent(
data = PlayerData(
name = "fredthedeadhead",
characterUnitNumber = 1u,
associatedCharactersUnitNumbers = emptyList(),
position = PositionData(
type = PositionType.MAP,
x = 30.65625,
y = 84.07421875,
),
colour = Colour(
red = 0.869000017642974853515625f,
green = 0.5f,
blue = 0.12999999523162841796875f,
alpha = 0.5f
),
chatColour = Colour(
red = 1f,
green = 0.62999999523162841796875f,
blue = 0.259000003337860107421875f,
alpha = 1f
),
lastOnline = 2287061u
),
eventType = "on_player_joined_game",
modVersion = "0.2.1",
tick = 2287072u
)
actual shouldBe expected
expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaPlayer
}
test("Then: expect encode equals json") {
val encoded = jsonMapperKafkatorio.encodeToString(actual)
encoded.shouldEqualJson(json)
}
}
}
context("Given: json LuaSurface") {
// language=JSON
val json = """
{
"data": {
"objectName": "LuaSurface",
"name": "nauvis",
"index": 1,
"daytime": 0.749480000092057618843455202295444905757904052734375
},
"packetType": "EVENT",
"eventType": "on_tick",
"modVersion": "0.2.1",
"tick": 2301240
}
""".trimIndent()
context("When: decoded") {
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
test("should equal obj") {
val expected = FactorioEvent(
data = SurfaceData(
name = "nauvis",
index = 1u,
daytime = 0.749480000092057618843455202295444905757904052734375
),
eventType = "on_tick",
modVersion = "0.2.1",
tick = 2301240u
)
actual shouldBe expected
expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaSurface
}
test("Then: expect encode equals json") {
val encoded = jsonMapperKafkatorio.encodeToString(actual)
encoded.shouldEqualJson(json)
}
}
}
context("Given: LuaEntity on_player_changed_position") {
// language=JSON
val json = """
{
"data": {
"objectName": "LuaEntity",
"name": "character",
"type": "character",
"active": true,
"health": 250,
"healthRatio": 1,
"surfaceIndex": 1,
"unitNumber": 1,
"position": {
"type": "MAP",
"x": 37.859375,
"y": 81.14453125
}
},
"packetType": "EVENT",
"eventType": "on_player_changed_position",
"modVersion": "0.2.1",
"tick": 2301231
}
""".trimIndent()
context("When: decoded") {
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
test("parse") {
val expected = FactorioEvent(
data = EntityData(
name = "character",
type = "character",
active = true,
health = 250.0,
healthRatio = 1.0,
surfaceIndex = 1,
unitNumber = 1u,
playerIndex = null,
position = PositionData(
x = 37.859375,
y = 81.14453125,
type = PositionType.MAP,
)
),
eventType = "on_player_changed_position",
modVersion = "0.2.1",
tick = 2301231u
)
actual shouldBe expected
expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaEntity
}
test("Then: expect encode equals json") {
val encoded = jsonMapperKafkatorio.encodeToString(actual)
encoded.shouldEqualJson(json)
}
}
}
})

View file

@ -1,176 +0,0 @@
package dev.adamko.kafkatorio.events.schema
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.equality.shouldBeEqualToComparingFields
import io.kotest.matchers.shouldBe
import kotlinx.serialization.decodeFromString
import org.intellij.lang.annotations.Language
class FactorioEventTest : BehaviorSpec({
Given("json on_player_joined_game") {
@Language("JSON")
val json = """
{
"data": {
"objectName": "LuaPlayer",
"name": "fredthedeadhead",
"characterUnitNumber": 1,
"associatedCharactersUnitNumbers": {},
"position": {
"type": "MAP",
"x": 30.65625,
"y": 84.07421875
},
"colour": {
"red": 0.869000017642974853515625,
"green": 0.5,
"blue": 0.12999999523162841796875,
"alpha": 0.5
},
"chatColour": {
"red": 1,
"green": 0.62999999523162841796875,
"blue": 0.259000003337860107421875,
"alpha": 1
},
"lastOnline": 2287061
},
"packetType": "EVENT",
"eventType": "on_player_joined_game",
"modVersion": "0.2.1",
"tick": 2287072
}
""".trimIndent()
Then("parse") {
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
val expected = FactorioEvent(
data = PlayerData(
name = "fredthedeadhead",
characterUnitNumber = 1u,
associatedCharactersUnitNumbers = emptyList(),
position = PositionData(
type = PositionType.MAP,
x = 30.65625,
y = 84.07421875,
),
colour = Colour(
red = 0.869000017642974853515625f,
green = 0.5f,
blue = 0.12999999523162841796875f,
alpha = 0.5f
),
chatColour = Colour(
red = 1f,
green = 0.62999999523162841796875f,
blue = 0.259000003337860107421875f,
alpha = 1f
),
lastOnline = 2287061u
),
eventType = "on_player_joined_game",
modVersion = "0.2.1",
tick = 2287072u
)
actual shouldBeEqualToComparingFields expected
expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaPlayer
}
}
Given("json surface") {
@Language("JSON")
val json = """
{
"data": {
"objectName": "LuaSurface",
"name": "nauvis",
"index": 1,
"daytime": 0.749480000092057618843455202295444905757904052734375
},
"packetType": "EVENT",
"eventType": "on_tick",
"modVersion": "0.2.1",
"tick": 2301240
}
""".trimIndent()
Then("parse") {
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
val expected = FactorioEvent(
data = SurfaceData(
name = "nauvis",
index = 1u,
daytime = 0.749480000092057618843455202295444905757904052734375
),
eventType = "on_tick",
modVersion = "0.2.1",
tick = 2301240u
)
actual shouldBeEqualToComparingFields expected
expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaSurface
}
}
Given("LuaEntity on_player_changed_position") {
@Language("JSON")
val json = """
{
"data": {
"objectName": "LuaEntity",
"name": "character",
"type": "character",
"active": true,
"health": 250,
"healthRatio": 1,
"surfaceIndex": 1,
"unitNumber": 1,
"position": {
"type": "MAP",
"x": 37.859375,
"y": 81.14453125
}
},
"packetType": "EVENT",
"eventType": "on_player_changed_position",
"modVersion": "0.2.1",
"tick": 2301231
}
""".trimIndent()
Then("parse") {
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
val expected = FactorioEvent(
data = EntityData(
name = "character",
type = "character",
active = true,
health = 250.0,
healthRatio = 1.0,
surfaceIndex = 1,
unitNumber = 1u,
playerIndex = null,
position = PositionData(
x = 37.859375,
y = 81.14453125,
type = PositionType.MAP,
)
),
eventType = "on_player_changed_position",
modVersion = "0.2.1",
tick = 2301231u
)
actual shouldBeEqualToComparingFields expected
expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaEntity
}
}
})