- start code clean up by commenting out unused/deprecated code (start moving towards the 'event updates' Kafkatorio packets

- bring back the event Queue, and the command to emit lots of chunks
- allow setting the event update timeout directly when debouncing/throttling an update
This commit is contained in:
Adam 2022-03-14 00:05:15 +01:00
parent 1fbe0d87b0
commit 8d36111d9a
11 changed files with 613 additions and 636 deletions

View file

@ -11,7 +11,6 @@ require("./main/cache/cacheChecker")
script.on_configuration_changed((data: ConfigurationChangedData) => { script.on_configuration_changed((data: ConfigurationChangedData) => {
// runs whenever the version of the base game, or a mod, changes // runs whenever the version of the base game, or a mod, changes
initGlobal(true) initGlobal(true)
KafkatorioSettings.loadSettings() KafkatorioSettings.loadSettings()
emitConfigurationUpdate(data) emitConfigurationUpdate(data)

View file

@ -1,38 +1,11 @@
// Generated by TypeScriptGenerator - do not edit this file manually // Generated by TypeScriptGenerator - do not edit this file manually
type ObjectName = "LuaPlayer" | "LuaEntity" | "LuaSurface" | "MapChunk" | "LuaTiles" | "ConsoleChatMessage"; type ObjectName = "LuaSurface" | "ConsoleChatMessage";
interface FactorioObjectData { interface FactorioObjectData {
objectName: ObjectName; objectName: ObjectName;
} }
interface PlayerData extends FactorioObjectData, FactorioLuaControl {
associatedCharactersUnitNumbers: uint[];
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 | null;
name: string;
objectName: ObjectName;
playerIndex: uint | null;
position: MapEntityPosition;
surface: uint;
type: string;
unitNumber: uint | null;
}
interface SurfaceData extends FactorioObjectData { interface SurfaceData extends FactorioObjectData {
daytime: double; daytime: double;
index: uint; index: uint;
@ -40,19 +13,6 @@ interface SurfaceData extends FactorioObjectData {
objectName: ObjectName; objectName: ObjectName;
} }
interface MapTiles extends FactorioObjectData {
objectName: ObjectName;
surfaceIndex: uint;
tiles: MapTile[];
}
interface MapChunk extends FactorioObjectData {
area: MapBoundingBox;
objectName: ObjectName;
position: MapChunkPosition;
tiles: MapTiles;
}
interface ConsoleChatMessage extends FactorioObjectData { interface ConsoleChatMessage extends FactorioObjectData {
authorPlayerIndex: uint | null; authorPlayerIndex: uint | null;
content: string; content: string;

View file

@ -16,17 +16,6 @@ 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;
@ -34,33 +23,28 @@ interface Colour {
red: float; red: float;
} }
interface MapTilePosition {
x: int;
y: int;
}
interface MapBoundingBox {
bottomRight: MapTilePosition;
topLeft: MapTilePosition;
}
interface MapChunkPosition {
x: int;
y: int;
}
interface MapTile {
proto: string;
x: int;
y: int;
}
interface EntityIdentifiers { interface EntityIdentifiers {
name: string; name: string;
type: string; type: string;
unitNumber: uint | null; unitNumber: uint | null;
} }
interface EntityIdentifiersData extends EntityIdentifiers {
name: string;
type: string;
unitNumber: uint | null;
}
interface MapEntityPosition {
x: double;
y: double;
}
interface MapChunkPosition {
x: int;
y: int;
}
interface MapTileDictionary { interface MapTileDictionary {
protos: { [key: string]: string }; protos: { [key: string]: string };
tilesXY: { [key: string]: { [key: string]: string } }; tilesXY: { [key: string]: { [key: string]: string } };

View file

@ -32,8 +32,9 @@ export namespace EventUpdates {
public throttle<TYPE extends FactorioEventUpdateType>( public throttle<TYPE extends FactorioEventUpdateType>(
key: CacheKey<TYPE>, key: CacheKey<TYPE>,
mutate: CacheDataMutator<TYPE>, mutate: CacheDataMutator<TYPE>,
expirationDurationTicks?: uint,
) { ) {
this.update(key, mutate, false) this.update(key, mutate, false, expirationDurationTicks)
} }
@ -44,8 +45,9 @@ export namespace EventUpdates {
public debounce<TYPE extends FactorioEventUpdateType>( public debounce<TYPE extends FactorioEventUpdateType>(
key: CacheKey<TYPE>, key: CacheKey<TYPE>,
mutate: CacheDataMutator<TYPE>, mutate: CacheDataMutator<TYPE>,
expirationDurationTicks?: uint,
) { ) {
this.update(key, mutate, true) this.update(key, mutate, true, expirationDurationTicks)
} }
@ -53,12 +55,16 @@ export namespace EventUpdates {
key: CacheKey<TYPE>, key: CacheKey<TYPE>,
mutate: CacheDataMutator<TYPE>, mutate: CacheDataMutator<TYPE>,
resetLastUpdated: boolean, resetLastUpdated: boolean,
expirationDurationTicks?: uint,
) { ) {
const entry = this.getCacheEntry(key) ?? this.createCacheEntry(key, mutate) const entry: CacheEntry<TYPE> = this.getCacheEntry(key) ?? this.createCacheEntry(key, mutate)
mutate(entry.data) mutate(entry.data)
if (resetLastUpdated) { if (resetLastUpdated) {
entry.lastUpdatedTick = game.tick entry.lastUpdatedTick = game.tick
} }
if (expirationDurationTicks != undefined) {
entry.expirationDurationTicks = expirationDurationTicks
}
} }

View file

@ -1,7 +1,7 @@
import {emitPrototypes} from "../config-update/prototypes"; import {emitPrototypes} from "../config-update/prototypes";
import {Queue} from "../queue/queue";
import {initGlobal} from "../global-init"; import {initGlobal} from "../global-init";
import floor = math.floor; import floor = math.floor;
import {Queue} from "../queue/queue";
commands.add_command( commands.add_command(
@ -24,22 +24,24 @@ commands.add_command(
emitPrototypes() emitPrototypes()
} else if (paramUppercase.startsWith("CHUNKS")) { } else if (paramUppercase.startsWith("CHUNKS")) {
let size = paramUppercase.split(" ")?.[1] ?? null const size = paramUppercase.split(" ")?.[1] ?? null
let radius = (size != null) ? parseInt(size) : 1 let radius = (size != null) ? parseInt(size) : 1
// radius = Math.max(radius, 10)
if (e.player_index != undefined) { if (e.player_index != undefined) {
let player = game.players[e.player_index] let player = game.players[e.player_index]
let chunkPosition: ChunkPosition = { const chunkPosition: ChunkPosition = {
x: floor(player.position.x / 32), x: floor(player.position.x / 32),
y: floor(player.position.y / 32), y: floor(player.position.y / 32),
} }
let chunkXMin = chunkPosition.x - radius const chunkXMin = chunkPosition.x - radius
let chunkXMax = chunkPosition.x + radius const chunkXMax = chunkPosition.x + radius
let chunkYMin = chunkPosition.y - radius const chunkYMin = chunkPosition.y - radius
let chunkYMax = chunkPosition.y + radius const chunkYMax = chunkPosition.y + radius
// let i = 100
for (const [, surface] of game.surfaces) { for (const [, surface] of game.surfaces) {
for (const chunk of surface.get_chunks()) { for (const chunk of surface.get_chunks()) {
if ( if (
@ -48,7 +50,7 @@ commands.add_command(
(chunk.y >= chunkYMin && chunk.y <= chunkYMax) (chunk.y >= chunkYMin && chunk.y <= chunkYMax)
) { ) {
let data: OnChunkGeneratedEvent = { const data: OnChunkGeneratedEvent = {
name: defines.events.on_chunk_generated, name: defines.events.on_chunk_generated,
position: {x: chunk.x, y: chunk.y}, position: {x: chunk.x, y: chunk.y},
area: chunk.area, area: chunk.area,
@ -61,6 +63,9 @@ commands.add_command(
data, data,
50 50
) )
// handleChunkGeneratedEvent(data, i)
// i = i + 10
} }
} }
} }

View file

@ -29,38 +29,38 @@ export namespace Converters {
} }
export function entityToTable(entity: LuaEntity): EntityData { // export function entityToTable(entity: LuaEntity): EntityData {
//
let player: LuaPlayer | null = entity.is_player() ? entity.player!! : null // let player: LuaPlayer | null = entity.is_player() ? entity.player!! : null
//
return { // return {
objectName: entity.object_name, // objectName: entity.object_name,
//
// entity data // // entity data
name: entity.name, // name: entity.name,
type: entity.type, // type: entity.type,
active: entity.active, // active: entity.active,
health: entity.health ?? null, // health: entity.health ?? null,
healthRatio: entity.get_health_ratio() ?? null, // healthRatio: entity.get_health_ratio() ?? null,
surface: entity.surface.index, // surface: entity.surface.index,
unitNumber: entity.unit_number ?? null, // unitNumber: entity.unit_number ?? null,
position: mapEntityPosition(entity.position), // position: mapEntityPosition(entity.position),
force: entity.force.index, // force: entity.force.index,
//
// player data // // player data
playerIndex: player?.index ?? null // playerIndex: player?.index ?? null
} // }
} // }
//
function entitiesToUnitNumbers(entities: LuaEntity[]): uint[] { // function entitiesToUnitNumbers(entities: LuaEntity[]): uint[] {
let result: (uint) [] = [] // let result: (uint) [] = []
for (let entity of entities) { // for (let entity of entities) {
if (entity.unit_number != null) { // if (entity.unit_number != null) {
result[result.length] = entity.unit_number // result[result.length] = entity.unit_number
} // }
} // }
return result // return result
} // }
export function surfaceToTable(surface: LuaSurface): SurfaceData { export function surfaceToTable(surface: LuaSurface): SurfaceData {
return { return {
@ -72,26 +72,26 @@ export namespace Converters {
} }
} }
export function mapEntityPosition(mapPos: MapPositionTable): MapEntityPosition { // export function mapEntityPosition(mapPos: MapPositionTable): MapEntityPosition {
return { // return {
x: mapPos.x, // x: mapPos.x,
y: mapPos.y, // y: mapPos.y,
} // }
} // }
export function mapTilePosition(mapPos: MapPositionTable): MapTilePosition { // export function mapTilePosition(mapPos: MapPositionTable): MapTilePosition {
return { // return {
x: mapPos.x, // x: mapPos.x,
y: mapPos.y, // y: mapPos.y,
} // }
} // }
export function mapChunkPosition(mapPos: ChunkPositionTable): MapChunkPosition { // export function mapChunkPosition(mapPos: ChunkPositionTable): MapChunkPosition {
return { // return {
x: mapPos.x, // x: mapPos.x,
y: mapPos.y, // y: mapPos.y,
} // }
} // }
export function mapColour(color: ColorTable): Colour { export function mapColour(color: ColorTable): Colour {
return { return {
@ -111,23 +111,23 @@ export namespace Converters {
} }
} }
export function convertTile(tile: LuaTile): MapTile { // export function convertTile(tile: LuaTile): MapTile {
return { // return {
x: tile.position.x, // x: tile.position.x,
y: tile.position.y, // y: tile.position.y,
proto: tile.prototype.name, // proto: tile.prototype.name,
} // }
} // }
//
// export function convertTiles(tiles: LuaTile[]): MapTile[] {
// return tiles.map((tile: LuaTile) => convertTile(tile))
// }
export function convertTiles(tiles: LuaTile[]): MapTile[] { // export function convertBoundingBox(bb: BoundingBoxRead): MapBoundingBox {
return tiles.map((tile: LuaTile) => convertTile(tile)) // return {
} // topLeft: mapTilePosition(bb.left_top),
// bottomRight: mapTilePosition(bb.right_bottom),
export function convertBoundingBox(bb: BoundingBoxRead): MapBoundingBox { // }
return { // }
topLeft: mapTilePosition(bb.left_top),
bottomRight: mapTilePosition(bb.right_bottom),
}
}
} }

View file

@ -10,24 +10,24 @@ import {emitEvent} from "./emitEvent";
// handleCharactersEvent(tick, eventType, playerIndex) // handleCharactersEvent(tick, eventType, playerIndex)
// } // }
export function handleCharactersEvent(tick: uint, eventType: string, playerIndex: uint) { // export function handleCharactersEvent(tick: uint, eventType: string, playerIndex: uint) {
//
// let player: LuaPlayer = game.players[playerIndex]
//
// if (player.character != undefined) {
// handleEntityUpdate(tick, eventType, player.character)
// }
// for (const character of player.get_associated_characters()) {
// if (character != undefined) {
// handleEntityUpdate(tick, eventType, character)
// }
// }
// }
let player: LuaPlayer = game.players[playerIndex] // export function handleEntityUpdate(tick: uint, eventType: string, entity: LuaEntity) {
// let table = Converters.entityToTable(entity)
if (player.character != undefined) { // emitEvent(table, tick, eventType)
handleEntityUpdate(tick, eventType, player.character) // }
}
for (const character of player.get_associated_characters()) {
if (character != undefined) {
handleEntityUpdate(tick, eventType, character)
}
}
}
export function handleEntityUpdate(tick: uint, eventType: string, entity: LuaEntity) {
let table = Converters.entityToTable(entity)
emitEvent(table, tick, eventType)
}
export function handleSurfaceUpdate( export function handleSurfaceUpdate(
tick: uint, tick: uint,
@ -48,35 +48,35 @@ export function handleConsoleChat(
emitEvent(table, tick, eventType) emitEvent(table, tick, eventType)
} }
export function handleChunkUpdate( // export function handleChunkUpdate(
tick: uint, // tick: uint,
eventType: string, // eventType: string,
surfaceIndex: uint, // surfaceIndex: uint,
position: ChunkPositionTable, // position: ChunkPositionTable,
area: BoundingBoxRead, // area: BoundingBoxRead,
) { // ) {
//
let surface = game.get_surface(surfaceIndex) // let surface = game.get_surface(surfaceIndex)
//
let tiles: LuaTile[] = surface?.find_tiles_filtered({ // let tiles: LuaTile[] = surface?.find_tiles_filtered({
area: area, // area: area,
collision_mask: ["ground-tile", "water-tile"] // collision_mask: ["ground-tile", "water-tile"]
} // }
) ?? [] // ) ?? []
//
let convertedTiles: MapTile[] = tiles.map((tile: LuaTile) => { // let convertedTiles: MapTile[] = tiles.map((tile: LuaTile) => {
return Converters.convertTile(tile) // return Converters.convertTile(tile)
}) // })
//
let mapChunk: MapChunk = { // let mapChunk: MapChunk = {
objectName: "MapChunk", // objectName: "MapChunk",
tiles: createMapTiles(surfaceIndex, convertedTiles), // tiles: createMapTiles(surfaceIndex, convertedTiles),
position: Converters.mapChunkPosition(position), // position: Converters.mapChunkPosition(position),
area: Converters.convertBoundingBox(area), // area: Converters.convertBoundingBox(area),
} // }
//
emitEvent(mapChunk, tick, eventType) // emitEvent(mapChunk, tick, eventType)
} // }
// export function handleTilesUpdate( // export function handleTilesUpdate(
// tick: uint, // tick: uint,
@ -104,13 +104,13 @@ export function handleChunkUpdate(
// } // }
// } // }
function createMapTiles( // function createMapTiles(
surfaceIndex: uint, // surfaceIndex: uint,
tiles: MapTile[], // tiles: MapTile[],
): MapTiles { // ): MapTiles {
return { // return {
objectName: "LuaTiles", // objectName: "LuaTiles",
surfaceIndex: surfaceIndex, // surfaceIndex: surfaceIndex,
tiles: tiles, // tiles: tiles,
} // }
} // }

View file

@ -11,6 +11,7 @@ type MapChunkUpdater = (data: CacheData<"MAP_CHUNK">) => void
const mapProtoNameToKey: { [key: string]: string } = {} const mapProtoNameToKey: { [key: string]: string } = {}
let protoIndex: uint = 0 let protoIndex: uint = 0
function getProtoKey(protoName: string): string { function getProtoKey(protoName: string): string {
if (mapProtoNameToKey[protoName] == undefined) { if (mapProtoNameToKey[protoName] == undefined) {
mapProtoNameToKey[protoName] = `${protoIndex++}` mapProtoNameToKey[protoName] = `${protoIndex++}`
@ -25,6 +26,7 @@ function mapTilesUpdateDebounce(
tiles: TileRead[], tiles: TileRead[],
eventName: string, eventName: string,
updater?: MapChunkUpdater, updater?: MapChunkUpdater,
expirationDurationTicks?: uint,
) { ) {
if (surface == undefined) { if (surface == undefined) {
@ -64,7 +66,8 @@ function mapTilesUpdateDebounce(
if (updater != undefined) { if (updater != undefined) {
updater(data) updater(data)
} }
} },
expirationDurationTicks,
) )
} }
@ -80,20 +83,37 @@ function getTiles(
) ?? [] ) ?? []
} }
function getSurface(surfaceIndex: uint): LuaSurface | undefined { function getSurface(surfaceIndex: uint): LuaSurface | undefined {
return game.surfaces[surfaceIndex] return game.surfaces[surfaceIndex]
} }
script.on_event( script.on_event(
defines.events.on_chunk_generated, defines.events.on_chunk_generated,
(e: OnChunkGeneratedEvent) => { (e: OnChunkGeneratedEvent) => {
log(`on_chunk_generated ${e.tick}`) log(`on_chunk_generated ${e.tick}`)
handleChunkGeneratedEvent(e)
let tiles = getTiles(e.surface, e.area)
mapTilesUpdateDebounce(e.surface, e.position, tiles, Converters.eventNameString(e.name))
} }
) )
export function handleChunkGeneratedEvent(
e: OnChunkGeneratedEvent,
expirationDurationTicks?: uint,
) {
let tiles = getTiles(e.surface, e.area)
mapTilesUpdateDebounce(
e.surface,
e.position,
tiles,
Converters.eventNameString(e.name),
undefined,
expirationDurationTicks,
)
}
script.on_event( script.on_event(
defines.events.on_chunk_charted, defines.events.on_chunk_charted,
(e: OnChunkChartedEvent) => { (e: OnChunkChartedEvent) => {
@ -111,6 +131,7 @@ script.on_event(
} }
) )
script.on_event( script.on_event(
defines.events.script_raised_set_tiles, defines.events.script_raised_set_tiles,
(e: ScriptRaisedSetTilesEvent) => { (e: ScriptRaisedSetTilesEvent) => {
@ -146,6 +167,7 @@ function groupTiles(tiles: TileRead[]): Map<MapChunkPosition, TileRead[]> {
return mapChunkPositionToTiles return mapChunkPositionToTiles
} }
function convertOldPosition( function convertOldPosition(
oldTiles: OldTileAndPosition[], oldTiles: OldTileAndPosition[],
placedTile: LuaTilePrototype, placedTile: LuaTilePrototype,
@ -160,6 +182,7 @@ function convertOldPosition(
) )
} }
function onBuildTileEvent(event: OnPlayerBuiltTileEvent | OnRobotBuiltTileEvent) { function onBuildTileEvent(event: OnPlayerBuiltTileEvent | OnRobotBuiltTileEvent) {
const surface = getSurface(event.surface_index) const surface = getSurface(event.surface_index)
@ -199,6 +222,7 @@ function onBuildTileEvent(event: OnPlayerBuiltTileEvent | OnRobotBuiltTileEvent)
} }
} }
script.on_event(defines.events.on_player_built_tile, (e: OnPlayerBuiltTileEvent) => { script.on_event(defines.events.on_player_built_tile, (e: OnPlayerBuiltTileEvent) => {
log(`on_player_built_tile ${e.tick}`) log(`on_player_built_tile ${e.tick}`)
onBuildTileEvent(e) onBuildTileEvent(e)
@ -246,10 +270,9 @@ script.on_event(
key, key,
data => { data => {
data.isDeleted = true data.isDeleted = true
} },
0, // deletion is important - emit ASAP
) )
// deletion is important - emit ASAP
EventUpdatesManager.setExpiration(key, 0)
} }
} }
) )

View file

@ -1,23 +1,19 @@
import { import {handleConsoleChat, handleSurfaceUpdate,} from "./handlers";
handleChunkUpdate,
handleConsoleChat,
handleEntityUpdate,
handleSurfaceUpdate,
} from "./handlers";
import {Queue} from "../queue/queue"; import {Queue} from "../queue/queue";
import {isEventType} from "./eventTypeCheck"; import {isEventType} from "./eventTypeCheck";
import {Converters} from "./converters"; import {Converters} from "./converters";
import KafkatorioSettings from "../settings/KafkatorioSettings"; import KafkatorioSettings from "../settings/KafkatorioSettings";
import {handleChunkGeneratedEvent} from "./onMapChunkEventListeners";
script.on_event( // script.on_event(
defines.events.on_player_mined_entity, // defines.events.on_player_mined_entity,
(e: OnPlayerMinedEntityEvent) => { // (e: OnPlayerMinedEntityEvent) => {
let eventName = Converters.eventNameString(e.name) // let eventName = Converters.eventNameString(e.name)
// handlePlayerUpdate(e.tick, eventName, e.player_index) // // handlePlayerUpdate(e.tick, eventName, e.player_index)
handleEntityUpdate(e.tick, eventName, e.entity) // handleEntityUpdate(e.tick, eventName, e.entity)
} // }
) // )
// script.on_event( // script.on_event(
// defines.events.on_player_joined_game, // defines.events.on_player_joined_game,
@ -47,22 +43,24 @@ script.on_event(
// } // }
} }
// if (e.tick % 30 == 0) { if (e.tick % 7 == 0) {
// let events: EventData[] = Queue.dequeueValues(1) const events: EventData[] = Queue.dequeueValues(1)
//
// if (events.length > 0) { if (events.length > 0) {
// log(`[${e.tick}] dequed ${events.length} events, current size: ${Queue.size()}`) log(`[${e.tick}] dequed ${events.length} events, current size: ${Queue.size()}`)
//
// for (const event of events) { let i = 100
// if (isEventType(event, defines.events.on_chunk_generated)) { for (const event of events) {
// let eName = Converters.eventNameString(event.name) if (isEventType(event, defines.events.on_chunk_generated)) {
// let eName = Converters.eventNameString(event.name)
// log(`[${e.tick}] dequed event ${eName}`)
// handleChunkUpdate(e.tick, eName, event.surface.index, event.position, event.area) log(`[${e.tick}] dequed event ${eName}`)
// } handleChunkGeneratedEvent(event, i)
// } i += 10
// } }
// } }
}
}
} }
) )

View file

@ -35,12 +35,12 @@ sealed class FactorioObjectData {
// } // }
enum class ObjectName { enum class ObjectName {
LuaPlayer, // LuaPlayer,
LuaEntity, // LuaEntity,
LuaSurface, LuaSurface,
MapChunk, // MapChunk,
// LuaTile, // LuaTile,
LuaTiles, // LuaTiles,
ConsoleChatMessage, ConsoleChatMessage,
; ;
@ -69,60 +69,60 @@ object FactorioObjectDataJsonSerializer : JsonContentPolymorphicSerializer<Facto
requireNotNull(type) { "Unknown FactorioObjectData $key: $element" } requireNotNull(type) { "Unknown FactorioObjectData $key: $element" }
return when (type) { return when (type) {
FactorioObjectData.ObjectName.LuaPlayer -> PlayerData.serializer() // FactorioObjectData.ObjectName.LuaPlayer -> PlayerData.serializer()
FactorioObjectData.ObjectName.LuaEntity -> EntityData.serializer() // FactorioObjectData.ObjectName.LuaEntity -> EntityData.serializer()
FactorioObjectData.ObjectName.LuaSurface -> SurfaceData.serializer() FactorioObjectData.ObjectName.LuaSurface -> SurfaceData.serializer()
FactorioObjectData.ObjectName.MapChunk -> MapChunk.serializer() // FactorioObjectData.ObjectName.MapChunk -> MapChunk.serializer()
// FactorioObjectData.ObjectName.LuaTile -> MapTile.serializer() // FactorioObjectData.ObjectName.LuaTile -> MapTile.serializer()
FactorioObjectData.ObjectName.LuaTiles -> MapTiles.serializer() // FactorioObjectData.ObjectName.LuaTiles -> MapTiles.serializer()
FactorioObjectData.ObjectName.ConsoleChatMessage -> ConsoleChatMessage.serializer() FactorioObjectData.ObjectName.ConsoleChatMessage -> ConsoleChatMessage.serializer()
} }
} }
} }
/** [`LuaControl`](https://lua-api.factorio.com/latest/LuaControl.html) */ ///** [`LuaControl`](https://lua-api.factorio.com/latest/LuaControl.html) */
interface FactorioLuaControl { //interface FactorioLuaControl {
val position: MapEntityPosition // val position: MapEntityPosition
val surface: SurfaceIndex // val surface: SurfaceIndex
val force: ForceIndex // val force: ForceIndex
} //}
@Serializable //@Serializable
data class PlayerData( //data class PlayerData(
override val force: ForceIndex, // override val force: ForceIndex,
override val position: MapEntityPosition, // override val position: MapEntityPosition,
override val surface: SurfaceIndex, // override val surface: SurfaceIndex,
@Contextual // @Contextual
val associatedCharactersUnitNumbers: List<UnitNumber>, // val associatedCharactersUnitNumbers: List<UnitNumber>,
val characterUnitNumber: UnitNumber?, // val characterUnitNumber: UnitNumber?,
val chatColour: Colour, // val chatColour: Colour,
val colour: Colour, // val colour: Colour,
val lastOnline: Tick, // val lastOnline: Tick,
val name: String, // val name: String,
) : FactorioObjectData(), FactorioLuaControl { //) : 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 force: ForceIndex,
override val position: MapEntityPosition, // override val position: MapEntityPosition,
override val surface: SurfaceIndex, // 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 playerIndex: PlayerIndex? = null, // val playerIndex: PlayerIndex? = null,
val type: String, // val type: String,
val unitNumber: UnitNumber? = null, // val unitNumber: UnitNumber? = null,
) : FactorioObjectData(), FactorioLuaControl { //) : FactorioObjectData(), FactorioLuaControl {
@EncodeDefault // @EncodeDefault
override val objectName = ObjectName.LuaEntity // override val objectName = ObjectName.LuaEntity
} //}
@Serializable @Serializable
@ -136,16 +136,16 @@ data class SurfaceData(
} }
/** 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(
val tiles: MapTiles, // val tiles: MapTiles,
val position: MapChunkPosition, // val position: MapChunkPosition,
val area: MapBoundingBox, // val area: MapBoundingBox,
) : FactorioObjectData() { //) : FactorioObjectData() {
@EncodeDefault // @EncodeDefault
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 */
@ -153,10 +153,12 @@ data class MapChunk(
data class MapTiles( data class MapTiles(
val surfaceIndex: SurfaceIndex, val surfaceIndex: SurfaceIndex,
val tiles: List<MapTile>, val tiles: List<MapTile>,
) : FactorioObjectData() { )
@EncodeDefault // : FactorioObjectData()
override val objectName = ObjectName.LuaTiles //{
} // @EncodeDefault
// override val objectName = ObjectName.LuaTiles
//}
@Serializable @Serializable

View file

@ -8,335 +8,335 @@ import kotlinx.serialization.encodeToString
class FactorioEventTest : FunSpec({ class FactorioEventTest : FunSpec({
context("Given: json on_player_joined_game") { // context("Given: json on_player_joined_game") {
//
// language=JSON // // language=JSON
val json = """ // val json = """
{ // {
"data": { // "data": {
"objectName": "LuaPlayer", // "objectName": "LuaPlayer",
"force": 1, // "force": 1,
"surface": 1, // "surface": 1,
"name": "fredthedeadhead", // "name": "fredthedeadhead",
"characterUnitNumber": 1, // "characterUnitNumber": 1,
"associatedCharactersUnitNumbers": {}, // "associatedCharactersUnitNumbers": {},
"position": { // "position": {
"x": 30.6, // "x": 30.6,
"y": 84.1 // "y": 84.1
}, // },
"colour": { // "colour": {
"red": 0.86, // "red": 0.86,
"green": 0.5, // "green": 0.5,
"blue": 0.12, // "blue": 0.12,
"alpha": 0.5 // "alpha": 0.5
}, // },
"chatColour": { // "chatColour": {
"red": 1, // "red": 1,
"green": 0.62, // "green": 0.62,
"blue": 0.25 // "blue": 0.25
}, // },
"lastOnline": 2287061 // "lastOnline": 2287061
}, // },
"packetType": "EVENT", // "packetType": "EVENT",
"eventType": "on_player_joined_game", // "eventType": "on_player_joined_game",
"modVersion": "0.2.1", // "modVersion": "0.2.1",
"tick": 2287072 // "tick": 2287072
} // }
""".trimIndent() // """.trimIndent()
context("When: decoded") { // context("When: decoded") {
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json) // val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
//
test("Then: parse") { // test("Then: parse") {
//
val expected = FactorioEvent( // val expected = FactorioEvent(
data = PlayerData( // data = PlayerData(
name = "fredthedeadhead", // name = "fredthedeadhead",
surface = SurfaceIndex(1u), // surface = SurfaceIndex(1u),
force = ForceIndex(1u), // force = ForceIndex(1u),
characterUnitNumber = UnitNumber(1u), // characterUnitNumber = UnitNumber(1u),
associatedCharactersUnitNumbers = emptyList(), // associatedCharactersUnitNumbers = emptyList(),
position = MapEntityPosition( // position = MapEntityPosition(
x = 30.6, // x = 30.6,
y = 84.1, // y = 84.1,
), // ),
colour = Colour( // colour = Colour(
red = 0.86f, // red = 0.86f,
green = 0.5f, // green = 0.5f,
blue = 0.12f, // blue = 0.12f,
alpha = 0.5f // alpha = 0.5f
), // ),
chatColour = Colour( // chatColour = Colour(
red = 1f, // red = 1f,
green = 0.62f, // green = 0.62f,
blue = 0.25f, // blue = 0.25f,
alpha = 1f // alpha = 1f
), // ),
lastOnline = Tick(2287061u) // lastOnline = Tick(2287061u)
), // ),
eventType = "on_player_joined_game", // eventType = "on_player_joined_game",
modVersion = "0.2.1", // modVersion = "0.2.1",
tick = Tick(2287072u) // tick = Tick(2287072u)
) // )
//
actual shouldBe expected // actual shouldBe expected
//
expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaPlayer // expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaPlayer
} // }
//
test("Then: expect encode equals json") { // test("Then: expect encode equals json") {
val encoded = jsonMapperKafkatorio.encodeToString(actual) // val encoded = jsonMapperKafkatorio.encodeToString(actual)
encoded.shouldEqualJson(json) // encoded.shouldEqualJson(json)
} // }
} // }
} // }
//
context("Given: json LuaSurface") { // context("Given: json LuaSurface") {
// language=JSON // // language=JSON
val json = """ // val json = """
{ // {
"data": { // "data": {
"objectName": "LuaSurface", // "objectName": "LuaSurface",
"name": "nauvis", // "name": "nauvis",
"index": 1, // "index": 1,
"daytime": 0.745 // "daytime": 0.745
}, // },
"packetType": "EVENT", // "packetType": "EVENT",
"eventType": "on_tick", // "eventType": "on_tick",
"modVersion": "0.2.1", // "modVersion": "0.2.1",
"tick": 2301240 // "tick": 2301240
} // }
""".trimIndent() // """.trimIndent()
//
context("When: decoded") { // context("When: decoded") {
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json) // val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
//
test("should equal obj") { // test("should equal obj") {
//
val expected = FactorioEvent( // val expected = FactorioEvent(
data = SurfaceData( // data = SurfaceData(
name = "nauvis", // name = "nauvis",
index = SurfaceIndex(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 = Tick(2301240u) // tick = Tick(2301240u)
) // )
//
actual shouldBe expected // actual shouldBe expected
//
expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaSurface // expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaSurface
} // }
//
test("Then: expect encode equals json") { // test("Then: expect encode equals json") {
val encoded = jsonMapperKafkatorio.encodeToString(actual) // val encoded = jsonMapperKafkatorio.encodeToString(actual)
encoded.shouldEqualJson(json) // encoded.shouldEqualJson(json)
} // }
} // }
} // }
//
context("Given: LuaEntity on_player_changed_position") { // context("Given: LuaEntity on_player_changed_position") {
// language=JSON // // language=JSON
val json = """ // val json = """
{ // {
"data": { // "data": {
"objectName": "LuaEntity", // "objectName": "LuaEntity",
"name": "character", // "name": "character",
"type": "character", // "type": "character",
"active": true, // "active": true,
"health": 250, // "health": 250,
"healthRatio": 1, // "healthRatio": 1,
"surface": 1, // "surface": 1,
"force": 1, // "force": 1,
"unitNumber": 1, // "unitNumber": 1,
"position": { // "position": {
"x": 37.5, // "x": 37.5,
"y": 81.1 // "y": 81.1
} // }
}, // },
"packetType": "EVENT", // "packetType": "EVENT",
"eventType": "on_player_changed_position", // "eventType": "on_player_changed_position",
"modVersion": "0.2.1", // "modVersion": "0.2.1",
"tick": 2301231 // "tick": 2301231
} // }
""".trimIndent() // """.trimIndent()
context("When: decoded") { // context("When: decoded") {
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json) // val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
//
test("parse") { // test("parse") {
//
val expected = FactorioEvent( // val expected = FactorioEvent(
data = EntityData( // data = EntityData(
name = "character", // name = "character",
type = "character", // type = "character",
active = true, // active = true,
health = 250.0, // health = 250.0,
healthRatio = 1.0, // healthRatio = 1.0,
surface = SurfaceIndex(1u), // surface = SurfaceIndex(1u),
unitNumber = UnitNumber(1u), // unitNumber = UnitNumber(1u),
force = ForceIndex(1u), // force = ForceIndex(1u),
playerIndex = null, // playerIndex = null,
position = MapEntityPosition( // position = MapEntityPosition(
x = 37.5, // x = 37.5,
y = 81.1, // y = 81.1,
) // )
), // ),
eventType = "on_player_changed_position", // eventType = "on_player_changed_position",
modVersion = "0.2.1", // modVersion = "0.2.1",
tick = Tick(2301231u) // tick = Tick(2301231u)
) // )
//
actual shouldBe expected // actual shouldBe expected
//
expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaEntity // expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaEntity
} // }
//
test("Then: expect encode equals json") { // test("Then: expect encode equals json") {
val encoded = jsonMapperKafkatorio.encodeToString(actual) // val encoded = jsonMapperKafkatorio.encodeToString(actual)
encoded.shouldEqualJson(json) // encoded.shouldEqualJson(json)
} // }
} // }
//
} // }
//
context("Given: LuaTiles on_player_built_tile") { // context("Given: LuaTiles on_player_built_tile") {
// language=JSON // // language=JSON
val json = """ // val json = """
{ // {
"data": { // "data": {
"objectName": "LuaTiles", // "objectName": "LuaTiles",
"surfaceIndex": 1, // "surfaceIndex": 1,
"tiles": [ // "tiles": [
{ // {
"y": 10, // "y": 10,
"x": -65, // "x": -65,
"proto": "refined-concrete" // "proto": "refined-concrete"
}, // },
{ // {
"y": 11, // "y": 11,
"x": -65, // "x": -65,
"proto": "red-earth" // "proto": "red-earth"
}, // },
{ // {
"y": 10, // "y": 10,
"x": -64, // "x": -64,
"proto": "blue-cheese" // "proto": "blue-cheese"
}, // },
{ // {
"y": 11, // "y": 11,
"x": -64, // "x": -64,
"proto": "refined-concrete" // "proto": "refined-concrete"
} // }
] // ]
}, // },
"packetType": "EVENT", // "packetType": "EVENT",
"eventType": "on_player_built_tile", // "eventType": "on_player_built_tile",
"modVersion": "0.2.2", // "modVersion": "0.2.2",
"tick": 2429929 // "tick": 2429929
} // }
""".trimIndent() // """.trimIndent()
context("When: decoded") { // context("When: decoded") {
val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json) // val actual: KafkatorioPacket = jsonMapperKafkatorio.decodeFromString(json)
//
test("parse") { // test("parse") {
//
val expected = FactorioEvent( // val expected = FactorioEvent(
data = MapTiles( // data = MapTiles(
surfaceIndex = SurfaceIndex(1u), // surfaceIndex = SurfaceIndex(1u),
tiles = listOf( // tiles = listOf(
MapTile( // MapTile(
proto = PrototypeName("refined-concrete"), // proto = PrototypeName("refined-concrete"),
x = -65, // x = -65,
y = 10, // y = 10,
), // ),
MapTile( // MapTile(
proto = PrototypeName("red-earth"), // proto = PrototypeName("red-earth"),
x = -65, // x = -65,
y = 11, // y = 11,
), // ),
MapTile( // MapTile(
proto = PrototypeName("blue-cheese"), // proto = PrototypeName("blue-cheese"),
x = -64, // x = -64,
y = 10, // y = 10,
), // ),
MapTile( // MapTile(
proto = PrototypeName("refined-concrete"), // proto = PrototypeName("refined-concrete"),
x = -64, // x = -64,
y = 11, // y = 11,
), // ),
) // )
), // ),
eventType = "on_player_built_tile", // eventType = "on_player_built_tile",
modVersion = "0.2.2", // modVersion = "0.2.2",
tick = Tick(2429929u) // tick = Tick(2429929u)
) // )
//
actual shouldBe expected // actual shouldBe expected
//
expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaTiles // expected.data.objectName shouldBe FactorioObjectData.ObjectName.LuaTiles
} // }
//
test("Then: expect encode equals json") { // test("Then: expect encode equals json") {
val encoded = jsonMapperKafkatorio.encodeToString(actual) // val encoded = jsonMapperKafkatorio.encodeToString(actual)
encoded.shouldEqualJson(json) // encoded.shouldEqualJson(json)
} // }
} // }
} // }
//
context("Given: packet FactorioConfigurationUpdate") { // context("Given: packet FactorioConfigurationUpdate") {
// language=JSON // // language=JSON
val json = """ // val json = """
{ // {
"modVersion": "0.2.8", // "modVersion": "0.2.8",
"packetType": "CONFIG", // "packetType": "CONFIG",
"tick": 534, // "tick": 534,
"allMods": [ // "allMods": [
{ // {
"modName": "kafkatorio-events", // "modName": "kafkatorio-events",
"currentVersion": "0.2.8", // "currentVersion": "0.2.8",
"previousVersion": "0.2.7" // "previousVersion": "0.2.7"
}, // },
{ // {
"modName": "base", // "modName": "base",
"currentVersion": "1.1.53" // "currentVersion": "1.1.53"
} // }
], // ],
"factorioData": {} // "factorioData": {}
} // }
""".trimIndent() // """.trimIndent()
context("When: decoded") { // context("When: decoded") {
val actual: FactorioConfigurationUpdate = jsonMapperKafkatorio.decodeFromString(json) // val actual: FactorioConfigurationUpdate = jsonMapperKafkatorio.decodeFromString(json)
//
test("parse") { // test("parse") {
//
val expected = FactorioConfigurationUpdate( // val expected = FactorioConfigurationUpdate(
modVersion = "0.2.8", // modVersion = "0.2.8",
tick = Tick(534u), // tick = Tick(534u),
factorioData = FactorioGameDataUpdate(null, null), // factorioData = FactorioGameDataUpdate(null, null),
allMods = listOf( // allMods = listOf(
FactorioModInfo( // FactorioModInfo(
modName = "kafkatorio-events", // modName = "kafkatorio-events",
currentVersion = "0.2.8", // currentVersion = "0.2.8",
previousVersion = "0.2.7" // previousVersion = "0.2.7"
), // ),
FactorioModInfo( // FactorioModInfo(
modName = "base", // modName = "base",
currentVersion = "1.1.53", // currentVersion = "1.1.53",
previousVersion = null // previousVersion = null
), // ),
) // )
) // )
//
actual shouldBe expected // actual shouldBe expected
//
expected.packetType shouldBe KafkatorioPacket.PacketType.CONFIG // expected.packetType shouldBe KafkatorioPacket.PacketType.CONFIG
} // }
//
test("Then: expect encode equals json") { // test("Then: expect encode equals json") {
val encoded = jsonMapperKafkatorio.encodeToString(actual) // val encoded = jsonMapperKafkatorio.encodeToString(actual)
encoded.shouldEqualJson(json) // encoded.shouldEqualJson(json)
} // }
} // }
//
} // }
}) })