From d14d0cd991d5c659331980a4af4cbb1f16885f96 Mon Sep 17 00:00:00 2001 From: Adam <897017+aSemy@users.noreply.github.com> Date: Sun, 20 Feb 2022 22:18:14 +0100 Subject: [PATCH] finish first implementation of incremental updates --- .../typescript/main/cache/EventDataCache.ts | 143 ++++++++---- .../typescript/main/cache/cacheChecker.ts | 52 +++++ .../main/config-update/prototypes.ts | 1 + .../typescript/main/emitKafkatorioPacket.ts | 1 - .../main/typescript/main/events/converters.ts | 35 +-- .../typescript/main/events/eventTypeCheck.ts | 8 + .../main/typescript/main/events/handlers.ts | 16 +- .../main/typescript/main/events/mapEvents.ts | 213 ++++++++++++++++++ .../typescript/main/events/playerEvents.ts | 178 +++++++++++++++ .../main/events/registerHandlers.ts | 39 ++-- .../src/main/typescript/main/global.d.ts | 8 - .../src/main/typescript/main/types.d.ts | 17 ++ 12 files changed, 614 insertions(+), 97 deletions(-) create mode 100644 modules/events-mod/src/main/typescript/main/cache/cacheChecker.ts create mode 100644 modules/events-mod/src/main/typescript/main/events/eventTypeCheck.ts create mode 100644 modules/events-mod/src/main/typescript/main/events/mapEvents.ts create mode 100644 modules/events-mod/src/main/typescript/main/events/playerEvents.ts create mode 100644 modules/events-mod/src/main/typescript/main/types.d.ts diff --git a/modules/events-mod/src/main/typescript/main/cache/EventDataCache.ts b/modules/events-mod/src/main/typescript/main/cache/EventDataCache.ts index 3252242..7c9225a 100644 --- a/modules/events-mod/src/main/typescript/main/cache/EventDataCache.ts +++ b/modules/events-mod/src/main/typescript/main/cache/EventDataCache.ts @@ -1,62 +1,78 @@ -import {ExcludeNullKeys} from "../global"; +import {ExcludeNullKeys, NonNullableKeys} from "../types"; export namespace EventDataCache { declare const global: { - cache: LuaTable, CacheEntry>, - DEFAULT_EXPIRATION_DURATION_TICKS: uint, + cache: LuaTable, CacheEntry>, + DEFAULT_CACHE_DURATION_TICKS: LuaTable, + DEFAULT_CACHE_DURATION_TICKS2: Record, + MAP_CHUNK_CACHE_DURATION_TICKS: uint, } export function init() { if (typeof global.cache == undefined) { - global.cache = new LuaTable, CacheEntry>() + global.cache = new LuaTable, CacheEntry>() - global.DEFAULT_EXPIRATION_DURATION_TICKS = 60 * 60 // ~60 seconds + global.DEFAULT_CACHE_DURATION_TICKS = new LuaTable() + global.DEFAULT_CACHE_DURATION_TICKS.set("PLAYER", 30) // 0.5 seconds + global.DEFAULT_CACHE_DURATION_TICKS.set("MAP_CHUNK", 60 * 15) // ~ 15 seconds + global.DEFAULT_CACHE_DURATION_TICKS.set("ENTITY", 60 * 2) // ~2 seconds + + global.DEFAULT_CACHE_DURATION_TICKS2 = { + "PLAYER": 30, // 0.5 seconds + "MAP_CHUNK": 60 * 15, // ~ 15 seconds + "ENTITY": 60 * 2, // ~2 seconds + "default": 60 + } } } + /** * Update the cache data without restarting the 'time-to-emit' countdown, so that the data won't * be emitted more than once per {@link CacheEntry.expirationDurationTicks}. */ - export function throttle( - key: CacheKey, - mutate: (data: CacheData | undefined) => void, + export function throttle( + key: CacheKey, + mutate: CacheDataMutator, ) { update(key, mutate, false) } + /** * Update the cache data and reset the 'time-to-emit' countdown, so the data won't be emitted * until there's an inactivity gap of {@link CacheEntry.expirationDurationTicks}. */ - export function debounce( - key: CacheKey, - mutate: (data: CacheData | undefined) => void, + export function debounce( + key: CacheKey, + mutate: CacheDataMutator, ) { update(key, mutate, true) } - function update( - key: CacheKey, - mutate: (data: CacheData | undefined) => void, + + function update( + key: CacheKey, + mutate: CacheDataMutator, resetLastUpdated: boolean, ) { - const entry = getCacheEntry(key) - mutate(entry?.data) - if (entry != undefined && resetLastUpdated) { + const entry = getCacheEntry(key) ?? createCacheEntry(key, mutate) + mutate(entry.data) + if (resetLastUpdated) { entry.lastUpdatedTick = game.tick } } + /** * Usage example: If an urgent update comes in, then the expiration can be reduced so that * it's transmitted sooner. */ export function setExpiration( - key: CacheKey, + key: CacheKey, expirationDurationTicks?: uint, ) { const entry = getCacheEntry(key) @@ -65,9 +81,22 @@ export namespace EventDataCache { } } - function getCacheEntry( - key: CacheKey - ): CacheEntry | undefined { + + export function extractExpired(): Array> { + const expiredData: Array> = [] + for (let [key, entry] of global.cache) { + if (entry.isExpired()) { + expiredData.push(entry.data) + global.cache.delete(key) + } + } + return expiredData + } + + + function getCacheEntry( + key: CacheKey + ): CacheEntry | undefined { if (!global.cache.has(key)) { return undefined } @@ -80,27 +109,57 @@ export namespace EventDataCache { } } - type UpdateType = T["updateType"] - /** Only include the non-null properties */ - export type CacheKey = ExcludeNullKeys & { - updateType: UpdateType - } - - /** Make the generated schema objects generic closed-polymorphic */ - export type CacheData = Omit & { - updateType: UpdateType + function createCacheEntry( + key: CacheKey, + mutate: CacheDataMutator, + ): CacheEntry { + // @ts-ignore // TODO remove ts-ignore for "not assignable to type" + const data: CacheData = {updateType: key.updateType} + mutate(data) + let entry: CacheEntry = new CacheEntry(data) + global.cache.set(key, entry) + return entry } - class CacheEntry { + /** Map a {@link FactorioEventUpdateType} to a {@link FactorioEventUpdate} DTO */ + type ConvertUpdateType = + TYPE extends "PLAYER" ? PlayerUpdate : + TYPE extends "MAP_CHUNK" ? MapChunkUpdate : + TYPE extends "ENTITY" ? EntityUpdate : + never + + + /** Only include the non-null properties, and make `updateType` specific */ + export type CacheKey = + CacheTyped + & Omit>, "updateType"> + + + /** Exclude {@link CacheKey} fields, and make `updateType` specific */ + export type CacheData = + CacheTyped + & NonNullableKeys, keyof CacheKey | "updateType">>> + + + export type CacheTyped = { + readonly updateType: TYPE + } + + + export type CacheDataMutator = + (data: CacheData) => void + + + class CacheEntry { lastUpdatedTick: uint = game.tick expirationDurationTicks?: uint - data: CacheData + data: CacheData constructor( - data: CacheData, + data: CacheData, expirationDurationTicks?: uint, ) { this.data = data @@ -110,16 +169,18 @@ export namespace EventDataCache { } isExpired(): boolean { - return game.tick - - this.lastUpdatedTick > - (this.expirationDurationTicks ?? global.DEFAULT_EXPIRATION_DURATION_TICKS) + const cacheDuration = + this.expirationDurationTicks ?? global.DEFAULT_CACHE_DURATION_TICKS2[this.data.updateType] + + return game.tick - this.lastUpdatedTick > cacheDuration } } - function isType( - data: CacheEntry, - updateType: UpdateType, - ): data is CacheEntry { + + function isType( + data: CacheEntry, + updateType: TYPE, + ): data is CacheEntry { return data.data.updateType == updateType } @@ -129,7 +190,7 @@ export namespace EventDataCache { // type: string // } // -// interface Update { +// interface Update { // type: T // } // diff --git a/modules/events-mod/src/main/typescript/main/cache/cacheChecker.ts b/modules/events-mod/src/main/typescript/main/cache/cacheChecker.ts new file mode 100644 index 0000000..4404725 --- /dev/null +++ b/modules/events-mod/src/main/typescript/main/cache/cacheChecker.ts @@ -0,0 +1,52 @@ +import {EventDataCache} from "./EventDataCache"; +import {emitPacket} from "../emitKafkatorioPacket"; +// import { global } from "../global"; + +/** Every 0.1 seconds */ +script.on_nth_tick(6, (nthTick: NthTickEventData) => { + + const cachedEvents: Array> = EventDataCache.extractExpired() + + for (const event of cachedEvents) { + + const packet: FactorioEventUpdatePacket = { + tick: nthTick.tick, + modVersion: global.MOD_VERSION, + packetType: "UPDATE", + update: event, + } + + emitPacket(packet) + } +}) + +// +// function createEntityUpdate(cacheKey: EntityCacheKey, events: EventName[]): EntityUpdate | null { +// +// +// return null +// } +// +// interface EntityUpdate { +// name: string +// +// unit_number: uint +// +// unhandledEvents?: string[] +// +// chunkPosition: MapChunkPosition +// graphics_variation?: uint8 +// health?: float +// isActive?: boolean +// isRotatable?: boolean +// last_user?: uint +// localised_description?: string +// localised_name?: string +// prototype?: string +// +// // ghost_localised_description?: string +// // ghost_localised_name?: string +// // ghost_name?: string +// // ghost_prototype?: string +// // ghost_unit_number?: uint +// } diff --git a/modules/events-mod/src/main/typescript/main/config-update/prototypes.ts b/modules/events-mod/src/main/typescript/main/config-update/prototypes.ts index 634d1a8..8b494da 100644 --- a/modules/events-mod/src/main/typescript/main/config-update/prototypes.ts +++ b/modules/events-mod/src/main/typescript/main/config-update/prototypes.ts @@ -1,5 +1,6 @@ import {Converters} from "../events/converters"; import {emitPacket} from "../emitKafkatorioPacket"; +// import { global } from "../global"; export function emitPrototypes() { emitPacket({ diff --git a/modules/events-mod/src/main/typescript/main/emitKafkatorioPacket.ts b/modules/events-mod/src/main/typescript/main/emitKafkatorioPacket.ts index fcaa92f..c86af5d 100644 --- a/modules/events-mod/src/main/typescript/main/emitKafkatorioPacket.ts +++ b/modules/events-mod/src/main/typescript/main/emitKafkatorioPacket.ts @@ -1,7 +1,6 @@ /** Emit a serialised KafkatorioPacket */ export function emitPacket(packet: T) { let data = game.table_to_json(packet) - // localised_print(`KafkatorioPacket: ${packet.packetType}`) localised_print(`KafkatorioPacket: ${data}`) // rcon.print(`KafkatorioPacket: ${data}`) } diff --git a/modules/events-mod/src/main/typescript/main/events/converters.ts b/modules/events-mod/src/main/typescript/main/events/converters.ts index 6314ba4..7acecb2 100644 --- a/modules/events-mod/src/main/typescript/main/events/converters.ts +++ b/modules/events-mod/src/main/typescript/main/events/converters.ts @@ -1,19 +1,19 @@ export namespace Converters { - export function playerToTable(player: LuaPlayer): PlayerData { - let charIds = entitiesToUnitNumbers(player.get_associated_characters()) - return { - objectName: player.object_name, - - name: player.name, - characterUnitNumber: player.character?.unit_number ?? null, - associatedCharactersUnitNumbers: charIds, - position: mapEntityPosition(player.position), - colour: mapColour(player.color), - chatColour: mapColour(player.chat_color), - lastOnline: player.last_online - } - } + // export function playerToTable(player: LuaPlayer): PlayerData { + // let charIds = entitiesToUnitNumbers(player.get_associated_characters()) + // return { + // objectName: player.object_name, + // + // name: player.name, + // characterUnitNumber: player.character?.unit_number ?? null, + // associatedCharactersUnitNumbers: charIds, + // position: mapEntityPosition(player.position), + // colour: mapColour(player.color), + // chatColour: mapColour(player.chat_color), + // lastOnline: player.last_online + // } + // } export function entityToTable(entity: LuaEntity): EntityData { @@ -28,9 +28,10 @@ export namespace Converters { active: entity.active, health: entity.health ?? null, healthRatio: entity.get_health_ratio(), - surfaceIndex: entity.surface.index, + surface: entity.surface.index, unitNumber: entity.unit_number ?? null, position: mapEntityPosition(entity.position), + force: entity.force.index, // player data playerIndex: player?.index ?? null @@ -103,6 +104,10 @@ export namespace Converters { } } + export function convertTiles(tiles: LuaTile[]): MapTile[] { + return tiles.map((tile: LuaTile) => convertTile(tile)) + } + export function convertBoundingBox(bb: BoundingBoxRead): MapBoundingBox { return { topLeft: mapTilePosition(bb.left_top), diff --git a/modules/events-mod/src/main/typescript/main/events/eventTypeCheck.ts b/modules/events-mod/src/main/typescript/main/events/eventTypeCheck.ts new file mode 100644 index 0000000..e3769f2 --- /dev/null +++ b/modules/events-mod/src/main/typescript/main/events/eventTypeCheck.ts @@ -0,0 +1,8 @@ + +function isEventType( + eventData: EventData, + type: ED extends CustomInputEvent ? string : EventId +): eventData is ED { + let id: EventId | string = eventData.name + return id == type +} diff --git a/modules/events-mod/src/main/typescript/main/events/handlers.ts b/modules/events-mod/src/main/typescript/main/events/handlers.ts index 569eb27..2feb68c 100644 --- a/modules/events-mod/src/main/typescript/main/events/handlers.ts +++ b/modules/events-mod/src/main/typescript/main/events/handlers.ts @@ -1,14 +1,14 @@ import {Converters} from "./converters" import {emitEvent} from "./emitEvent"; -export function handlePlayerUpdate(tick: uint, eventType: string, playerIndex: uint) { - let player: LuaPlayer = game.players[playerIndex] - let table = Converters.playerToTable(player) - - emitEvent(table, tick, eventType) - - handleCharactersEvent(tick, eventType, playerIndex) -} +// export function handlePlayerUpdate(tick: uint, eventType: string, playerIndex: uint) { +// let player: LuaPlayer = game.players[playerIndex] +// let table = Converters.playerToTable(player) +// +// emitEvent(table, tick, eventType) +// +// handleCharactersEvent(tick, eventType, playerIndex) +// } export function handleCharactersEvent(tick: uint, eventType: string, playerIndex: uint) { diff --git a/modules/events-mod/src/main/typescript/main/events/mapEvents.ts b/modules/events-mod/src/main/typescript/main/events/mapEvents.ts new file mode 100644 index 0000000..5744703 --- /dev/null +++ b/modules/events-mod/src/main/typescript/main/events/mapEvents.ts @@ -0,0 +1,213 @@ +import {EventDataCache} from "../cache/EventDataCache"; +import CacheKey = EventDataCache.CacheKey; +import CacheData = EventDataCache.CacheData; + + +type MapChunkUpdater = (data: CacheData<"MAP_CHUNK">) => void + + +function mapTilesUpdateDebounce( + surface: LuaSurface | undefined, + chunkPosition: ChunkPositionTable, + tiles: TileRead[], + updater?: MapChunkUpdater +) { + if (surface == undefined) { + return + } + + EventDataCache.debounce<"MAP_CHUNK">( + { + surfaceIndex: surface.index, + chunkPosition: chunkPosition, + updateType: "MAP_CHUNK", + }, + data => { + if (data.tiles == undefined) { + data.tiles = new Map() + } + + for (const tile of tiles) { + const position: MapTilePosition = {x: tile.position.x, y: tile.position.y} + data.tiles.set(position, tile.name) + } + + if (updater != undefined) { + updater(data) + } + } + ) +} + + +function getTiles( + surface: LuaSurface | undefined, + area: BoundingBoxTable +): LuaTile[] { + return surface?.find_tiles_filtered({ + area: area, + // collision_mask: ["ground-tile", "water-tile"] + } + ) ?? [] +} + +function getSurface(surfaceIndex: uint): LuaSurface | undefined { + return game.surfaces[surfaceIndex] +} + +script.on_event( + defines.events.on_chunk_generated, + (e: OnChunkGeneratedEvent) => { + let tiles = getTiles(e.surface, e.area) + mapTilesUpdateDebounce(e.surface, e.position, tiles) + } +) + +script.on_event( + defines.events.on_chunk_charted, + (e: OnChunkChartedEvent) => { + + const surface = getSurface(e.surface_index) + if (surface == undefined) { + return + } + + let tiles = getTiles(surface, e.area) + mapTilesUpdateDebounce(surface, e.position, tiles, (data => { + data.force = e.force.index + })) + } +) + +script.on_event( + defines.events.script_raised_set_tiles, + (e: ScriptRaisedSetTilesEvent) => { + + const surface = getSurface(e.surface_index) + if (surface == undefined) { + return + } + + const groupedTiles = groupTiles(e.tiles) + + for (const [chunkPos, tiles] of groupedTiles) { + mapTilesUpdateDebounce(surface, chunkPos, tiles) + } + } +) + + +function groupTiles(tiles: TileRead[]): Map { + + const mapChunkPositionToTiles = new Map() + for (const tile of tiles) { + const chunkPosition = { + x: math.floor((tile.position.x / 32)), + y: math.floor((tile.position.y / 32)), + } + if (!mapChunkPositionToTiles.has(chunkPosition)) { + mapChunkPositionToTiles.set(chunkPosition, []) + } + mapChunkPositionToTiles.get(chunkPosition)?.push(tile) + } + return mapChunkPositionToTiles +} + +function convertOldPosition( + oldTiles: OldTileAndPosition[], + placedTile: LuaTilePrototype, +): TileRead[] { + + return oldTiles.map((tile) => { + return { + position: {x: tile.position.x, y: tile.position.y}, + name: placedTile.name, + } + } + ) +} + +function onBuildTileEvent(event: OnPlayerBuiltTileEvent | OnRobotBuiltTileEvent) { + + const surface = getSurface(event.surface_index) + if (surface == undefined) { + return + } + + const tiles: TileRead[] = convertOldPosition(event.tiles, event.tile) + const groupedTiles = groupTiles(tiles) + + for (const [chunkPos, tiles] of groupedTiles) { + mapTilesUpdateDebounce( + surface, + chunkPos, + tiles, + (data => { + if (isEventType(event, defines.events.on_player_built_tile)) { + data.player = event.player_index + return + } + if (isEventType(event, defines.events.on_robot_built_tile)) { + data.robot = { + unitNumber: event.robot?.unit_number ?? null, + name: event.robot.name, + type: event.robot.type, + } + return + } + // this line will not compile if the previous 'if' statements are not exhaustive + // noinspection UnnecessaryLocalVariableJS,JSUnusedLocalSymbols + const exhaustiveCheck: never = event + } + ) + ) + } +} + +script.on_event(defines.events.on_player_built_tile, (e: OnPlayerBuiltTileEvent) => onBuildTileEvent(e)) +script.on_event(defines.events.on_robot_built_tile, (e: OnRobotBuiltTileEvent) => onBuildTileEvent(e)) + +// script.on_event( +// defines.events.on_player_mined_tile, +// (e: OnPlayerMinedTileEvent) => { +// // need to group tiles by ChunkPosition... +// +// } +// ) + +// script.on_event( +// defines.events.on_robot_mined_tile, +// (e: OnRobotMinedTileEvent) => { +// // need to group tiles by ChunkPosition... +// +// } +// ) + + +script.on_event( + defines.events.on_pre_chunk_deleted, + (e: OnPreChunkDeletedEvent) => { + + const surface = getSurface(e.surface_index) + if (surface == undefined) { + return + } + + for (const position of e.positions) { + const key: CacheKey<"MAP_CHUNK"> = { + surfaceIndex: surface.index, + chunkPosition: position, + updateType: "MAP_CHUNK", + } + + EventDataCache.debounce<"MAP_CHUNK">( + key, + data => { + data.isDeleted = true + } + ) + // deletion is important - emit ASAP + EventDataCache.setExpiration(key, 0) + } + } +) diff --git a/modules/events-mod/src/main/typescript/main/events/playerEvents.ts b/modules/events-mod/src/main/typescript/main/events/playerEvents.ts new file mode 100644 index 0000000..4cf49b0 --- /dev/null +++ b/modules/events-mod/src/main/typescript/main/events/playerEvents.ts @@ -0,0 +1,178 @@ +import {EventDataCache} from "../cache/EventDataCache"; +import {Converters} from "./converters"; +import CacheData = EventDataCache.CacheData; + +type PlayerUpdater = (player: LuaPlayer, data: CacheData<"PLAYER">) => void + +function playerUpdateThrottle( + playerIndex: uint, + mutate: PlayerUpdater, +) { + EventDataCache.throttle<"PLAYER">( + {index: playerIndex, updateType: "PLAYER"}, + (data => { + const player = game.players[playerIndex] + if (player != undefined) { + mutate(player, data) + } + }) + ) +} + +function playerUpdateDebounce(playerIndex: uint, mutate: PlayerUpdater) { + EventDataCache.debounce<"PLAYER">( + {index: playerIndex, updateType: "PLAYER"}, + (data => { + const player = game.players[playerIndex] + mutate(player, data) + }) + ) +} + +function playerOnlineInfo(player: LuaPlayer, data: CacheData<"PLAYER">) { + data.lastOnline = player.last_online + data.onlineTime = player.online_time + data.afkTime = player.afk_time + data.isConnected = player.connected +} + +script.on_event( + defines.events.on_player_joined_game, + (e: OnPlayerJoinedGameEvent) => { + playerUpdateThrottle( + e.player_index, + (player, data) => { + data.isAdmin = player.admin + data.characterUnitNumber = player.character?.unit_number + data.chatColour = Converters.mapColour(player.chat_color) + data.colour = Converters.mapColour(player.color) + data.forceIndex = player.force.index + data.name = player.name + data.isShowOnMap = player.show_on_map + data.isSpectator = player.spectator + data.tag = player.tag + playerOnlineInfo(player, data) + } + ) + } +) + +script.on_event( + defines.events.on_player_changed_position, + (e: OnPlayerChangedPositionEvent) => { + playerUpdateThrottle( + e.player_index, + (player, data) => { + data.position = player.position + } + ) + } +) + +script.on_event( + defines.events.on_player_changed_surface, + (e: OnPlayerChangedSurfaceEvent) => { + playerUpdateThrottle( + e.player_index, + (player, data) => { + data.position = player.position + data.surfaceIndex = player.surface.index + } + ) + } +) + +script.on_event( + defines.events.on_player_died, + (e: OnPlayerDiedEvent) => { + playerUpdateThrottle( + e.player_index, + (player, data) => { + data.ticksToRespawn = player.ticks_to_respawn + playerOnlineInfo(player, data) + if (e.cause != undefined) { + data.diedCause = { + unitNumber: e.cause.unit_number ?? null, + name: e.cause.name, + type: e.cause.type + } + } + } + ) + } +) + +script.on_event( + defines.events.on_player_banned, + (e: OnPlayerBannedEvent) => { + if (e.player_index != undefined) { + playerUpdateThrottle( + e.player_index, + (player, data) => { + data.bannedReason = e.reason + playerOnlineInfo(player, data) + } + ) + } + } +) + +script.on_event( + defines.events.on_player_unbanned, + (e: OnPlayerUnbannedEvent) => { + if (e.player_index != undefined) { + playerUpdateThrottle( + e.player_index, + (player, data) => { + data.bannedReason = e.reason + playerOnlineInfo(player, data) + } + ) + } + } +) + +script.on_event( + defines.events.on_player_kicked, + (e: OnPlayerKickedEvent) => { + playerUpdateThrottle( + e.player_index, + (player, data) => { + data.kickedReason = e.reason + playerOnlineInfo(player, data) + } + ) + } +) + + +const disconnectReasons = new LuaTable() +for (const [name, disconnectId] of pairs(defines.disconnect_reason)) { + disconnectReasons.set(disconnectId, name) +} + +script.on_event( + defines.events.on_pre_player_left_game, + (e: OnPrePlayerLeftGameEvent) => { + playerUpdateThrottle( + e.player_index, + (player, data) => { + data.disconnectReason = disconnectReasons.get(e.reason) + playerOnlineInfo(player, data) + } + ) + } +) + +script.on_event( + defines.events.on_player_removed, + (e: OnPlayerRemovedEvent) => { + playerUpdateThrottle( + e.player_index, + (player, data) => { + data.isRemoved = true + playerOnlineInfo(player, data) + } + ) + } +) diff --git a/modules/events-mod/src/main/typescript/main/events/registerHandlers.ts b/modules/events-mod/src/main/typescript/main/events/registerHandlers.ts index 61e4f60..339ce17 100644 --- a/modules/events-mod/src/main/typescript/main/events/registerHandlers.ts +++ b/modules/events-mod/src/main/typescript/main/events/registerHandlers.ts @@ -2,12 +2,12 @@ import { handleChunkUpdate, handleConsoleChat, handleEntityUpdate, - handlePlayerUpdate, + // handlePlayerUpdate, handleSurfaceUpdate, handleTilesUpdate } from "./handlers"; import {Queue} from "../queue/queue"; -import {EventName} from "../global"; +import {EventName} from "../types"; const mapEventIdToName = new LuaTable() @@ -32,24 +32,24 @@ script.on_event( defines.events.on_player_mined_entity, (e: OnPlayerMinedEntityEvent) => { let eventName = mapEventIdToName.get(e.name) - handlePlayerUpdate(e.tick, eventName, e.player_index) + // handlePlayerUpdate(e.tick, eventName, e.player_index) handleEntityUpdate(e.tick, eventName, e.entity) } ) -script.on_event( - defines.events.on_player_joined_game, - (e: OnPlayerJoinedGameEvent) => { - handlePlayerUpdate(e.tick, mapEventIdToName.get(e.name), e.player_index) - } -) +// script.on_event( +// defines.events.on_player_joined_game, +// (e: OnPlayerJoinedGameEvent) => { +// handlePlayerUpdate(e.tick, mapEventIdToName.get(e.name), e.player_index) +// } +// ) -script.on_event( - defines.events.on_player_changed_position, - (e: OnPlayerChangedPositionEvent) => { - handlePlayerUpdate(e.tick, mapEventIdToName.get(e.name), e.player_index) - } -) +// script.on_event( +// defines.events.on_player_changed_position, +// (e: OnPlayerChangedPositionEvent) => { +// handlePlayerUpdate(e.tick, mapEventIdToName.get(e.name), e.player_index) +// } +// ) script.on_event( defines.events.on_tick, @@ -113,12 +113,3 @@ script.on_event( ) } ) - - -function isEventType( - eventData: EventData, - type: ED extends CustomInputEvent ? string : EventId -): eventData is ED { - let id: EventId | string = eventData.name - return id == type -} diff --git a/modules/events-mod/src/main/typescript/main/global.d.ts b/modules/events-mod/src/main/typescript/main/global.d.ts index b8122e7..7a73643 100644 --- a/modules/events-mod/src/main/typescript/main/global.d.ts +++ b/modules/events-mod/src/main/typescript/main/global.d.ts @@ -2,11 +2,3 @@ declare const global: { MOD_VERSION: string FACTORIO_VERSION: string } - -export type EventName = keyof typeof defines.events - -type NonNullKeys = { - [P in keyof T]: null extends Exclude ? never : P -}[keyof T]; - -type ExcludeNullKeys = Pick> diff --git a/modules/events-mod/src/main/typescript/main/types.d.ts b/modules/events-mod/src/main/typescript/main/types.d.ts new file mode 100644 index 0000000..62198ea --- /dev/null +++ b/modules/events-mod/src/main/typescript/main/types.d.ts @@ -0,0 +1,17 @@ +export type EventName = keyof typeof defines.events + + +/** Get all keys of `TYPE` that are not nullable. */ +type NonNullKeys = { + [KEY in keyof TYPE]: null extends Exclude ? never : KEY +}[keyof TYPE]; + + +/** Exclude all nullable keys from `TYPE`. */ +type ExcludeNullKeys = Pick> + + +/** Make all keys of `TYPE` non-nullable. */ +type NonNullableKeys = { + [KEY in keyof TYPE]: NonNullable; +}