diff --git a/README.md b/README.md index 5fa1128..507d532 100644 --- a/README.md +++ b/README.md @@ -50,17 +50,14 @@ kt-flatbuffers -> wasm -> lua? https://www.npmjs.com/package/wasm2lua?activeTab=readme -##### flatbuffers -https://github.com/dvidelabs/flatcc +##### Encodings - -##### z85 encoding - -* Kotlin https://gist.github.com/ischumacher/b4929f26341ebef62cbce35c65543eda -* Lua https://web-eworks.github.io/lZ85/ - -#### CBOR - -https://www.zash.se/lua-cbor.html -https://code.zash.se/lua-cbor/archive/68b3a36d0816.tar.gz +* flatbuffers https://github.com/dvidelabs/flatcc +* z85 encoding + * Kotlin https://gist.github.com/ischumacher/b4929f26341ebef62cbce35c65543eda + * Lua https://web-eworks.github.io/lZ85/ +* https://github.com/SafeteeWoW/LibDeflate +* CBOR + * https://www.zash.se/lua-cbor.html + * https://code.zash.se/lua-cbor/archive/68b3a36d0816.tar.gz diff --git a/build.gradle.kts b/build.gradle.kts index b67ca9a..42a664f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { } group = "dev.adamko.kafkatorio" -version = "0.1.6" +version = "0.1.7" val licenseFile: RegularFile by extra(layout.projectDirectory.file("LICENSE")) diff --git a/modules/events-mod/src/main/typescript/control.ts b/modules/events-mod/src/main/typescript/control.ts index 544678b..e0064ea 100644 --- a/modules/events-mod/src/main/typescript/control.ts +++ b/modules/events-mod/src/main/typescript/control.ts @@ -1 +1,8 @@ -require("events") \ No newline at end of file +import {emitTiles} from "./prototypes/emitPrototypes"; + +require("events") + +// on startup, push out prototypes +script.on_configuration_changed((e: ConfigurationChangedData) => { + emitTiles() +}) diff --git a/modules/events-mod/src/main/typescript/events.ts b/modules/events-mod/src/main/typescript/events.ts index 7ac5ec3..fd5d7d3 100644 --- a/modules/events-mod/src/main/typescript/events.ts +++ b/modules/events-mod/src/main/typescript/events.ts @@ -1,63 +1,16 @@ -import {Serdes} from "./serdes/serdes" - -const MOD_VERSION = script.active_mods["@mod.name@"] ?? "UNKNOWN" -const FACTORIO_VERSION = script.active_mods["base"] ?? "UNKNOWN" +import { + handleChunkUpdate, + handleConsoleChat, + handleEntityUpdate, + handlePlayerUpdate, + handleSurfaceUpdate +} from "./events/handlers"; const mapEventIdToName = new LuaTable() for (const [k, v] of pairs(defines.events)) { mapEventIdToName.set(v, k) } -function handlePlayerUpdate(tick: uint, playerIndex: uint, eventType: string) { - let player: LuaPlayer = game.players[playerIndex] - let table = Serdes.playerToTable(player) - emitEvent(table, tick, eventType) - - handleCharactersEvent(tick, playerIndex, eventType) -} - -function handleCharactersEvent(tick: uint, playerIndex: uint, eventType: string) { - - let player: LuaPlayer = game.players[playerIndex] - - if (player.character != undefined) { - handleEntityUpdate(tick, player.character, eventType) - } - for (const character of player.get_associated_characters()) { - if (character != undefined) { - handleEntityUpdate(tick, character, eventType) - } - } -} - -function handleEntityUpdate(tick: uint, entity: LuaEntity, eventType: string) { - let table = Serdes.entityToTable(entity) - emitEvent(table, tick, eventType) -} - -function surfaceEvent(tick: uint, surface: LuaSurface, eventType: string) { - let table = Serdes.surfaceToTable(surface) - emitEvent(table, tick, eventType) -} - -// const SERVER_ID: uint = 0 -// const EVENT_FILE_DIR: string = "events" -/** Emit a serialised event */ -function emitEvent(eventData: T, tick: uint, eventType: string) { - - let event: FactorioEvent = { - data: eventData, - event_type: eventType, - mod_version: MOD_VERSION, - factorio_version: FACTORIO_VERSION, - tick: tick - } - - let data = game.table_to_json(event) - - localised_print(`FactorioEvent: ${data}`) -} - // script.on_event( // [defines.events.on_pre_build, defines.events.on_player_dropped_item], // (e: OnPreBuildEvent | OnPlayerDroppedItemEvent) => { @@ -94,20 +47,32 @@ script.on_event( defines.events.on_tick, (e: OnTickEvent) => { if (e.tick % 60 == 0) { - - for (const [index, _] of pairs(game.surfaces)) { - let surface = game.get_surface(index) // TODO fix / report can't iterate over surfaces - if (surface != undefined) { - surfaceEvent(e.tick, surface, mapEventIdToName.get(e.name)) - } - // let surface = game.surfaces[index] - // surfaceEvent(e.tick, surface, mapEventIdToName.get(e.name)) + for (const [_, surface] of pairs(game.surfaces)) { + handleSurfaceUpdate(e.tick, surface, mapEventIdToName.get(e.name)) } + + // for (const [index, _] of pairs(game.surfaces)) { + // let surface = game.get_surface(index) // TODO fix / report can't iterate over surfaces + // if (surface != undefined) { + // handleSurfaceUpdate(e.tick, surface, mapEventIdToName.get(e.name)) + // } + //// let surface = game.surfaces[index] + //// surfaceEvent(e.tick, surface, mapEventIdToName.get(e.name)) + // } } } -); +) +script.on_event( + defines.events.on_console_chat, + (e: OnConsoleChatEvent) => { + handleConsoleChat(e.tick, e.player_index, e.message, mapEventIdToName.get(e.name)) + } +) -// script.on_load(() => { -// game.print("loaded Factorio Web Map!") -// }); +script.on_event( + defines.events.on_chunk_charted, + (e: OnChunkChartedEvent) => { + handleChunkUpdate(e.tick, mapEventIdToName.get(e.name), e.surface_index, e.position) + } +) diff --git a/modules/events-mod/src/main/typescript/events/emitter.ts b/modules/events-mod/src/main/typescript/events/emitter.ts new file mode 100644 index 0000000..8613fae --- /dev/null +++ b/modules/events-mod/src/main/typescript/events/emitter.ts @@ -0,0 +1,21 @@ +export const MOD_VERSION = script.active_mods["@mod.name@"] ?? "UNKNOWN" +export const FACTORIO_VERSION = script.active_mods["base"] ?? "UNKNOWN" + +// const SERVER_ID: uint = 0 +// const EVENT_FILE_DIR: string = "events" + +/** Emit a serialised event */ +export function emitEvent(eventData: T, tick: uint, eventType: string) { + + let event: FactorioEvent = { + data: eventData, + event_type: eventType, + mod_version: MOD_VERSION, + factorio_version: FACTORIO_VERSION, + tick: tick + } + + let data = game.table_to_json(event) + + localised_print(`FactorioEvent: ${data}`) +} diff --git a/modules/events-mod/src/main/typescript/events/handlers.ts b/modules/events-mod/src/main/typescript/events/handlers.ts new file mode 100644 index 0000000..e2ec935 --- /dev/null +++ b/modules/events-mod/src/main/typescript/events/handlers.ts @@ -0,0 +1,82 @@ +import {Serdes} from "./serdes" +import {emitEvent} from "./emitter"; + +export function handlePlayerUpdate(tick: uint, playerIndex: uint, eventType: string) { + let player: LuaPlayer = game.players[playerIndex] + let table = Serdes.playerToTable(player) + emitEvent(table, tick, eventType) + + handleCharactersEvent(tick, playerIndex, eventType) +} + +export function handleCharactersEvent(tick: uint, playerIndex: uint, eventType: string) { + + let player: LuaPlayer = game.players[playerIndex] + + if (player.character != undefined) { + handleEntityUpdate(tick, player.character, eventType) + } + for (const character of player.get_associated_characters()) { + if (character != undefined) { + handleEntityUpdate(tick, character, eventType) + } + } +} + +export function handleEntityUpdate(tick: uint, entity: LuaEntity, eventType: string) { + let table = Serdes.entityToTable(entity) + emitEvent(table, tick, eventType) +} + +export function handleSurfaceUpdate( + tick: uint, + surface: LuaSurface, + eventType: string +) { + let table = Serdes.surfaceToTable(surface) + emitEvent(table, tick, eventType) +} + + +export function handleConsoleChat( + tick: uint, + playerIndex: uint | undefined, + message: string, + eventType: string, +) { + let table = Serdes.consoleChat(message, playerIndex) + emitEvent(table, tick, eventType) +} + +const CHUNK_SIZE = 32 + +export function handleChunkUpdate(tick: uint, + eventType: string, + surfaceIndex: uint, + position: ChunkPosition) { + + let surface = game.get_surface(surfaceIndex) + + let x = (position as ChunkPositionTable).x * CHUNK_SIZE + let y = (position as ChunkPositionTable).y * CHUNK_SIZE + + let tiles = surface?.find_tiles_filtered({ + position: {x: x, y: y}, + radius: CHUNK_SIZE, + collision_mask: ["ground-tile", "water-tile"] + } + ) ?? [] + + let tilePositionMap = new Map(); + for (let tile of tiles) { + let position = Serdes.positionTableToTable(tile.position) + tilePositionMap.set(position, Serdes.convertTile(tile)) + } + let mapChunk: FactorioTilesMap = { + object_name: "FactorioTilesMap", + tiles: tilePositionMap, + } + + emitEvent(mapChunk, tick, eventType) + +} diff --git a/modules/events-mod/src/main/typescript/serdes/serdes.ts b/modules/events-mod/src/main/typescript/events/serdes.ts similarity index 78% rename from modules/events-mod/src/main/typescript/serdes/serdes.ts rename to modules/events-mod/src/main/typescript/events/serdes.ts index 128f219..3394ba6 100644 --- a/modules/events-mod/src/main/typescript/serdes/serdes.ts +++ b/modules/events-mod/src/main/typescript/events/serdes.ts @@ -1,6 +1,5 @@ export namespace Serdes { - export function playerToTable(player: LuaPlayer): PlayerData { let charIds = entitiesToUnitNumbers(player.get_associated_characters()) return { @@ -65,8 +64,7 @@ export namespace Serdes { } } - export function mapColour(color: Color): Colour { - color = (color as ColorTable) + export function mapColour(color: ColorTable): Colour { return { red: color.r ?? 0, green: color.g ?? 0, @@ -75,4 +73,23 @@ export namespace Serdes { } } + export function consoleChat(content: string, playerIndex?: uint): ConsoleChatMessage { + return { + object_name: "ConsoleChatMessage", + + author_player_index: playerIndex ?? null, + content: content + } + } + + export function convertTile(tile: LuaTile): FactorioTile { + return { + object_name: tile.object_name, + + position: tile.position, + prototype_name: tile.prototype.name, + surface_index: tile.surface.index + } + } + } diff --git a/modules/events-mod/src/main/typescript/package-lock.json b/modules/events-mod/src/main/typescript/package-lock.json index a7c3550..4fe36f3 100644 --- a/modules/events-mod/src/main/typescript/package-lock.json +++ b/modules/events-mod/src/main/typescript/package-lock.json @@ -1,6 +1,6 @@ { "name": "kafkatorio-events-mod", - "version": "0.1.6", + "version": "0.1.7", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -74,9 +74,9 @@ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" }, "typed-factorio": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/typed-factorio/-/typed-factorio-0.14.1.tgz", - "integrity": "sha512-0ot54PB1/bvSz2dENYh2pdQSdGgBuxD4ZxRVBlp8R1AiurbU2yqRvn8JPX5oOMcJjRGHqnO8g0m4R3fRwI8qvQ==" + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/typed-factorio/-/typed-factorio-0.15.0.tgz", + "integrity": "sha512-hEpW+nRL3q5vg3aOxbNbYpwARxYzMTncihurAucwnpQ/IDc4w4PrO2/OWHI5R+PkZSEQUY5LSRxG7qrGqDeWHQ==" }, "typescript": { "version": "4.5.4", diff --git a/modules/events-mod/src/main/typescript/package.json b/modules/events-mod/src/main/typescript/package.json index 603a2d4..5fd898c 100644 --- a/modules/events-mod/src/main/typescript/package.json +++ b/modules/events-mod/src/main/typescript/package.json @@ -1,6 +1,6 @@ { "name": "kafkatorio-events-mod", - "version": "0.1.6", + "version": "0.1.7", "private": true, "scripts": { "build": "tstl", @@ -14,7 +14,7 @@ "lua-types": "^2.11.0", "@types/node": "^12.0.8", "typescript-to-lua": "1.3.0", - "typed-factorio": "0.14.1", + "typed-factorio": "0.15.0", "typescript": "4.5.4" }, "license": "UNLICENSED", diff --git a/modules/events-mod/src/main/typescript/prototypes/emitPrototypes.ts b/modules/events-mod/src/main/typescript/prototypes/emitPrototypes.ts new file mode 100644 index 0000000..44aa893 --- /dev/null +++ b/modules/events-mod/src/main/typescript/prototypes/emitPrototypes.ts @@ -0,0 +1,42 @@ +import {Serdes} from "../events/serdes"; + +export function emitTiles() { + + let tilePrototypes = new LuaTable() + + for (const [_, tile] of pairs(game.tile_prototypes)) { + // let ttttt = game.tile_prototypes[tileName] + tilePrototypes.set(tile.name, mapTilePrototype(tile)) + } + + // for (let tileName in game.tile_prototypes) { + // const tile = game.tile_prototypes[tileName] + // tilePrototypes.set(tileName, mapTilePrototype(tile)) + // } + + // for (const [id, player] of pairs(game.players)) { + // const num: number = id + // const p: LuaPlayer = player + // } + emitPrototypes(tilePrototypes) +} + +function mapTilePrototype(tile: LuaTilePrototype): FactorioMapTilePrototype { + return { + object_name: tile.object_name, + + name: tile.name, + order: tile.order, + layer: tile.layer, + collision_masks: [], + map_color: Serdes.mapColour(tile.map_color), + can_be_mined: tile.mineable_properties.minable, + } +} + +function emitPrototypes(prototypes: LuaTable) { + + let data = game.table_to_json(prototypes) + + localised_print(`FactorioPrototype: ${data}`) +} diff --git a/modules/events-mod/src/main/typescript/schema/events-schema.ts b/modules/events-mod/src/main/typescript/schema/events-schema.ts index 88aa0db..24d67a3 100644 --- a/modules/events-mod/src/main/typescript/schema/events-schema.ts +++ b/modules/events-mod/src/main/typescript/schema/events-schema.ts @@ -1,4 +1,4 @@ -// Generated by TypeScriptGenerator - do edit this file manually +// Generated by TypeScriptGenerator - do not edit this file manually interface FactorioObjectData { object_name: string; } @@ -52,4 +52,41 @@ interface SurfaceData extends FactorioObjectData { index: uint; name: string; object_name: string; +} + +interface ConsoleChatMessage extends FactorioObjectData { + author_player_index: uint | null; + content: string; + object_name: string; +} + +interface FactorioTile extends FactorioObjectData { + object_name: string; + position: PositionData; + prototype_name: string; + surface_index: int; +} + +interface FactorioTilesMap extends FactorioObjectData { + object_name: string; + tiles: Map; +} + +interface FactorioTiles extends FactorioObjectData { + object_name: string; + tiles: FactorioTile[]; +} + +interface FactorioPrototype { + object_name: string; +} + +interface FactorioMapTilePrototype extends FactorioPrototype { + can_be_mined: boolean; + collision_masks: string[]; + layer: uint; + map_color: Colour; + name: string; + object_name: string; + order: string; } \ No newline at end of file diff --git a/modules/events-mod/src/main/typescript/tsconfig.json b/modules/events-mod/src/main/typescript/tsconfig.json index 1e9e646..70b9ed4 100644 --- a/modules/events-mod/src/main/typescript/tsconfig.json +++ b/modules/events-mod/src/main/typescript/tsconfig.json @@ -12,6 +12,8 @@ "lua-types/5.2", "typed-factorio/runtime" ], + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, "explainFiles": true, "forceConsistentCasingInFileNames": true, "listEmittedFiles": true, @@ -22,8 +24,7 @@ "strict": true, "strictFunctionTypes": true, "strictNullChecks": true, - "traceResolution": true, - "esModuleInterop": true + "traceResolution": true }, "tstl": { "luaTarget": "5.2", diff --git a/modules/events-schema/build.gradle.kts b/modules/events-schema/build.gradle.kts index 94ce097..efe3409 100644 --- a/modules/events-schema/build.gradle.kts +++ b/modules/events-schema/build.gradle.kts @@ -53,7 +53,8 @@ kotlin { val jvmMain by getting { dependencies { - implementation("com.github.ntrrgc:ts-generator:1.1.2") + implementation("com.github.aSemy:ts-generator:v1.2.1") +// implementation("com.github.ntrrgc:ts-generator:1.1.2") implementation("org.jetbrains.kotlin:kotlin-reflect") } } 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 ebf5d33..746352d 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 @@ -149,3 +149,44 @@ data class Colour( fun isPercentage(): Boolean = !isDecimal() } + +@Serializable +data class ConsoleChatMessage( + @SerialName("author_player_index") + val authorPlayerIndex: UInt?, + val content: String, +) : FactorioObjectData() { + @Transient + override val objectName: String = "ConsoleChatMessage" +} + +@Serializable +@SerialName("FactorioTilesMap") +data class FactorioTilesMap( + val tiles: Map, +) : FactorioObjectData() { + @Transient + override val objectName: String = "FactorioTilesMap" +} + + +@Serializable +@SerialName("FactorioTiles") +data class FactorioTiles( + val tiles: List, +) : FactorioObjectData() { + @Transient + override val objectName: String = "FactorioTiles" +} + + +@Serializable +@SerialName("LuaTile") +data class FactorioTile( + val prototypeName: String, + val position: PositionData, + val surfaceIndex: Int, +) : FactorioObjectData() { + @Transient + override val objectName: String = "LuaTile" +} diff --git a/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioPrototypes.kt b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioPrototypes.kt new file mode 100644 index 0000000..53aacb6 --- /dev/null +++ b/modules/events-schema/src/commonMain/kotlin/dev/adamko/kafkatorio/events/schema/factorioPrototypes.kt @@ -0,0 +1,28 @@ +package dev.adamko.kafkatorio.events.schema + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient +import kotlinx.serialization.json.JsonClassDiscriminator + +@Serializable +@JsonClassDiscriminator(FactorioObjectDataDiscriminatorKey) +sealed class FactorioPrototype { + abstract val objectName: String +} + +@Serializable +@SerialName("LuaTilePrototype") +data class FactorioMapTilePrototype( + val name: String, + val layer: UInt, + val mapColor: Colour, + val collisionMasks: List, + val order: String, + + /** Is this tile mineable at all? */ + val canBeMined: Boolean, +) : FactorioPrototype() { + @Transient + override val objectName: String = "LuaTilePrototype" +} diff --git a/modules/events-schema/src/jvmMain/kotlin/dev/adamko/kafkatorio/events/schema/kt2ts.kt b/modules/events-schema/src/jvmMain/kotlin/dev/adamko/kafkatorio/events/schema/kt2ts.kt index 4a8af3f..8bbbabf 100644 --- a/modules/events-schema/src/jvmMain/kotlin/dev/adamko/kafkatorio/events/schema/kt2ts.kt +++ b/modules/events-schema/src/jvmMain/kotlin/dev/adamko/kafkatorio/events/schema/kt2ts.kt @@ -19,6 +19,7 @@ fun main(args: Array) { buildSet { add(FactorioEvent::class) addAll(FactorioObjectData::class.sealedSubclasses) + addAll(FactorioPrototype::class.sealedSubclasses) }, mappings = mapOf( // builtin Factorio numeric types > `typed-factorio/generated/builtin-types.d.ts` @@ -56,7 +57,7 @@ fun main(args: Array) { @Language("TypeScript") val header = """ - |// Generated by TypeScriptGenerator - do edit this file manually + |// Generated by TypeScriptGenerator - do not edit this file manually | """.trimMargin()