chunk pngs almost working...

- rm yarn lock, it should be in ./gradle/kotlin-js-store
 - move kafka extensions to another project, kotka-streams
 - move prototypes to their own package
 - create a Factorio command for emitting prototypes
 - add bounding box to chunk updates
 - bump typed-factorio version
 - fix MapEntityPosition -> MapChunkPosition x/y rounding
 - lots of work on the Kafka Streams topology
This commit is contained in:
Adam 2022-01-16 23:16:09 +01:00
parent 49ad3654a3
commit 8533be0af8
47 changed files with 1097 additions and 4179 deletions

View file

@ -20,7 +20,7 @@ kotlin {
}
}
@Suppress("UnstableApiUsage") // enforcedPlatform is incubating
@Suppress("UnstableApiUsage") // platform + version catalogs is incubating
sourceSets {
all {

View file

@ -19,8 +19,8 @@ data class MapEntityPosition(
) {
fun toMapChunkPosition() = MapChunkPosition(
(x / MAP_CHUNK_SIZE).roundToInt(),
(y / MAP_CHUNK_SIZE).roundToInt(),
(x / MAP_CHUNK_SIZE).toInt(),
(y / MAP_CHUNK_SIZE).toInt(),
)
}
@ -36,10 +36,17 @@ data class MapChunkPosition(
val x: Int,
val y: Int,
) {
fun toMapEntityPosition() = MapEntityPosition(
x * MAP_CHUNK_SIZE.toDouble(),
y * MAP_CHUNK_SIZE.toDouble(),
)
fun toMapTilePosition() = MapChunkPosition(
x * MAP_CHUNK_SIZE,
y * MAP_CHUNK_SIZE,
)
}
/**
@ -62,6 +69,14 @@ data class MapTilePosition(
}
@Serializable
data class MapBoundingBox(
val topLeft: MapTilePosition,
val bottomRight: MapTilePosition,
)
/**
* Red, green, blue and alpha values, all in range `[0, 1]` or all in range `[0, 255]` if any
* value is > 1.
@ -81,7 +96,7 @@ data class Colour(
) {
/** True if any value is greater than 1, so the values are hexadecimal. */
fun isDecimal(): Boolean {
fun isHexadecimal(): Boolean {
return red > 1f
|| green > 1f
|| blue > 1f
@ -89,9 +104,9 @@ data class Colour(
}
/** True if all values are between `[0..1]`. */
fun isPercentage(): Boolean = !isDecimal()
fun isPercentage(): Boolean = !isHexadecimal()
fun asDecimal() = if (isPercentage()) {
fun asHexadecimal() = if (isPercentage()) {
Colour(
(red * 255).coerceIn(0f..255f),
(green * 255).coerceIn(0f..255f),

View file

@ -1,10 +1,7 @@
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
@ -12,10 +9,9 @@ data class FactorioConfigurationUpdate(
override val modVersion: String,
val factorioData: FactorioGameDataUpdate,
val allMods: List<FactorioModInfo>,
val prototypes: List<FactorioPrototype>,
) : KafkatorioPacket() {
@EncodeDefault
override val packetType = PacketType.CONFIG
override val packetType = PacketType.CONFIG
}
@Serializable

View file

@ -119,6 +119,7 @@ data class SurfaceData(
data class MapChunk(
val tiles: MapTiles,
val position: MapChunkPosition,
val area: MapBoundingBox,
) : FactorioObjectData() {
@EncodeDefault
override val objectName = ObjectName.MapChunk

View file

@ -10,6 +10,16 @@ import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
@Serializable
data class FactorioPrototypes(
override val modVersion: String,
val prototypes: List<FactorioPrototype>,
) : KafkatorioPacket() {
@EncodeDefault
override val packetType = PacketType.PROTOTYPES
}
@Serializable(with = FactorioPrototypeSerializer::class)
sealed class FactorioPrototype {
@EncodeDefault
@ -49,6 +59,7 @@ data class MapTilePrototype(
val name: String,
val layer: UInt,
val mapColour: Colour,
@Serializable(with = FactorioJsonListSerializer::class)
val collisionMasks: List<String>,
val order: String,
/** Can the tile be mined for resources? */

View file

@ -10,8 +10,17 @@ import kotlinx.serialization.json.JsonTransformingSerializer
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
val jsonMapperKafkatorio = Json {
prettyPrint = true
prettyPrintIndent = " "
// serializersModule = FactorioEvent.kxsModule
// serializersModule = KafkatorioPacket.kxsModule + FactorioEvent.kxsModule
// serializersModule = SerializersModule { }
}
/** Factorio outputs lists as Json objects - this serializer converts an object back to a list. */
// actually I'm not sure that it does - I think *empty* lists get encoded as *empty* objects
internal class ListAsObjectSerializer<T>(dataSerializer: KSerializer<T>) :
JsonTransformingSerializer<List<T>>(ListSerializer(dataSerializer)) {
@ -26,10 +35,18 @@ internal class ListAsObjectSerializer<T>(dataSerializer: KSerializer<T>) :
)
}
val jsonMapperKafkatorio = Json {
prettyPrint = true
prettyPrintIndent = " "
// serializersModule = FactorioEvent.kxsModule
// serializersModule = KafkatorioPacket.kxsModule + FactorioEvent.kxsModule
// serializersModule = SerializersModule { }
/** Factorio outputs lists as Json objects - this serializer converts an object back to a list. */
// actually I'm not sure that it does - I think *empty* lists get encoded as *empty* objects
internal class FactorioJsonListSerializer<T>(dataSerializer: KSerializer<T>) :
JsonTransformingSerializer<List<T>>(ListSerializer(dataSerializer)) {
override fun transformDeserialize(element: JsonElement): JsonElement {
return if (element is JsonObject) {
JsonArray(emptyList())
} else {
element
}
}
}

View file

@ -20,6 +20,7 @@ sealed class KafkatorioPacket {
enum class PacketType {
EVENT,
CONFIG,
PROTOTYPES,
}
}
@ -41,6 +42,7 @@ object KafkatorioPacketSerializer : JsonContentPolymorphicSerializer<KafkatorioP
return when (type) {
KafkatorioPacket.PacketType.EVENT -> FactorioEvent.serializer()
KafkatorioPacket.PacketType.CONFIG -> FactorioConfigurationUpdate.serializer()
KafkatorioPacket.PacketType.PROTOTYPES -> FactorioPrototypes.serializer()
null ->
throw Exception("Unknown KafkatorioPacket ${key}: '$type' ")
}

View file

@ -0,0 +1,45 @@
package dev.adamko.kafkatorio.events.schema
import io.kotest.core.spec.style.BehaviorSpec
import kotlinx.serialization.decodeFromString
class PrototypesTest : BehaviorSpec(
{
Given("Prototypes Json") {
//Language=JSON
val raw = """
{
"modVersion":"0.2.4",
"packetType":"PROTOTYPES",
"prototypes":[
{
"prototypeObjectName":"LuaTilePrototype",
"name":"tile-unknown",
"order":"z-a",
"layer":0,
"collisionMasks":{
},
"mapColour":{
"red":0,
"green":0,
"blue":0,
"alpha":255
},
"canBeMined":false
}
]
}
""".trimIndent()
Then("expect can be parsed") {
val data = jsonMapperKafkatorio.decodeFromString<KafkatorioPacket>(raw)
println(data)
}
}
}
) {
companion object {
}
}

View file

@ -16,6 +16,8 @@ fun main(args: Array<String>) {
addAll(KafkatorioPacket::class.sealedSubclasses)
addAll(FactorioObjectData::class.sealedSubclasses)
addAll(FactorioPrototype::class.sealedSubclasses)
add(FactorioPrototypes::class)
add(FactorioConfigurationUpdate::class)
},
mappings = mapOf(
// builtin Factorio numeric types > `typed-factorio/generated/builtin-types.d.ts`
@ -40,7 +42,6 @@ fun main(args: Array<String>) {
println(definitions)
}
else -> {
val outPath = Path(filename)
outPath.createDirectories()
@ -64,17 +65,18 @@ private fun splitDefinitions(definitions: String): Map<String, String> {
.split("\n\n")
.groupBy { def ->
when {
"extends FactorioObjectData" in def ||
"interface FactorioObjectData" in def ||
"type ObjectName" in def -> "object-data.d.ts"
"extends FactorioPrototype" in def ||
"interface FactorioPrototype" in def ||
"type PrototypeObjectName" in def -> "prototype.d.ts"
"extends FactorioConfigurationUpdate" in def ||
"interface FactorioConfigurationUpdate" in def ||
"FactorioGameDataUpdate" in def ||
"FactorioModInfo" in def -> "config-update.d.ts"
else -> "schema.d.ts"
"extends FactorioObjectData " in def ||
"interface FactorioObjectData " in def ||
"type ObjectName " in def -> "object-data.d.ts"
"extends FactorioPrototype " in def ||
"interface FactorioPrototypes " in def ||
"interface FactorioPrototype " in def ||
"type PrototypeObjectName " in def -> "prototype.d.ts"
"extends FactorioConfigurationUpdate " in def ||
"interface FactorioConfigurationUpdate " in def ||
"FactorioGameDataUpdate " in def ||
"FactorioModInfo " in def -> "config-update.d.ts"
else -> "schema.d.ts"
}
}
.mapValues { (_, def) ->