From beb73d158484534e9fae6a87a7fa8e96491d5d4a Mon Sep 17 00:00:00 2001 From: Adam <897017+aSemy@users.noreply.github.com> Date: Sun, 9 Jan 2022 14:01:48 +0100 Subject: [PATCH] - make tests multi-platform - fix polymorphism finally??? --- .kotlin-js-store/yarn.lock | 154 +++++++++++++- modules/events-schema/build.gradle.kts | 2 + .../events/schema/factorioConfiguration.kt | 8 +- .../events/schema/factorioEvents.kt | 82 ++++--- .../events/schema/factorioLuaObjects.kt | 62 +++++- .../adamko/kafkatorio/events/schema/json.kt | 2 +- .../events/schema/kafkatorioPacket.kt | 28 ++- .../events/schema/FactorioEventTest.kt | 200 ++++++++++++++++++ .../events/schema/FactorioEventTest.kt | 176 --------------- 9 files changed, 471 insertions(+), 243 deletions(-) create mode 100644 modules/events-schema/src/commonTest/kotlin/dev/adamko/kafkatorio/events/schema/FactorioEventTest.kt delete mode 100644 modules/events-schema/src/jvmTest/kotlin/dev/adamko/kafkatorio/events/schema/FactorioEventTest.kt diff --git a/.kotlin-js-store/yarn.lock b/.kotlin-js-store/yarn.lock index 7a7afaa..8f53c73 100644 --- a/.kotlin-js-store/yarn.lock +++ b/.kotlin-js-store/yarn.lock @@ -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" diff --git a/modules/events-schema/build.gradle.kts b/modules/events-schema/build.gradle.kts index a22817b..f49820c 100644 --- a/modules/events-schema/build.gradle.kts +++ b/modules/events-schema/build.gradle.kts @@ -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") diff --git a/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioConfiguration.kt b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioConfiguration.kt index ee45182..28787fa 100644 --- a/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioConfiguration.kt +++ b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioConfiguration.kt @@ -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, val prototypes: List, ) : KafkatorioPacket() { +// @Transient + + @EncodeDefault override val packetType = PacketType.CONFIG } diff --git a/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioEvents.kt b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioEvents.kt index badb888..0228337 100644 --- a/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioEvents.kt +++ b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioEvents.kt @@ -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( +//@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::class -) { - - override fun selectDeserializer(element: JsonElement): DeserializationStrategy> { - - 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::class +//) { +// +// override fun selectDeserializer(element: JsonElement): DeserializationStrategy> { +// +// 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) +// } +//} diff --git a/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioLuaObjects.kt b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioLuaObjects.kt index f1ab819..d2df5b9 100644 --- a/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioLuaObjects.kt +++ b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioLuaObjects.kt @@ -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::class +) { + private val key = + FactorioObjectData::objectName.name +// "objectName" + + override fun selectDeserializer(element: JsonElement): DeserializationStrategy { + + 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, @@ -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, ) : 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 } diff --git a/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/json.kt b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/json.kt index 78f26d5..42551b0 100644 --- a/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/json.kt +++ b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/json.kt @@ -29,7 +29,7 @@ internal class ListAsObjectSerializer(dataSerializer: KSerializer) : val jsonMapperKafkatorio = Json { prettyPrint = true prettyPrintIndent = " " - serializersModule = FactorioEvent.kxsModule +// serializersModule = FactorioEvent.kxsModule // serializersModule = KafkatorioPacket.kxsModule + FactorioEvent.kxsModule // serializersModule = SerializersModule { } } diff --git a/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/kafkatorioPacket.kt b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/kafkatorioPacket.kt index 702542f..c99b231 100644 --- a/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/kafkatorioPacket.kt +++ b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/kafkatorioPacket.kt @@ -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::class ) { - private const val key = "packetType" + private val key = + KafkatorioPacket::packetType.name +// "packetType" override fun selectDeserializer(element: JsonElement): DeserializationStrategy { @@ -33,13 +45,15 @@ object KafkatorioPacketSerializer : JsonContentPolymorphicSerializer + 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' ") } } } diff --git a/modules/events-schema/src/commonTest/kotlin/dev/adamko/kafkatorio/events/schema/FactorioEventTest.kt b/modules/events-schema/src/commonTest/kotlin/dev/adamko/kafkatorio/events/schema/FactorioEventTest.kt new file mode 100644 index 0000000..aad3502 --- /dev/null +++ b/modules/events-schema/src/commonTest/kotlin/dev/adamko/kafkatorio/events/schema/FactorioEventTest.kt @@ -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) + } + } + + } +}) diff --git a/modules/events-schema/src/jvmTest/kotlin/dev/adamko/kafkatorio/events/schema/FactorioEventTest.kt b/modules/events-schema/src/jvmTest/kotlin/dev/adamko/kafkatorio/events/schema/FactorioEventTest.kt deleted file mode 100644 index 04625ed..0000000 --- a/modules/events-schema/src/jvmTest/kotlin/dev/adamko/kafkatorio/events/schema/FactorioEventTest.kt +++ /dev/null @@ -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 - } - } - -})