- update data model: simplify key/data (by removing data)
This commit is contained in:
parent
b82e3a1bbf
commit
8e7208ba08
8 changed files with 221 additions and 282 deletions
|
|
@ -6,11 +6,8 @@ interface FactorioEventUpdateKey {
|
||||||
updateType: FactorioEventUpdateType;
|
updateType: FactorioEventUpdateType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FactorioEventUpdateData {
|
interface FactorioEventUpdate extends FactorioEventUpdateKey {
|
||||||
updateType: FactorioEventUpdateType;
|
events: string[] | null;
|
||||||
}
|
|
||||||
|
|
||||||
interface FactorioEventUpdate extends FactorioEventUpdateKey, FactorioEventUpdateData {
|
|
||||||
updateType: FactorioEventUpdateType;
|
updateType: FactorioEventUpdateType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,31 +22,7 @@ interface PlayerUpdateKey extends FactorioEventUpdateKey {
|
||||||
index: uint;
|
index: uint;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PlayerUpdateData extends FactorioEventUpdateData {
|
interface PlayerUpdate extends FactorioEventUpdate, PlayerUpdateKey {
|
||||||
afkTime: uint | null;
|
|
||||||
bannedReason: string | null;
|
|
||||||
characterUnitNumber: uint | null;
|
|
||||||
chatColour: Colour | null;
|
|
||||||
colour: Colour | null;
|
|
||||||
diedCause: EntityIdentifiers | null;
|
|
||||||
disconnectReason: string | null;
|
|
||||||
forceIndex: uint | null;
|
|
||||||
isAdmin: boolean | null;
|
|
||||||
isConnected: boolean | null;
|
|
||||||
isRemoved: boolean | null;
|
|
||||||
isShowOnMap: boolean | null;
|
|
||||||
isSpectator: boolean | null;
|
|
||||||
kickedReason: string | null;
|
|
||||||
lastOnline: uint | null;
|
|
||||||
name: string | null;
|
|
||||||
onlineTime: uint | null;
|
|
||||||
position: MapEntityPosition | null;
|
|
||||||
surfaceIndex: uint | null;
|
|
||||||
tag: string | null;
|
|
||||||
ticksToRespawn: uint | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PlayerUpdate extends FactorioEventUpdate, PlayerUpdateKey, PlayerUpdateData {
|
|
||||||
afkTime: uint | null;
|
afkTime: uint | null;
|
||||||
bannedReason: string | null;
|
bannedReason: string | null;
|
||||||
characterUnitNumber: uint | null;
|
characterUnitNumber: uint | null;
|
||||||
|
|
@ -57,6 +30,7 @@ interface PlayerUpdate extends FactorioEventUpdate, PlayerUpdateKey, PlayerUpdat
|
||||||
colour: Colour | null;
|
colour: Colour | null;
|
||||||
diedCause: EntityIdentifiers | null;
|
diedCause: EntityIdentifiers | null;
|
||||||
disconnectReason: string | null;
|
disconnectReason: string | null;
|
||||||
|
events: string[] | null;
|
||||||
forceIndex: uint | null;
|
forceIndex: uint | null;
|
||||||
index: uint;
|
index: uint;
|
||||||
isAdmin: boolean | null;
|
isAdmin: boolean | null;
|
||||||
|
|
@ -81,20 +55,9 @@ interface EntityUpdateKey extends EntityIdentifiers, FactorioEventUpdateKey {
|
||||||
unitNumber: uint;
|
unitNumber: uint;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EntityUpdateData extends FactorioEventUpdateData {
|
interface EntityUpdate extends FactorioEventUpdate, EntityIdentifiers, EntityUpdateKey {
|
||||||
chunkPosition: MapChunkPosition | null;
|
|
||||||
graphicsVariation: number | null;
|
|
||||||
health: float | null;
|
|
||||||
isActive: boolean | null;
|
|
||||||
isRotatable: boolean | null;
|
|
||||||
lastUser: int | null;
|
|
||||||
localisedDescription: string | null;
|
|
||||||
localisedName: string | null;
|
|
||||||
prototype: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EntityUpdate extends FactorioEventUpdate, EntityIdentifiers, EntityUpdateKey, EntityUpdateData {
|
|
||||||
chunkPosition: MapChunkPosition | null;
|
chunkPosition: MapChunkPosition | null;
|
||||||
|
events: string[] | null;
|
||||||
graphicsVariation: number | null;
|
graphicsVariation: number | null;
|
||||||
health: float | null;
|
health: float | null;
|
||||||
isActive: boolean | null;
|
isActive: boolean | null;
|
||||||
|
|
@ -114,16 +77,9 @@ interface MapChunkUpdateKey extends FactorioEventUpdateKey {
|
||||||
surfaceIndex: uint;
|
surfaceIndex: uint;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MapChunkUpdateData extends FactorioEventUpdateData {
|
interface MapChunkUpdate extends FactorioEventUpdate, MapChunkUpdateKey {
|
||||||
force: uint | null;
|
|
||||||
isDeleted: boolean | null;
|
|
||||||
player: uint | null;
|
|
||||||
robot: EntityIdentifiers | null;
|
|
||||||
tiles: MapTile[] | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MapChunkUpdate extends FactorioEventUpdate, MapChunkUpdateKey, MapChunkUpdateData {
|
|
||||||
chunkPosition: MapChunkPosition;
|
chunkPosition: MapChunkPosition;
|
||||||
|
events: string[] | null;
|
||||||
force: uint | null;
|
force: uint | null;
|
||||||
isDeleted: boolean | null;
|
isDeleted: boolean | null;
|
||||||
player: uint | null;
|
player: uint | null;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import {NonNullableKeys} from "../types";
|
|
||||||
|
|
||||||
export namespace EventDataCache {
|
export namespace EventDataCache {
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -88,8 +86,7 @@ export namespace EventDataCache {
|
||||||
const expiredData: Array<FactorioEventUpdate> = []
|
const expiredData: Array<FactorioEventUpdate> = []
|
||||||
for (let [key, entry] of global.cache) {
|
for (let [key, entry] of global.cache) {
|
||||||
if (isExpired(entry)) {
|
if (isExpired(entry)) {
|
||||||
const update: FactorioEventUpdate = {...key, ...entry.data}
|
expiredData.push(entry.data)
|
||||||
expiredData.push(update)
|
|
||||||
global.cache.delete(key)
|
global.cache.delete(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +101,7 @@ export namespace EventDataCache {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
const value: CacheEntry<any> = global.cache.get(key)
|
const value: CacheEntry<any> = global.cache.get(key)
|
||||||
if (isType(value, key.updateType)) {
|
if (isEntryInstanceOf(value, key.updateType)) {
|
||||||
return value
|
return value
|
||||||
} else {
|
} else {
|
||||||
// Type mismatch. This shouldn't happen...
|
// Type mismatch. This shouldn't happen...
|
||||||
|
|
@ -117,8 +114,7 @@ export namespace EventDataCache {
|
||||||
key: CacheKey<TYPE>,
|
key: CacheKey<TYPE>,
|
||||||
mutate: CacheDataMutator<TYPE>,
|
mutate: CacheDataMutator<TYPE>,
|
||||||
): CacheEntry<TYPE> {
|
): CacheEntry<TYPE> {
|
||||||
// @ts-ignore // TODO resolve ts-ignore for "not assignable to type"
|
const data: CacheData<TYPE> = <CacheData<TYPE>>{updateType: key.updateType}
|
||||||
const data: CacheData<TYPE> = {updateType: key.updateType}
|
|
||||||
mutate(data)
|
mutate(data)
|
||||||
let entry: CacheEntry<TYPE> = new CacheEntry<TYPE>(data)
|
let entry: CacheEntry<TYPE> = new CacheEntry<TYPE>(data)
|
||||||
global.cache.set(key, entry)
|
global.cache.set(key, entry)
|
||||||
|
|
@ -127,34 +123,35 @@ export namespace EventDataCache {
|
||||||
|
|
||||||
|
|
||||||
// /** Map a {@link FactorioEventUpdateType} to a {@link FactorioEventUpdate} DTO */
|
// /** Map a {@link FactorioEventUpdateType} to a {@link FactorioEventUpdate} DTO */
|
||||||
// type ConvertUpdateType<TYPE extends FactorioEventUpdateType> =
|
type ConvertToUpdate<TYPE extends FactorioEventUpdateType> =
|
||||||
// TYPE extends "PLAYER" ? PlayerUpdate :
|
TYPE extends "PLAYER" ? PlayerUpdate :
|
||||||
// TYPE extends "MAP_CHUNK" ? MapChunkUpdate :
|
TYPE extends "MAP_CHUNK" ? MapChunkUpdate :
|
||||||
// TYPE extends "ENTITY" ? EntityUpdate :
|
TYPE extends "ENTITY" ? EntityUpdate :
|
||||||
// never
|
never
|
||||||
|
|
||||||
type ConvertKeyType<TYPE extends FactorioEventUpdateType> =
|
type ConvertToUpdateKey<TYPE extends FactorioEventUpdateType> =
|
||||||
TYPE extends "PLAYER" ? PlayerUpdateKey :
|
TYPE extends "PLAYER" ? PlayerUpdateKey :
|
||||||
TYPE extends "MAP_CHUNK" ? MapChunkUpdateKey :
|
TYPE extends "MAP_CHUNK" ? MapChunkUpdateKey :
|
||||||
TYPE extends "ENTITY" ? EntityUpdateKey :
|
TYPE extends "ENTITY" ? EntityUpdateKey :
|
||||||
never
|
never
|
||||||
type ConvertKeyData<TYPE extends FactorioEventUpdateType> =
|
// type ConvertToUpdateData<TYPE extends FactorioEventUpdateType> =
|
||||||
TYPE extends "PLAYER" ? PlayerUpdateData :
|
// TYPE extends "PLAYER" ? PlayerUpdateData :
|
||||||
TYPE extends "MAP_CHUNK" ? MapChunkUpdateData :
|
// TYPE extends "MAP_CHUNK" ? MapChunkUpdateData :
|
||||||
TYPE extends "ENTITY" ? EntityUpdateData :
|
// TYPE extends "ENTITY" ? EntityUpdateData :
|
||||||
never
|
// never
|
||||||
|
|
||||||
|
|
||||||
/** Only include the non-null properties, and make `updateType` specific */
|
/** Make `updateType` specific */
|
||||||
export type CacheKey<TYPE extends FactorioEventUpdateType> =
|
export type CacheKey<TYPE extends FactorioEventUpdateType> =
|
||||||
CacheTyped<TYPE>
|
CacheTyped<TYPE>
|
||||||
& Omit<ConvertKeyType<TYPE>, "updateType">
|
& Omit<ConvertToUpdateKey<TYPE>, "updateType">
|
||||||
|
|
||||||
|
|
||||||
/** Exclude {@link CacheKey} fields, and make `updateType` specific */
|
/** Make nullable-fields optional, and `updateType` specific */
|
||||||
export type CacheData<TYPE extends FactorioEventUpdateType> =
|
export type CacheData<TYPE extends FactorioEventUpdateType> =
|
||||||
CacheTyped<TYPE>
|
CacheTyped<TYPE>
|
||||||
& NonNullableKeys<Partial<Omit<ConvertKeyData<TYPE>, "updateType">>>
|
& Omit<ConvertToUpdate<TYPE>, "updateType">
|
||||||
|
// & NullablePartial<Omit<ConvertToUpdate<TYPE>, "updateType">>
|
||||||
|
|
||||||
|
|
||||||
export type CacheTyped<TYPE extends FactorioEventUpdateType> = {
|
export type CacheTyped<TYPE extends FactorioEventUpdateType> = {
|
||||||
|
|
@ -189,54 +186,19 @@ export namespace EventDataCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function isType<TYPE extends FactorioEventUpdateType>(
|
function isEntryInstanceOf<TYPE extends FactorioEventUpdateType>(
|
||||||
data: CacheEntry<TYPE>,
|
data: CacheEntry<any>,
|
||||||
updateType: TYPE,
|
updateType: TYPE,
|
||||||
): data is CacheEntry<TYPE> {
|
): data is CacheEntry<TYPE> {
|
||||||
return data.data.updateType == updateType
|
return isDataInstanceOf<TYPE>(data.data, updateType)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function isDataInstanceOf<TYPE extends FactorioEventUpdateType>(
|
||||||
|
data: CacheData<any>,
|
||||||
|
updateType: TYPE,
|
||||||
|
): data is CacheData<TYPE> {
|
||||||
|
return data.updateType == updateType
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// interface FactorioEventUpdate {
|
|
||||||
// type: string
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// interface Update<TYPE extends FactorioEventUpdateTypeType> {
|
|
||||||
// type: T
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// export interface PlayerUpdate extends Update<"PLAYER"> {
|
|
||||||
// index: uint
|
|
||||||
//
|
|
||||||
// unhandledEvents?: string[]
|
|
||||||
//
|
|
||||||
// characterUnitNumber?: uint
|
|
||||||
// chatColour?: Colour
|
|
||||||
// colour?: Colour
|
|
||||||
// disconnectReason?: string
|
|
||||||
// forceIndex?: uint
|
|
||||||
// isAdmin?: boolean
|
|
||||||
// isConnected?: boolean
|
|
||||||
// isShowOnMap?: boolean
|
|
||||||
// isSpectator?: boolean
|
|
||||||
// lastOnline?: uint
|
|
||||||
// afkTime?: uint
|
|
||||||
// name?: string
|
|
||||||
// onlineTime?: uint
|
|
||||||
// position?: MapEntityPosition
|
|
||||||
// surfaceIndex?: uint
|
|
||||||
// ticksToRespawn?: uint
|
|
||||||
// tag?: string
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export type CacheKey<Type> = MapChunkCacheKey | EntityCacheKey | PlayerCacheKey & {
|
|
||||||
// type: Type
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// export function isCacheType<CK extends CacheKey>(
|
|
||||||
// cacheKey: CacheKey,
|
|
||||||
// type: CacheType
|
|
||||||
// ): cacheKey is CK {
|
|
||||||
// return cacheKey.type == type
|
|
||||||
// }
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import {EventName} from "../types";
|
||||||
|
|
||||||
export namespace Converters {
|
export namespace Converters {
|
||||||
|
|
||||||
// export function playerToTable(player: LuaPlayer): PlayerData {
|
// export function playerToTable(player: LuaPlayer): PlayerData {
|
||||||
|
|
@ -15,6 +17,18 @@ export namespace Converters {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
const mapEventIdToName = new LuaTable<defines.Events, EventName>()
|
||||||
|
for (const [eventName, eventId] of pairs(defines.events)) {
|
||||||
|
mapEventIdToName.set(eventId, eventName)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function eventNameString(event: defines.Events): EventName {
|
||||||
|
return mapEventIdToName.get(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import {EventDataCache} from "../cache/EventDataCache";
|
import {EventDataCache} from "../cache/EventDataCache";
|
||||||
import {isEventType} from "./eventTypeCheck";
|
import {isEventType} from "./eventTypeCheck";
|
||||||
|
import {Converters} from "./converters";
|
||||||
import CacheKey = EventDataCache.CacheKey;
|
import CacheKey = EventDataCache.CacheKey;
|
||||||
import CacheData = EventDataCache.CacheData;
|
import CacheData = EventDataCache.CacheData;
|
||||||
|
|
||||||
|
|
@ -11,8 +12,10 @@ function mapTilesUpdateDebounce(
|
||||||
surface: LuaSurface | undefined,
|
surface: LuaSurface | undefined,
|
||||||
chunkPosition: ChunkPositionTable,
|
chunkPosition: ChunkPositionTable,
|
||||||
tiles: TileRead[],
|
tiles: TileRead[],
|
||||||
updater?: MapChunkUpdater
|
eventName: string,
|
||||||
|
updater?: MapChunkUpdater,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
if (surface == undefined) {
|
if (surface == undefined) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +41,13 @@ function mapTilesUpdateDebounce(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.events == null) {
|
||||||
|
data.events = []
|
||||||
|
}
|
||||||
|
if (eventName ! in data.events) {
|
||||||
|
data.events.push(eventName)
|
||||||
|
}
|
||||||
|
|
||||||
if (updater != undefined) {
|
if (updater != undefined) {
|
||||||
updater(data)
|
updater(data)
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +77,7 @@ script.on_event(
|
||||||
log(`on_chunk_generated ${e.tick}`)
|
log(`on_chunk_generated ${e.tick}`)
|
||||||
|
|
||||||
let tiles = getTiles(e.surface, e.area)
|
let tiles = getTiles(e.surface, e.area)
|
||||||
mapTilesUpdateDebounce(e.surface, e.position, tiles)
|
mapTilesUpdateDebounce(e.surface, e.position, tiles, Converters.eventNameString(e.name))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -76,15 +86,15 @@ script.on_event(
|
||||||
(e: OnChunkChartedEvent) => {
|
(e: OnChunkChartedEvent) => {
|
||||||
log(`on_chunk_charted ${e.tick}`)
|
log(`on_chunk_charted ${e.tick}`)
|
||||||
|
|
||||||
const surface = getSurface(e.surface_index)
|
// const surface = getSurface(e.surface_index)
|
||||||
if (surface == undefined) {
|
// if (surface == undefined) {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
let tiles = getTiles(surface, e.area)
|
// let tiles = getTiles(surface, e.area)
|
||||||
mapTilesUpdateDebounce(surface, e.position, tiles, (data => {
|
// mapTilesUpdateDebounce(surface, e.position, tiles, (data => {
|
||||||
data.force = e.force.index
|
// data.force = e.force.index
|
||||||
}))
|
// }))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -101,7 +111,7 @@ script.on_event(
|
||||||
const groupedTiles = groupTiles(e.tiles)
|
const groupedTiles = groupTiles(e.tiles)
|
||||||
|
|
||||||
for (const [chunkPos, tiles] of groupedTiles) {
|
for (const [chunkPos, tiles] of groupedTiles) {
|
||||||
mapTilesUpdateDebounce(surface, chunkPos, tiles)
|
mapTilesUpdateDebounce(surface, chunkPos, tiles, Converters.eventNameString(e.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -146,12 +156,14 @@ function onBuildTileEvent(event: OnPlayerBuiltTileEvent | OnRobotBuiltTileEvent)
|
||||||
|
|
||||||
const tiles: TileRead[] = convertOldPosition(event.tiles, event.tile)
|
const tiles: TileRead[] = convertOldPosition(event.tiles, event.tile)
|
||||||
const groupedTiles = groupTiles(tiles)
|
const groupedTiles = groupTiles(tiles)
|
||||||
|
const eventName = Converters.eventNameString(event.name)
|
||||||
|
|
||||||
for (const [chunkPos, tiles] of groupedTiles) {
|
for (const [chunkPos, tiles] of groupedTiles) {
|
||||||
mapTilesUpdateDebounce(
|
mapTilesUpdateDebounce(
|
||||||
surface,
|
surface,
|
||||||
chunkPos,
|
chunkPos,
|
||||||
tiles,
|
tiles,
|
||||||
|
eventName,
|
||||||
(data => {
|
(data => {
|
||||||
if (isEventType(event, defines.events.on_player_built_tile)) {
|
if (isEventType(event, defines.events.on_player_built_tile)) {
|
||||||
data.player = event.player_index
|
data.player = event.player_index
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ type PlayerUpdater = (player: LuaPlayer, data: CacheData<"PLAYER">) => void
|
||||||
|
|
||||||
function playerUpdateThrottle(
|
function playerUpdateThrottle(
|
||||||
playerIndex: uint,
|
playerIndex: uint,
|
||||||
|
eventName: string,
|
||||||
mutate: PlayerUpdater,
|
mutate: PlayerUpdater,
|
||||||
) {
|
) {
|
||||||
EventDataCache.throttle<"PLAYER">(
|
EventDataCache.throttle<"PLAYER">(
|
||||||
|
|
@ -15,6 +16,13 @@ function playerUpdateThrottle(
|
||||||
if (player != undefined) {
|
if (player != undefined) {
|
||||||
mutate(player, data)
|
mutate(player, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.events == null) {
|
||||||
|
data.events = []
|
||||||
|
}
|
||||||
|
if (eventName ! in data.events) {
|
||||||
|
data.events.push(eventName)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -41,9 +49,10 @@ script.on_event(
|
||||||
(e: OnPlayerJoinedGameEvent) => {
|
(e: OnPlayerJoinedGameEvent) => {
|
||||||
playerUpdateThrottle(
|
playerUpdateThrottle(
|
||||||
e.player_index,
|
e.player_index,
|
||||||
|
Converters.eventNameString(e.name),
|
||||||
(player, data) => {
|
(player, data) => {
|
||||||
data.isAdmin = player.admin
|
data.isAdmin = player.admin
|
||||||
data.characterUnitNumber = player.character?.unit_number
|
data.characterUnitNumber = player.character?.unit_number ?? null
|
||||||
data.chatColour = Converters.mapColour(player.chat_color)
|
data.chatColour = Converters.mapColour(player.chat_color)
|
||||||
data.colour = Converters.mapColour(player.color)
|
data.colour = Converters.mapColour(player.color)
|
||||||
data.forceIndex = player.force.index
|
data.forceIndex = player.force.index
|
||||||
|
|
@ -62,6 +71,7 @@ script.on_event(
|
||||||
(e: OnPlayerChangedPositionEvent) => {
|
(e: OnPlayerChangedPositionEvent) => {
|
||||||
playerUpdateThrottle(
|
playerUpdateThrottle(
|
||||||
e.player_index,
|
e.player_index,
|
||||||
|
Converters.eventNameString(e.name),
|
||||||
(player, data) => {
|
(player, data) => {
|
||||||
data.position = player.position
|
data.position = player.position
|
||||||
}
|
}
|
||||||
|
|
@ -74,6 +84,7 @@ script.on_event(
|
||||||
(e: OnPlayerChangedSurfaceEvent) => {
|
(e: OnPlayerChangedSurfaceEvent) => {
|
||||||
playerUpdateThrottle(
|
playerUpdateThrottle(
|
||||||
e.player_index,
|
e.player_index,
|
||||||
|
Converters.eventNameString(e.name),
|
||||||
(player, data) => {
|
(player, data) => {
|
||||||
data.position = player.position
|
data.position = player.position
|
||||||
data.surfaceIndex = player.surface.index
|
data.surfaceIndex = player.surface.index
|
||||||
|
|
@ -87,8 +98,9 @@ script.on_event(
|
||||||
(e: OnPlayerDiedEvent) => {
|
(e: OnPlayerDiedEvent) => {
|
||||||
playerUpdateThrottle(
|
playerUpdateThrottle(
|
||||||
e.player_index,
|
e.player_index,
|
||||||
|
Converters.eventNameString(e.name),
|
||||||
(player, data) => {
|
(player, data) => {
|
||||||
data.ticksToRespawn = player.ticks_to_respawn
|
data.ticksToRespawn = player.ticks_to_respawn ?? null
|
||||||
playerOnlineInfo(player, data)
|
playerOnlineInfo(player, data)
|
||||||
if (e.cause != undefined) {
|
if (e.cause != undefined) {
|
||||||
data.diedCause = {
|
data.diedCause = {
|
||||||
|
|
@ -102,43 +114,31 @@ script.on_event(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
script.on_event(
|
script.on_event(defines.events.on_player_banned, handleBannedEvent)
|
||||||
defines.events.on_player_banned,
|
script.on_event(defines.events.on_player_unbanned, handleBannedEvent)
|
||||||
(e: OnPlayerBannedEvent) => {
|
|
||||||
if (e.player_index != undefined) {
|
|
||||||
playerUpdateThrottle(
|
|
||||||
e.player_index,
|
|
||||||
(player, data) => {
|
|
||||||
data.bannedReason = e.reason
|
|
||||||
playerOnlineInfo(player, data)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
script.on_event(
|
function handleBannedEvent(e: OnPlayerBannedEvent | OnPlayerUnbannedEvent) {
|
||||||
defines.events.on_player_unbanned,
|
|
||||||
(e: OnPlayerUnbannedEvent) => {
|
if (e.player_index != undefined) {
|
||||||
if (e.player_index != undefined) {
|
playerUpdateThrottle(
|
||||||
playerUpdateThrottle(
|
e.player_index,
|
||||||
e.player_index,
|
Converters.eventNameString(e.name),
|
||||||
(player, data) => {
|
(player, data) => {
|
||||||
data.bannedReason = e.reason
|
data.bannedReason = e.reason ?? null
|
||||||
playerOnlineInfo(player, data)
|
playerOnlineInfo(player, data)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
script.on_event(
|
script.on_event(
|
||||||
defines.events.on_player_kicked,
|
defines.events.on_player_kicked,
|
||||||
(e: OnPlayerKickedEvent) => {
|
(e: OnPlayerKickedEvent) => {
|
||||||
playerUpdateThrottle(
|
playerUpdateThrottle(
|
||||||
e.player_index,
|
e.player_index,
|
||||||
|
Converters.eventNameString(e.name),
|
||||||
(player, data) => {
|
(player, data) => {
|
||||||
data.kickedReason = e.reason
|
data.kickedReason = e.reason ?? null
|
||||||
playerOnlineInfo(player, data)
|
playerOnlineInfo(player, data)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -156,6 +156,7 @@ script.on_event(
|
||||||
(e: OnPrePlayerLeftGameEvent) => {
|
(e: OnPrePlayerLeftGameEvent) => {
|
||||||
playerUpdateThrottle(
|
playerUpdateThrottle(
|
||||||
e.player_index,
|
e.player_index,
|
||||||
|
Converters.eventNameString(e.name),
|
||||||
(player, data) => {
|
(player, data) => {
|
||||||
data.disconnectReason = disconnectReasons.get(e.reason)
|
data.disconnectReason = disconnectReasons.get(e.reason)
|
||||||
playerOnlineInfo(player, data)
|
playerOnlineInfo(player, data)
|
||||||
|
|
@ -169,6 +170,7 @@ script.on_event(
|
||||||
(e: OnPlayerRemovedEvent) => {
|
(e: OnPlayerRemovedEvent) => {
|
||||||
playerUpdateThrottle(
|
playerUpdateThrottle(
|
||||||
e.player_index,
|
e.player_index,
|
||||||
|
Converters.eventNameString(e.name),
|
||||||
(player, data) => {
|
(player, data) => {
|
||||||
data.isRemoved = true
|
data.isRemoved = true
|
||||||
playerOnlineInfo(player, data)
|
playerOnlineInfo(player, data)
|
||||||
|
|
|
||||||
|
|
@ -3,23 +3,16 @@ import {
|
||||||
handleConsoleChat,
|
handleConsoleChat,
|
||||||
handleEntityUpdate,
|
handleEntityUpdate,
|
||||||
handleSurfaceUpdate,
|
handleSurfaceUpdate,
|
||||||
// handleTilesUpdate
|
|
||||||
} from "./handlers";
|
} from "./handlers";
|
||||||
import {Queue} from "../queue/queue";
|
import {Queue} from "../queue/queue";
|
||||||
import {EventName} from "../types";
|
|
||||||
import {isEventType} from "./eventTypeCheck";
|
import {isEventType} from "./eventTypeCheck";
|
||||||
|
import {Converters} from "./converters";
|
||||||
|
|
||||||
const mapEventIdToName = new LuaTable<defines.Events, EventName>()
|
|
||||||
for (const [eventName, eventId] of pairs(defines.events)) {
|
|
||||||
mapEventIdToName.set(eventId, eventName)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
script.on_event(
|
script.on_event(
|
||||||
defines.events.on_player_mined_entity,
|
defines.events.on_player_mined_entity,
|
||||||
(e: OnPlayerMinedEntityEvent) => {
|
(e: OnPlayerMinedEntityEvent) => {
|
||||||
let eventName = mapEventIdToName.get(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)
|
||||||
}
|
}
|
||||||
|
|
@ -44,7 +37,7 @@ script.on_event(
|
||||||
(e: OnTickEvent) => {
|
(e: OnTickEvent) => {
|
||||||
if (e.tick % 1000 == 0) {
|
if (e.tick % 1000 == 0) {
|
||||||
for (const [, surface] of game.surfaces) {
|
for (const [, surface] of game.surfaces) {
|
||||||
handleSurfaceUpdate(e.tick, mapEventIdToName.get(e.name), surface)
|
handleSurfaceUpdate(e.tick, Converters.eventNameString(e.name), surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
// let packets = new KafkatorioPacketQueue().dequeueValues(1)
|
// let packets = new KafkatorioPacketQueue().dequeueValues(1)
|
||||||
|
|
@ -61,7 +54,7 @@ script.on_event(
|
||||||
|
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
if (isEventType(event, defines.events.on_chunk_generated)) {
|
if (isEventType(event, defines.events.on_chunk_generated)) {
|
||||||
let eName = mapEventIdToName.get(event.name)
|
let eName = Converters.eventNameString(event.name)
|
||||||
|
|
||||||
log(`[${e.tick}] dequed event ${eName}`)
|
log(`[${e.tick}] dequed event ${eName}`)
|
||||||
handleChunkUpdate(e.tick, eName, event.surface.index, event.position, event.area)
|
handleChunkUpdate(e.tick, eName, event.surface.index, event.position, event.area)
|
||||||
|
|
@ -75,29 +68,15 @@ script.on_event(
|
||||||
script.on_event(
|
script.on_event(
|
||||||
defines.events.on_console_chat,
|
defines.events.on_console_chat,
|
||||||
(e: OnConsoleChatEvent) => {
|
(e: OnConsoleChatEvent) => {
|
||||||
handleConsoleChat(e.tick, mapEventIdToName.get(e.name), e.player_index, e.message)
|
handleConsoleChat(e.tick, Converters.eventNameString(e.name), e.player_index, e.message)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// script.on_event(
|
// script.on_event(
|
||||||
// defines.events.on_chunk_generated,
|
// defines.events.on_chunk_generated,
|
||||||
// (e: OnChunkGeneratedEvent) => {
|
// (e: OnChunkGeneratedEvent) => {
|
||||||
// handleChunkUpdate(e.tick, mapEventIdToName.get(e.name), e.surface.index, e.position, e.area)
|
// handleChunkUpdate(e.tick, mapEventIdToName.get(e.name), e.surface.index, e.position,
|
||||||
// }
|
// e.area) } ) script.on_event( [ defines.events.on_player_built_tile,
|
||||||
// )
|
// defines.events.on_robot_built_tile, ], (builtTilesEvent) => { handleTilesUpdate(
|
||||||
//
|
// builtTilesEvent.tick, mapEventIdToName.get(builtTilesEvent.name), builtTilesEvent.surface_index,
|
||||||
// script.on_event(
|
// builtTilesEvent.tile, builtTilesEvent.tiles, ) } )
|
||||||
// [
|
|
||||||
// defines.events.on_player_built_tile,
|
|
||||||
// defines.events.on_robot_built_tile,
|
|
||||||
// ],
|
|
||||||
// (builtTilesEvent) => {
|
|
||||||
// handleTilesUpdate(
|
|
||||||
// builtTilesEvent.tick,
|
|
||||||
// mapEventIdToName.get(builtTilesEvent.name),
|
|
||||||
// builtTilesEvent.surface_index,
|
|
||||||
// builtTilesEvent.tile,
|
|
||||||
// builtTilesEvent.tiles,
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// )
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package dev.adamko.kafkatorio.events.schema
|
package dev.adamko.kafkatorio.events.schema
|
||||||
|
|
||||||
import dev.adamko.kafkatorio.events.schema.FactorioEventUpdate.FactorioEventUpdateType
|
import dev.adamko.kafkatorio.events.schema.FactorioEventUpdate.FactorioEventUpdateType
|
||||||
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.DeserializationStrategy
|
import kotlinx.serialization.DeserializationStrategy
|
||||||
import kotlinx.serialization.EncodeDefault
|
import kotlinx.serialization.EncodeDefault
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
@ -31,16 +32,19 @@ sealed interface FactorioEventUpdateKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sealed interface FactorioEventUpdateData {
|
//sealed interface FactorioEventUpdateData {
|
||||||
val updateType: FactorioEventUpdateType
|
// val updateType: FactorioEventUpdateType
|
||||||
}
|
// val event: String?
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
@Serializable(with = FactorioEventUpdate.Companion.JsonSerializer::class)
|
@Serializable(with = FactorioEventUpdate.Companion.JsonSerializer::class)
|
||||||
sealed class FactorioEventUpdate : FactorioEventUpdateKey, FactorioEventUpdateData {
|
sealed class FactorioEventUpdate : FactorioEventUpdateKey {
|
||||||
|
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
abstract override val updateType: FactorioEventUpdateType
|
abstract override val updateType: FactorioEventUpdateType
|
||||||
|
@Contextual
|
||||||
|
abstract val events: List<String>?
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class FactorioEventUpdateType {
|
enum class FactorioEventUpdateType {
|
||||||
|
|
@ -93,63 +97,66 @@ sealed interface PlayerUpdateKey : FactorioEventUpdateKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sealed interface PlayerUpdateData : FactorioEventUpdateData {
|
//sealed interface PlayerUpdateData : FactorioEventUpdateData {
|
||||||
val characterUnitNumber: UnitNumber?
|
// val characterUnitNumber: UnitNumber?
|
||||||
val chatColour: Colour?
|
// val chatColour: Colour?
|
||||||
val colour: Colour?
|
// val colour: Colour?
|
||||||
val name: String?
|
// val name: String?
|
||||||
|
//
|
||||||
val afkTime: Tick?
|
// val afkTime: Tick?
|
||||||
val ticksToRespawn: Tick?
|
// val ticksToRespawn: Tick?
|
||||||
val forceIndex: ForceIndex?
|
// val forceIndex: ForceIndex?
|
||||||
val isAdmin: Boolean?
|
// val isAdmin: Boolean?
|
||||||
val isConnected: Boolean?
|
// val isConnected: Boolean?
|
||||||
val isShowOnMap: Boolean?
|
// val isShowOnMap: Boolean?
|
||||||
val isSpectator: Boolean?
|
// val isSpectator: Boolean?
|
||||||
val lastOnline: Tick?
|
// val lastOnline: Tick?
|
||||||
val onlineTime: Tick?
|
// val onlineTime: Tick?
|
||||||
val position: MapEntityPosition?
|
// val position: MapEntityPosition?
|
||||||
val surfaceIndex: SurfaceIndex?
|
// val surfaceIndex: SurfaceIndex?
|
||||||
val tag: String?
|
// val tag: String?
|
||||||
val diedCause: EntityIdentifiers?
|
// val diedCause: EntityIdentifiers?
|
||||||
|
//
|
||||||
val bannedReason: String?
|
// val bannedReason: String?
|
||||||
val kickedReason: String?
|
// val kickedReason: String?
|
||||||
val disconnectReason: String?
|
// val disconnectReason: String?
|
||||||
/** `true` when a player is removed (deleted) from the game */
|
// /** `true` when a player is removed (deleted) from the game */
|
||||||
val isRemoved: Boolean?
|
// val isRemoved: Boolean?
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PlayerUpdate(
|
data class PlayerUpdate(
|
||||||
override val index: PlayerIndex,
|
override val index: PlayerIndex,
|
||||||
|
|
||||||
override val characterUnitNumber: UnitNumber? = null,
|
@Contextual
|
||||||
override val chatColour: Colour? = null,
|
override val events: List<String>? = null,
|
||||||
override val colour: Colour? = null,
|
|
||||||
override val name: String? = null,
|
|
||||||
|
|
||||||
override val afkTime: Tick? = null,
|
val characterUnitNumber: UnitNumber? = null,
|
||||||
override val ticksToRespawn: Tick? = null,
|
val chatColour: Colour? = null,
|
||||||
override val forceIndex: ForceIndex? = null,
|
val colour: Colour? = null,
|
||||||
override val isAdmin: Boolean? = null,
|
val name: String? = null,
|
||||||
override val isConnected: Boolean? = null,
|
|
||||||
override val isShowOnMap: Boolean? = null,
|
|
||||||
override val isSpectator: Boolean? = null,
|
|
||||||
override val lastOnline: Tick? = null,
|
|
||||||
override val onlineTime: Tick? = null,
|
|
||||||
override val position: MapEntityPosition? = null,
|
|
||||||
override val surfaceIndex: SurfaceIndex? = null,
|
|
||||||
override val tag: String? = null,
|
|
||||||
override val diedCause: EntityIdentifiers? = null,
|
|
||||||
|
|
||||||
override val bannedReason: String? = null,
|
val afkTime: Tick? = null,
|
||||||
override val kickedReason: String? = null,
|
val ticksToRespawn: Tick? = null,
|
||||||
override val disconnectReason: String? = null,
|
val forceIndex: ForceIndex? = null,
|
||||||
|
val isAdmin: Boolean? = null,
|
||||||
|
val isConnected: Boolean? = null,
|
||||||
|
val isShowOnMap: Boolean? = null,
|
||||||
|
val isSpectator: Boolean? = null,
|
||||||
|
val lastOnline: Tick? = null,
|
||||||
|
val onlineTime: Tick? = null,
|
||||||
|
val position: MapEntityPosition? = null,
|
||||||
|
val surfaceIndex: SurfaceIndex? = null,
|
||||||
|
val tag: String? = null,
|
||||||
|
val diedCause: EntityIdentifiers? = null,
|
||||||
|
|
||||||
|
val bannedReason: String? = null,
|
||||||
|
val kickedReason: String? = null,
|
||||||
|
val disconnectReason: String? = null,
|
||||||
/** `true` when a player is removed (deleted) from the game */
|
/** `true` when a player is removed (deleted) from the game */
|
||||||
override val isRemoved: Boolean? = null,
|
val isRemoved: Boolean? = null,
|
||||||
) : FactorioEventUpdate(), PlayerUpdateKey, PlayerUpdateData {
|
) : FactorioEventUpdate(), PlayerUpdateKey {
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
override val updateType: FactorioEventUpdateType = FactorioEventUpdateType.PLAYER
|
override val updateType: FactorioEventUpdateType = FactorioEventUpdateType.PLAYER
|
||||||
}
|
}
|
||||||
|
|
@ -165,17 +172,17 @@ sealed interface EntityUpdateKey : EntityIdentifiers, FactorioEventUpdateKey {
|
||||||
override val type: String
|
override val type: String
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface EntityUpdateData : FactorioEventUpdateData {
|
//sealed interface EntityUpdateData : FactorioEventUpdateData {
|
||||||
val chunkPosition: MapChunkPosition?
|
// val chunkPosition: MapChunkPosition?
|
||||||
val graphicsVariation: UShort?
|
// val graphicsVariation: UShort?
|
||||||
val health: Float?
|
// val health: Float?
|
||||||
val isActive: Boolean?
|
// val isActive: Boolean?
|
||||||
val isRotatable: Boolean?
|
// val isRotatable: Boolean?
|
||||||
val lastUser: UInt?
|
// val lastUser: UInt?
|
||||||
val localisedDescription: String?
|
// val localisedDescription: String?
|
||||||
val localisedName: String?
|
// val localisedName: String?
|
||||||
val prototype: PrototypeName?
|
// val prototype: PrototypeName?
|
||||||
}
|
//}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class EntityUpdate(
|
data class EntityUpdate(
|
||||||
|
|
@ -183,16 +190,19 @@ data class EntityUpdate(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val type: String,
|
override val type: String,
|
||||||
|
|
||||||
override val chunkPosition: MapChunkPosition? = null,
|
@Contextual
|
||||||
override val graphicsVariation: UShort? = null,
|
override val events: List<String>? = null,
|
||||||
override val health: Float? = null,
|
|
||||||
override val isActive: Boolean? = null,
|
val chunkPosition: MapChunkPosition? = null,
|
||||||
override val isRotatable: Boolean? = null,
|
val graphicsVariation: UShort? = null,
|
||||||
override val lastUser: UInt? = null,
|
val health: Float? = null,
|
||||||
override val localisedDescription: String? = null,
|
val isActive: Boolean? = null,
|
||||||
override val localisedName: String? = null,
|
val isRotatable: Boolean? = null,
|
||||||
override val prototype: PrototypeName? = null,
|
val lastUser: UInt? = null,
|
||||||
) : FactorioEventUpdate(), EntityIdentifiers, EntityUpdateKey, EntityUpdateData {
|
val localisedDescription: String? = null,
|
||||||
|
val localisedName: String? = null,
|
||||||
|
val prototype: PrototypeName? = null,
|
||||||
|
) : FactorioEventUpdate(), EntityIdentifiers, EntityUpdateKey {
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
override val updateType: FactorioEventUpdateType = FactorioEventUpdateType.ENTITY
|
override val updateType: FactorioEventUpdateType = FactorioEventUpdateType.ENTITY
|
||||||
}
|
}
|
||||||
|
|
@ -207,14 +217,13 @@ sealed interface MapChunkUpdateKey : FactorioEventUpdateKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sealed interface MapChunkUpdateData : FactorioEventUpdateData {
|
//sealed interface MapChunkUpdateData : FactorioEventUpdateData {
|
||||||
val player: PlayerIndex?
|
// val player: PlayerIndex?
|
||||||
val robot: EntityIdentifiers?
|
// val robot: EntityIdentifiers?
|
||||||
val force: ForceIndex?
|
// val force: ForceIndex?
|
||||||
/** updated tiles - might be partial */
|
// val tiles: List<MapTile>?
|
||||||
val tiles: List<MapTile>?
|
// val isDeleted: Boolean?
|
||||||
val isDeleted: Boolean?
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|
@ -222,14 +231,19 @@ data class MapChunkUpdate(
|
||||||
override val chunkPosition: MapChunkPosition,
|
override val chunkPosition: MapChunkPosition,
|
||||||
override val surfaceIndex: SurfaceIndex,
|
override val surfaceIndex: SurfaceIndex,
|
||||||
|
|
||||||
override val player: PlayerIndex? = null,
|
@Contextual
|
||||||
override val robot: EntityIdentifiers? = null,
|
override val events: List<String>? = null,
|
||||||
override val force: ForceIndex? = null,
|
|
||||||
|
val player: PlayerIndex? = null,
|
||||||
|
val robot: EntityIdentifiers? = null,
|
||||||
|
val force: ForceIndex? = null,
|
||||||
|
/** updated tiles - might be partial */
|
||||||
// note: this must be a List, not a Map<Location, ProtoName>
|
// note: this must be a List, not a Map<Location, ProtoName>
|
||||||
// because JSON can't have non-string keys.
|
// because JSON can't have non-string keys.
|
||||||
override val tiles: List<MapTile>? = null,
|
@Contextual
|
||||||
override val isDeleted: Boolean? = null,
|
val tiles: List<MapTile>? = null,
|
||||||
) : FactorioEventUpdate(), MapChunkUpdateKey, MapChunkUpdateData {
|
val isDeleted: Boolean? = null,
|
||||||
|
) : FactorioEventUpdate(), MapChunkUpdateKey {
|
||||||
@EncodeDefault
|
@EncodeDefault
|
||||||
override val updateType: FactorioEventUpdateType = FactorioEventUpdateType.MAP_CHUNK
|
override val updateType: FactorioEventUpdateType = FactorioEventUpdateType.MAP_CHUNK
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ fun main(args: Array<String>) {
|
||||||
add(FactorioEventUpdatePacket::class)
|
add(FactorioEventUpdatePacket::class)
|
||||||
addAll(FactorioEventUpdate::class.sealedSubclasses)
|
addAll(FactorioEventUpdate::class.sealedSubclasses)
|
||||||
addAll(FactorioEventUpdateKey::class.sealedSubclasses)
|
addAll(FactorioEventUpdateKey::class.sealedSubclasses)
|
||||||
addAll(FactorioEventUpdateData::class.sealedSubclasses)
|
// addAll(FactorioEventUpdateData::class.sealedSubclasses)
|
||||||
|
|
||||||
},
|
},
|
||||||
mappings = mapOf(
|
mappings = mapOf(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue