- mod refactoring into separate files, specific dirs

- start work on emitting prototypes
- start preparing for generating map tiles for leaflet
- start work on more events
  - console chat
  - chunk charted
This commit is contained in:
Adam 2022-01-06 09:16:44 +01:00
parent a0c330384a
commit 58233c9343
16 changed files with 334 additions and 94 deletions

View file

@ -1 +1,8 @@
require("events")
import {emitTiles} from "./prototypes/emitPrototypes";
require("events")
// on startup, push out prototypes
script.on_configuration_changed((e: ConfigurationChangedData) => {
emitTiles()
})

View file

@ -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<defines.Events, keyof typeof defines.events>()
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<T extends FactorioObjectData>(eventData: T, tick: uint, eventType: string) {
let event: FactorioEvent<T> = {
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)
}
)

View file

@ -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<T extends FactorioObjectData>(eventData: T, tick: uint, eventType: string) {
let event: FactorioEvent<T> = {
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}`)
}

View file

@ -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<PositionData, FactorioTile>();
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)
}

View file

@ -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
}
}
}

View file

@ -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",

View file

@ -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",

View file

@ -0,0 +1,42 @@
import {Serdes} from "../events/serdes";
export function emitTiles() {
let tilePrototypes = new LuaTable<string, FactorioMapTilePrototype>()
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<T extends FactorioPrototype>(prototypes: LuaTable<string, T>) {
let data = game.table_to_json(prototypes)
localised_print(`FactorioPrototype: ${data}`)
}

View file

@ -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<PositionData, FactorioTile>;
}
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;
}

View file

@ -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",

View file

@ -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")
}
}

View file

@ -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<PositionData, FactorioTile>,
) : FactorioObjectData() {
@Transient
override val objectName: String = "FactorioTilesMap"
}
@Serializable
@SerialName("FactorioTiles")
data class FactorioTiles(
val tiles: List<FactorioTile>,
) : 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"
}

View file

@ -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<String>,
val order: String,
/** Is this tile mineable at all? */
val canBeMined: Boolean,
) : FactorioPrototype() {
@Transient
override val objectName: String = "LuaTilePrototype"
}

View file

@ -19,6 +19,7 @@ fun main(args: Array<String>) {
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<String>) {
@Language("TypeScript")
val header = """
|// Generated by TypeScriptGenerator - do edit this file manually
|// Generated by TypeScriptGenerator - do not edit this file manually
|
""".trimMargin()