update events schema
- unwrap value classes when generating TS - add value classes for some data types - add FactorioEventUpdates (for new incremental event updates) - use static lists for enum values (better performance) - add LuaControl for sharing Player/Entity fields
This commit is contained in:
parent
e989d25a3c
commit
8f9ebdb1e1
13 changed files with 396 additions and 67 deletions
|
|
@ -6,30 +6,6 @@ interface FactorioObjectData {
|
||||||
objectName: ObjectName;
|
objectName: ObjectName;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PlayerData extends FactorioObjectData {
|
|
||||||
associatedCharactersUnitNumbers: uint[];
|
|
||||||
characterUnitNumber: uint | null;
|
|
||||||
chatColour: Colour;
|
|
||||||
colour: Colour;
|
|
||||||
lastOnline: uint;
|
|
||||||
name: string;
|
|
||||||
objectName: ObjectName;
|
|
||||||
position: MapEntityPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EntityData extends FactorioObjectData {
|
|
||||||
active: boolean;
|
|
||||||
health: double | null;
|
|
||||||
healthRatio: double;
|
|
||||||
name: string;
|
|
||||||
objectName: ObjectName;
|
|
||||||
playerIndex: uint | null;
|
|
||||||
position: MapEntityPosition;
|
|
||||||
surfaceIndex: int;
|
|
||||||
type: string;
|
|
||||||
unitNumber: uint | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SurfaceData extends FactorioObjectData {
|
interface SurfaceData extends FactorioObjectData {
|
||||||
daytime: double;
|
daytime: double;
|
||||||
index: uint;
|
index: uint;
|
||||||
|
|
@ -39,7 +15,7 @@ interface SurfaceData extends FactorioObjectData {
|
||||||
|
|
||||||
interface MapTiles extends FactorioObjectData {
|
interface MapTiles extends FactorioObjectData {
|
||||||
objectName: ObjectName;
|
objectName: ObjectName;
|
||||||
surfaceIndex: int;
|
surfaceIndex: uint;
|
||||||
tiles: MapTile[];
|
tiles: MapTile[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ interface FactorioPrototypes extends KafkatorioPacket {
|
||||||
interface MapTilePrototype extends FactorioPrototype {
|
interface MapTilePrototype extends FactorioPrototype {
|
||||||
canBeMined: boolean;
|
canBeMined: boolean;
|
||||||
collisionMasks: string[];
|
collisionMasks: string[];
|
||||||
layer: uint;
|
layer: int;
|
||||||
mapColour: Colour;
|
mapColour: Colour;
|
||||||
name: string;
|
name: string;
|
||||||
order: string;
|
order: string;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,17 @@ interface FactorioEvent extends KafkatorioPacket {
|
||||||
tick: uint;
|
tick: uint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MapEntityPosition {
|
||||||
|
x: double;
|
||||||
|
y: double;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FactorioLuaControl {
|
||||||
|
force: uint;
|
||||||
|
position: MapEntityPosition;
|
||||||
|
surface: uint;
|
||||||
|
}
|
||||||
|
|
||||||
interface Colour {
|
interface Colour {
|
||||||
alpha: float;
|
alpha: float;
|
||||||
blue: float;
|
blue: float;
|
||||||
|
|
@ -22,9 +33,31 @@ interface Colour {
|
||||||
red: float;
|
red: float;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MapEntityPosition {
|
interface PlayerData extends FactorioObjectData, FactorioLuaControl {
|
||||||
x: double;
|
associatedCharactersUnitNumbers: uint[];
|
||||||
y: double;
|
characterUnitNumber: uint | null;
|
||||||
|
chatColour: Colour;
|
||||||
|
colour: Colour;
|
||||||
|
force: uint;
|
||||||
|
lastOnline: uint;
|
||||||
|
name: string;
|
||||||
|
objectName: ObjectName;
|
||||||
|
position: MapEntityPosition;
|
||||||
|
surface: uint;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface EntityData extends FactorioObjectData, FactorioLuaControl {
|
||||||
|
active: boolean;
|
||||||
|
force: uint;
|
||||||
|
health: double | null;
|
||||||
|
healthRatio: double;
|
||||||
|
name: string;
|
||||||
|
objectName: ObjectName;
|
||||||
|
playerIndex: uint | null;
|
||||||
|
position: MapEntityPosition;
|
||||||
|
surface: uint;
|
||||||
|
type: string;
|
||||||
|
unitNumber: uint | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MapTilePosition {
|
interface MapTilePosition {
|
||||||
|
|
@ -46,3 +79,53 @@ interface MapTile {
|
||||||
position: MapTilePosition;
|
position: MapTilePosition;
|
||||||
prototypeName: string;
|
prototypeName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FactorioEventUpdateType = "PLAYER" | "MAP_CHUNK" | "ENTITY";
|
||||||
|
|
||||||
|
interface FactorioEventUpdate {
|
||||||
|
updateType: FactorioEventUpdateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PlayerUpdate extends FactorioEventUpdate {
|
||||||
|
characterUnitNumber: uint | null;
|
||||||
|
chatColour: Colour | null;
|
||||||
|
colour: Colour | null;
|
||||||
|
disconnectReason: string | null;
|
||||||
|
forceIndex: uint | null;
|
||||||
|
index: uint;
|
||||||
|
isAdmin: boolean | null;
|
||||||
|
isConnected: boolean | null;
|
||||||
|
isShowOnMap: boolean | null;
|
||||||
|
isSpectator: boolean | null;
|
||||||
|
lastOnline: uint | null;
|
||||||
|
name: string | null;
|
||||||
|
onlineTime: uint | null;
|
||||||
|
position: MapEntityPosition | null;
|
||||||
|
surfaceIndex: uint | null;
|
||||||
|
tag: string | null;
|
||||||
|
updateType: FactorioEventUpdateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface EntityUpdate extends FactorioEventUpdate {
|
||||||
|
chunkPosition: MapChunkPosition | null;
|
||||||
|
graphicsVariation: number | null;
|
||||||
|
health: float | null;
|
||||||
|
isActive: boolean | null;
|
||||||
|
isRotatable: boolean | null;
|
||||||
|
lastUser: int | null;
|
||||||
|
localisedDescription: string | null;
|
||||||
|
localisedName: string | null;
|
||||||
|
name: string | null;
|
||||||
|
prototype: string | null;
|
||||||
|
type: string | null;
|
||||||
|
unitNumber: uint;
|
||||||
|
updateType: FactorioEventUpdateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MapChunkUpdate extends FactorioEventUpdate {
|
||||||
|
chunkPosition: MapChunkPosition;
|
||||||
|
isDeleted: boolean | null;
|
||||||
|
surfaceIndex: uint;
|
||||||
|
tiles: MapTiles | null;
|
||||||
|
updateType: FactorioEventUpdateType;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,18 @@
|
||||||
package dev.adamko.kafkatorio.events.schema
|
package dev.adamko.kafkatorio.events.schema
|
||||||
|
|
||||||
|
import kotlin.jvm.JvmInline
|
||||||
import kotlinx.serialization.EncodeDefault
|
import kotlinx.serialization.EncodeDefault
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
||||||
const val MAP_CHUNK_SIZE = 32
|
const val MAP_CHUNK_SIZE = 32
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@JvmInline
|
||||||
|
value class Tick(val value: UInt)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Coordinates of a [EntityData] on a map.
|
* Coordinates of a [EntityData] on a map.
|
||||||
*
|
*
|
||||||
|
|
@ -60,7 +67,7 @@ data class MapBoundingBox(
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Colour(
|
data class Colour(
|
||||||
@EncodeDefault
|
@EncodeDefault // remove encode default?
|
||||||
val red: Float = 0f,
|
val red: Float = 0f,
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
val green: Float = 0f,
|
val green: Float = 0f,
|
||||||
|
|
@ -74,7 +81,7 @@ data class Colour(
|
||||||
/** Size-efficient version of [Colour] (`4*4` bytes vs `4*1` bytes) */
|
/** Size-efficient version of [Colour] (`4*4` bytes vs `4*1` bytes) */
|
||||||
@Serializable
|
@Serializable
|
||||||
data class ColourHex(
|
data class ColourHex(
|
||||||
@EncodeDefault
|
@EncodeDefault // remove encode default?
|
||||||
val red: UByte = UByte.MIN_VALUE,
|
val red: UByte = UByte.MIN_VALUE,
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
val green: UByte = UByte.MIN_VALUE,
|
val green: UByte = UByte.MIN_VALUE,
|
||||||
|
|
@ -91,6 +98,6 @@ data class ColourHex(
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MapTile(
|
data class MapTile(
|
||||||
val prototypeName: String,
|
val prototypeName: PrototypeName,
|
||||||
val position: MapTilePosition,
|
val position: MapTilePosition,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
package dev.adamko.kafkatorio.events.schema
|
||||||
|
|
||||||
|
import kotlinx.serialization.DeserializationStrategy
|
||||||
|
import kotlinx.serialization.EncodeDefault
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable(with = FactorioEventUpdate.Companion.JsonSerializer::class)
|
||||||
|
sealed class FactorioEventUpdate {
|
||||||
|
|
||||||
|
@EncodeDefault
|
||||||
|
abstract val updateType: FactorioEventUpdateType
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
enum class FactorioEventUpdateType {
|
||||||
|
PLAYER,
|
||||||
|
MAP_CHUNK,
|
||||||
|
ENTITY,
|
||||||
|
;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val values: List<FactorioEventUpdateType> = values().toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
object JsonSerializer : JsonContentPolymorphicSerializer<FactorioEventUpdate>(
|
||||||
|
FactorioEventUpdate::class
|
||||||
|
) {
|
||||||
|
private val key = FactorioEventUpdate::updateType.name
|
||||||
|
|
||||||
|
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out FactorioEventUpdate> {
|
||||||
|
|
||||||
|
val type = element
|
||||||
|
.jsonObject[key]
|
||||||
|
?.jsonPrimitive
|
||||||
|
?.contentOrNull
|
||||||
|
?.let { json ->
|
||||||
|
FactorioEventUpdateType.values.firstOrNull { it.name == json }
|
||||||
|
}
|
||||||
|
|
||||||
|
requireNotNull(type) { "Unknown FactorioEventUpdate $key: $element" }
|
||||||
|
|
||||||
|
return when (type) {
|
||||||
|
FactorioEventUpdateType.PLAYER -> PlayerUpdate.serializer()
|
||||||
|
FactorioEventUpdateType.MAP_CHUNK -> TODO()
|
||||||
|
FactorioEventUpdateType.ENTITY -> EntityUpdate.serializer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class PlayerUpdate(
|
||||||
|
val index: PlayerIndex,
|
||||||
|
|
||||||
|
val characterUnitNumber: UnitNumber? = null,
|
||||||
|
val chatColour: Colour? = null,
|
||||||
|
val colour: Colour? = null,
|
||||||
|
val name: String? = null,
|
||||||
|
|
||||||
|
val disconnectReason: String? = null,
|
||||||
|
val forceIndex: ForceIndex? = null,
|
||||||
|
val isAdmin: Boolean? = null,
|
||||||
|
val isConnected: Boolean? = null,
|
||||||
|
val isShowOnMap: Boolean? = null,
|
||||||
|
val isSpectator: Boolean? = null,
|
||||||
|
val lastOnline: Tick? = null,
|
||||||
|
val onlineTime: Tick? = null,
|
||||||
|
val position: MapEntityPosition? = null,
|
||||||
|
val surfaceIndex: SurfaceIndex? = null,
|
||||||
|
val tag: String? = null,
|
||||||
|
) : FactorioEventUpdate() {
|
||||||
|
@EncodeDefault
|
||||||
|
override val updateType: FactorioEventUpdateType = FactorioEventUpdateType.PLAYER
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class EntityUpdate(
|
||||||
|
/**
|
||||||
|
* A [unitNumber] is required for caching, else the Entity Update should be emitted without
|
||||||
|
* debouncing/throttling
|
||||||
|
*/
|
||||||
|
val unitNumber: UnitNumber,
|
||||||
|
|
||||||
|
val name: String? = null,
|
||||||
|
val type: String? = null,
|
||||||
|
val chunkPosition: MapChunkPosition? = null,
|
||||||
|
val graphicsVariation: UShort? = null,
|
||||||
|
val health: Float? = null,
|
||||||
|
val isActive: Boolean? = null,
|
||||||
|
val isRotatable: Boolean? = null,
|
||||||
|
val lastUser: UInt? = null,
|
||||||
|
val localisedDescription: String? = null,
|
||||||
|
val localisedName: String? = null,
|
||||||
|
val prototype: PrototypeName? = null,
|
||||||
|
) : FactorioEventUpdate() {
|
||||||
|
@EncodeDefault
|
||||||
|
override val updateType: FactorioEventUpdateType = FactorioEventUpdateType.ENTITY
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MapChunkUpdate(
|
||||||
|
val chunkPosition: MapChunkPosition,
|
||||||
|
val surfaceIndex: SurfaceIndex,
|
||||||
|
|
||||||
|
/** Might be a partial list of updated tiles */
|
||||||
|
val tiles: MapTiles? = null,
|
||||||
|
val isDeleted: Boolean? = null,
|
||||||
|
) : FactorioEventUpdate() {
|
||||||
|
@EncodeDefault
|
||||||
|
override val updateType: FactorioEventUpdateType = FactorioEventUpdateType.MAP_CHUNK
|
||||||
|
}
|
||||||
|
|
@ -10,7 +10,7 @@ data class FactorioEvent(
|
||||||
/** the initial Factorio event (`defines.events`) trigger */
|
/** the initial Factorio event (`defines.events`) trigger */
|
||||||
val eventType: String,
|
val eventType: String,
|
||||||
/** game time */
|
/** game time */
|
||||||
val tick: UInt,
|
val tick: Tick,
|
||||||
val data: FactorioObjectData,
|
val data: FactorioObjectData,
|
||||||
) : KafkatorioPacket() {
|
) : KafkatorioPacket() {
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
package dev.adamko.kafkatorio.events.schema
|
||||||
|
|
||||||
|
import kotlin.jvm.JvmInline
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique ID associated with this surface
|
||||||
|
*
|
||||||
|
* See [`LuaSurface.index`](https://lua-api.factorio.com/latest/LuaSurface.html#LuaSurface.index)
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
@JvmInline
|
||||||
|
value class SurfaceIndex(val value: UInt)
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@JvmInline
|
||||||
|
value class ForceIndex(val value: UInt)
|
||||||
|
|
||||||
|
|
||||||
|
/** The player's index in `LuaGameScript::players` */
|
||||||
|
@Serializable
|
||||||
|
@JvmInline
|
||||||
|
value class PlayerIndex(val value: UInt)
|
||||||
|
|
||||||
|
|
||||||
|
/** This is universally unique for every entity that has one, for the lifetime of a whole game. */
|
||||||
|
@Serializable
|
||||||
|
@JvmInline
|
||||||
|
value class UnitNumber(val value: UInt)
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@JvmInline
|
||||||
|
value class PrototypeName(val value: String)
|
||||||
|
|
@ -10,6 +10,7 @@ import kotlinx.serialization.json.contentOrNull
|
||||||
import kotlinx.serialization.json.jsonObject
|
import kotlinx.serialization.json.jsonObject
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
|
||||||
|
|
||||||
@Serializable(with = FactorioObjectDataJsonSerializer::class)
|
@Serializable(with = FactorioObjectDataJsonSerializer::class)
|
||||||
sealed class FactorioObjectData {
|
sealed class FactorioObjectData {
|
||||||
|
|
||||||
|
|
@ -41,8 +42,14 @@ sealed class FactorioObjectData {
|
||||||
// LuaTile,
|
// LuaTile,
|
||||||
LuaTiles,
|
LuaTiles,
|
||||||
ConsoleChatMessage,
|
ConsoleChatMessage,
|
||||||
|
;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val values: List<ObjectName> = values().toList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
object FactorioObjectDataJsonSerializer : JsonContentPolymorphicSerializer<FactorioObjectData>(
|
object FactorioObjectDataJsonSerializer : JsonContentPolymorphicSerializer<FactorioObjectData>(
|
||||||
FactorioObjectData::class
|
FactorioObjectData::class
|
||||||
|
|
@ -56,7 +63,7 @@ object FactorioObjectDataJsonSerializer : JsonContentPolymorphicSerializer<Facto
|
||||||
?.jsonPrimitive
|
?.jsonPrimitive
|
||||||
?.contentOrNull
|
?.contentOrNull
|
||||||
?.let { json ->
|
?.let { json ->
|
||||||
FactorioObjectData.ObjectName.values().firstOrNull { it.name == json }
|
FactorioObjectData.ObjectName.values.firstOrNull { it.name == json }
|
||||||
}
|
}
|
||||||
|
|
||||||
requireNotNull(type) { "Unknown FactorioObjectData $key: $element" }
|
requireNotNull(type) { "Unknown FactorioObjectData $key: $element" }
|
||||||
|
|
@ -74,48 +81,61 @@ object FactorioObjectDataJsonSerializer : JsonContentPolymorphicSerializer<Facto
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** [`LuaControl`](https://lua-api.factorio.com/latest/LuaControl.html) */
|
||||||
|
interface FactorioLuaControl {
|
||||||
|
val position: MapEntityPosition
|
||||||
|
val surface: SurfaceIndex
|
||||||
|
val force: ForceIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PlayerData(
|
data class PlayerData(
|
||||||
// @Serializable(with = FactorioJsonListSerializer::class)
|
override val force: ForceIndex,
|
||||||
|
override val position: MapEntityPosition,
|
||||||
|
override val surface: SurfaceIndex,
|
||||||
@Contextual
|
@Contextual
|
||||||
val associatedCharactersUnitNumbers: List<UInt>,
|
val associatedCharactersUnitNumbers: List<UnitNumber>,
|
||||||
val characterUnitNumber: UInt?,
|
val characterUnitNumber: UnitNumber?,
|
||||||
val name: String,
|
|
||||||
val position: MapEntityPosition,
|
|
||||||
val colour: Colour,
|
|
||||||
val chatColour: Colour,
|
val chatColour: Colour,
|
||||||
val lastOnline: UInt,
|
val colour: Colour,
|
||||||
) : FactorioObjectData() {
|
val lastOnline: Tick,
|
||||||
|
val name: String,
|
||||||
|
) : FactorioObjectData(), FactorioLuaControl {
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
override val objectName = ObjectName.LuaPlayer
|
override val objectName = ObjectName.LuaPlayer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class EntityData(
|
data class EntityData(
|
||||||
|
override val force: ForceIndex,
|
||||||
|
override val position: MapEntityPosition,
|
||||||
|
override val surface: SurfaceIndex,
|
||||||
val active: Boolean,
|
val active: Boolean,
|
||||||
val health: Double?,
|
val health: Double?,
|
||||||
val healthRatio: Double,
|
val healthRatio: Double,
|
||||||
val name: String,
|
val name: String,
|
||||||
val position: MapEntityPosition,
|
val playerIndex: PlayerIndex? = null,
|
||||||
val surfaceIndex: Int,
|
|
||||||
val type: String,
|
val type: String,
|
||||||
val unitNumber: UInt? = null,
|
val unitNumber: UnitNumber? = null,
|
||||||
val playerIndex: UInt? = null,
|
) : FactorioObjectData(), FactorioLuaControl {
|
||||||
) : FactorioObjectData() {
|
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
override val objectName = ObjectName.LuaEntity
|
override val objectName = ObjectName.LuaEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SurfaceData(
|
data class SurfaceData(
|
||||||
val daytime: Double,
|
val daytime: Double,
|
||||||
val index: UInt,
|
val index: SurfaceIndex,
|
||||||
val name: String,
|
val name: String,
|
||||||
) : FactorioObjectData() {
|
) : FactorioObjectData() {
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
override val objectName = ObjectName.LuaSurface
|
override val objectName = ObjectName.LuaSurface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** This isn't a Factorio Lua type, but a helpful collection of Chunk info */
|
/** This isn't a Factorio Lua type, but a helpful collection of Chunk info */
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MapChunk(
|
data class MapChunk(
|
||||||
|
|
@ -127,19 +147,21 @@ data class MapChunk(
|
||||||
override val objectName = ObjectName.MapChunk
|
override val objectName = ObjectName.MapChunk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** This isn't a Factorio Lua type, but a helpful collection of [MapTile]s */
|
/** This isn't a Factorio Lua type, but a helpful collection of [MapTile]s */
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MapTiles(
|
data class MapTiles(
|
||||||
val surfaceIndex: Int,
|
val surfaceIndex: SurfaceIndex,
|
||||||
val tiles: List<MapTile>,
|
val tiles: List<MapTile>,
|
||||||
) : FactorioObjectData() {
|
) : FactorioObjectData() {
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
override val objectName = ObjectName.LuaTiles
|
override val objectName = ObjectName.LuaTiles
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class ConsoleChatMessage(
|
data class ConsoleChatMessage(
|
||||||
val authorPlayerIndex: UInt?,
|
val authorPlayerIndex: PlayerIndex?,
|
||||||
val content: String,
|
val content: String,
|
||||||
) : FactorioObjectData() {
|
) : FactorioObjectData() {
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,12 @@ sealed class FactorioPrototype {
|
||||||
abstract val prototypeObjectName: PrototypeObjectName
|
abstract val prototypeObjectName: PrototypeObjectName
|
||||||
|
|
||||||
enum class PrototypeObjectName {
|
enum class PrototypeObjectName {
|
||||||
LuaTilePrototype
|
LuaTilePrototype,
|
||||||
|
;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val values: List<PrototypeObjectName> = values().toList()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,7 +50,7 @@ object FactorioPrototypeJsonSerializer : JsonContentPolymorphicSerializer<Factor
|
||||||
?.jsonPrimitive
|
?.jsonPrimitive
|
||||||
?.contentOrNull
|
?.contentOrNull
|
||||||
?.let { json ->
|
?.let { json ->
|
||||||
PrototypeObjectName.values().firstOrNull { it.name == json }
|
PrototypeObjectName.values.firstOrNull { it.name == json }
|
||||||
}
|
}
|
||||||
|
|
||||||
requireNotNull(type) { "Unknown FactorioPrototype ${key}: $element" }
|
requireNotNull(type) { "Unknown FactorioPrototype ${key}: $element" }
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,11 @@ sealed class KafkatorioPacket {
|
||||||
EVENT,
|
EVENT,
|
||||||
CONFIG,
|
CONFIG,
|
||||||
PROTOTYPES,
|
PROTOTYPES,
|
||||||
|
;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val values: List<PacketType> = values().toList()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,7 +42,7 @@ object KafkatorioPacketJsonSerializer : JsonContentPolymorphicSerializer<Kafkato
|
||||||
?.jsonPrimitive
|
?.jsonPrimitive
|
||||||
?.contentOrNull
|
?.contentOrNull
|
||||||
?.let { json ->
|
?.let { json ->
|
||||||
KafkatorioPacket.PacketType.values().firstOrNull { it.name == json }
|
KafkatorioPacket.PacketType.values.firstOrNull { it.name == json }
|
||||||
}
|
}
|
||||||
|
|
||||||
requireNotNull(type) { "Unknown KafkatorioPacket ${key}: $element" }
|
requireNotNull(type) { "Unknown KafkatorioPacket ${key}: $element" }
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,9 @@ class FactorioEventTest : FunSpec({
|
||||||
val expected = FactorioEvent(
|
val expected = FactorioEvent(
|
||||||
data = PlayerData(
|
data = PlayerData(
|
||||||
name = "fredthedeadhead",
|
name = "fredthedeadhead",
|
||||||
characterUnitNumber = 1u,
|
surface = SurfaceIndex(1u),
|
||||||
|
force = ForceIndex(1u),
|
||||||
|
characterUnitNumber = UnitNumber(1u),
|
||||||
associatedCharactersUnitNumbers = emptyList(),
|
associatedCharactersUnitNumbers = emptyList(),
|
||||||
position = MapEntityPosition(
|
position = MapEntityPosition(
|
||||||
x = 30.6,
|
x = 30.6,
|
||||||
|
|
@ -68,11 +70,11 @@ class FactorioEventTest : FunSpec({
|
||||||
blue = 0.25f,
|
blue = 0.25f,
|
||||||
alpha = 1f
|
alpha = 1f
|
||||||
),
|
),
|
||||||
lastOnline = 2287061u
|
lastOnline = Tick(2287061u)
|
||||||
),
|
),
|
||||||
eventType = "on_player_joined_game",
|
eventType = "on_player_joined_game",
|
||||||
modVersion = "0.2.1",
|
modVersion = "0.2.1",
|
||||||
tick = 2287072u
|
tick = Tick(2287072u)
|
||||||
)
|
)
|
||||||
|
|
||||||
actual shouldBe expected
|
actual shouldBe expected
|
||||||
|
|
@ -112,12 +114,12 @@ class FactorioEventTest : FunSpec({
|
||||||
val expected = FactorioEvent(
|
val expected = FactorioEvent(
|
||||||
data = SurfaceData(
|
data = SurfaceData(
|
||||||
name = "nauvis",
|
name = "nauvis",
|
||||||
index = 1u,
|
index = SurfaceIndex(1u),
|
||||||
daytime = 0.745
|
daytime = 0.745
|
||||||
),
|
),
|
||||||
eventType = "on_tick",
|
eventType = "on_tick",
|
||||||
modVersion = "0.2.1",
|
modVersion = "0.2.1",
|
||||||
tick = 2301240u
|
tick = Tick(2301240u)
|
||||||
)
|
)
|
||||||
|
|
||||||
actual shouldBe expected
|
actual shouldBe expected
|
||||||
|
|
@ -168,8 +170,9 @@ class FactorioEventTest : FunSpec({
|
||||||
active = true,
|
active = true,
|
||||||
health = 250.0,
|
health = 250.0,
|
||||||
healthRatio = 1.0,
|
healthRatio = 1.0,
|
||||||
surfaceIndex = 1,
|
surface = SurfaceIndex(1u),
|
||||||
unitNumber = 1u,
|
unitNumber = UnitNumber(1u),
|
||||||
|
force = ForceIndex(1u),
|
||||||
playerIndex = null,
|
playerIndex = null,
|
||||||
position = MapEntityPosition(
|
position = MapEntityPosition(
|
||||||
x = 37.5,
|
x = 37.5,
|
||||||
|
|
@ -178,7 +181,7 @@ class FactorioEventTest : FunSpec({
|
||||||
),
|
),
|
||||||
eventType = "on_player_changed_position",
|
eventType = "on_player_changed_position",
|
||||||
modVersion = "0.2.1",
|
modVersion = "0.2.1",
|
||||||
tick = 2301231u
|
tick = Tick(2301231u)
|
||||||
)
|
)
|
||||||
|
|
||||||
actual shouldBe expected
|
actual shouldBe expected
|
||||||
|
|
@ -245,7 +248,7 @@ class FactorioEventTest : FunSpec({
|
||||||
|
|
||||||
val expected = FactorioEvent(
|
val expected = FactorioEvent(
|
||||||
data = MapTiles(
|
data = MapTiles(
|
||||||
surfaceIndex = 1,
|
surfaceIndex = SurfaceIndex(1u),
|
||||||
tiles = listOf(
|
tiles = listOf(
|
||||||
MapTile(
|
MapTile(
|
||||||
prototypeName = "refined-concrete",
|
prototypeName = "refined-concrete",
|
||||||
|
|
@ -267,7 +270,7 @@ class FactorioEventTest : FunSpec({
|
||||||
),
|
),
|
||||||
eventType = "on_player_built_tile",
|
eventType = "on_player_built_tile",
|
||||||
modVersion = "0.2.2",
|
modVersion = "0.2.2",
|
||||||
tick = 2429929u
|
tick = Tick(2429929u)
|
||||||
)
|
)
|
||||||
|
|
||||||
actual shouldBe expected
|
actual shouldBe expected
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
package dev.adamko.kafkatorio.events.schema
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.KTypeProjection
|
||||||
|
import kotlin.reflect.full.createType
|
||||||
|
import kotlin.reflect.full.declaredMemberProperties
|
||||||
|
import kotlin.reflect.full.withNullability
|
||||||
|
import me.ntrrgc.tsGenerator.ClassTransformer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 'Unwrap' value classes
|
||||||
|
*/
|
||||||
|
object ValueClassTransformer : ClassTransformer {
|
||||||
|
|
||||||
|
override fun transformPropertyType(type: KType, property: KProperty<*>, klass: KClass<*>): KType {
|
||||||
|
|
||||||
|
val classifier = type.classifier ?: return super.transformPropertyType(type, property, klass)
|
||||||
|
|
||||||
|
val valueClassType = unwrapValueClassType(type)
|
||||||
|
|
||||||
|
if (valueClassType != null) {
|
||||||
|
println("$klass has a value class $type -> $valueClassType")
|
||||||
|
return valueClassType
|
||||||
|
}
|
||||||
|
|
||||||
|
val hasValueClassTypeParameters = type.arguments
|
||||||
|
.mapNotNull { it.type?.classifier }
|
||||||
|
.filterIsInstance<KClass<*>>()
|
||||||
|
.any { it.isValue }
|
||||||
|
|
||||||
|
if (hasValueClassTypeParameters) {
|
||||||
|
|
||||||
|
val args = type.arguments.map { arg ->
|
||||||
|
when (val vct = unwrapValueClassType(arg.type)) {
|
||||||
|
null -> arg
|
||||||
|
else -> KTypeProjection(arg.variance, vct.withNullability(arg.type!!.isMarkedNullable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println("$klass has a prop with value class type parameters ${type.arguments} -> $args")
|
||||||
|
|
||||||
|
return classifier.createType(
|
||||||
|
arguments = args,
|
||||||
|
nullable = type.isMarkedNullable,
|
||||||
|
annotations = type.annotations,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.transformPropertyType(type, property, klass)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun unwrapValueClassType(type: KType?): KType? {
|
||||||
|
val klass = type?.classifier as? KClass<*> ?: return null
|
||||||
|
|
||||||
|
return when {
|
||||||
|
klass.isValue -> klass
|
||||||
|
.declaredMemberProperties
|
||||||
|
.first()
|
||||||
|
.returnType
|
||||||
|
.withNullability(type.isMarkedNullable)
|
||||||
|
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ fun main(args: Array<String>) {
|
||||||
addAll(FactorioPrototype::class.sealedSubclasses)
|
addAll(FactorioPrototype::class.sealedSubclasses)
|
||||||
add(FactorioPrototypes::class)
|
add(FactorioPrototypes::class)
|
||||||
add(FactorioConfigurationUpdate::class)
|
add(FactorioConfigurationUpdate::class)
|
||||||
|
addAll(FactorioEventUpdate::class.sealedSubclasses)
|
||||||
},
|
},
|
||||||
mappings = mapOf(
|
mappings = mapOf(
|
||||||
// builtin Factorio numeric types > `typed-factorio/generated/builtin-types.d.ts`
|
// builtin Factorio numeric types > `typed-factorio/generated/builtin-types.d.ts`
|
||||||
|
|
@ -31,16 +32,16 @@ fun main(args: Array<String>) {
|
||||||
ULong::class to "uint64",
|
ULong::class to "uint64",
|
||||||
),
|
),
|
||||||
classTransformers = listOf(
|
classTransformers = listOf(
|
||||||
|
ValueClassTransformer,
|
||||||
// PropertyNameTransformer,
|
// PropertyNameTransformer,
|
||||||
)
|
),
|
||||||
|
// voidType = VoidType.UNDEFINED,
|
||||||
)
|
)
|
||||||
|
|
||||||
val definitions = gen.definitionsText
|
val definitions = gen.definitionsText
|
||||||
|
|
||||||
when (val filename = args.firstOrNull()) {
|
when (val filename = args.firstOrNull()) {
|
||||||
null -> {
|
null -> println(definitions)
|
||||||
println(definitions)
|
|
||||||
}
|
|
||||||
else -> {
|
else -> {
|
||||||
val outPath = Path(filename)
|
val outPath = Path(filename)
|
||||||
outPath.createDirectories()
|
outPath.createDirectories()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue