From 80eb001bbf9ec632aa9d6b126a51a6a6774eb2ea Mon Sep 17 00:00:00 2001 From: Adam <897017+aSemy@users.noreply.github.com> Date: Fri, 8 Jul 2022 21:06:09 +0200 Subject: [PATCH] emit entity prototypes - mod: refactor event handlers to separate files - lib: update models for prototypes --- .../schema/common/factorioPrototypes.kt | 35 +- .../lua/main/events/configurationUpdate.lua | 58 +--- .../generated/lua/main/events/converters.lua | 29 ++ .../lua/main/events/entityUpdates.lua | 175 +--------- .../handlers/ConfigurationUpdateHandler.lua | 62 ++++ .../events/handlers/EntityUpdateHandler.lua | 175 ++++++++++ .../events/handlers/MapChunkUpdateHandler.lua | 208 ++++++++++++ .../events/handlers/PlayerUpdateHandler.lua | 60 ++++ .../lua/main/events/mapChunkUpdates.lua | 213 +------------ .../lua/main/events/playerUpdates.lua | 107 ++----- .../lua/main/events/prototypeUpdates.lua | 76 ++++- .../main/events/registerEventListeners.lua | 4 +- .../lua/main/events/resourceEntityUpdates.lua | 0 .../typescript/generated/kafkatorio-schema.ts | 20 +- .../main/events/configurationUpdate.ts | 57 +--- .../main/typescript/main/events/converters.ts | 43 +++ .../typescript/main/events/entityUpdates.ts | 254 +-------------- .../handlers/ConfigurationUpdateHandler.ts | 62 ++++ .../events/handlers/EntityUpdateHandler.ts | 250 +++++++++++++++ .../events/handlers/MapChunkUpdateHandler.ts | 242 ++++++++++++++ .../events/handlers/PlayerUpdateHandler.ts | 75 +++++ .../typescript/main/events/mapChunkUpdates.ts | 257 +-------------- .../typescript/main/events/playerUpdates.ts | 300 +++++++----------- .../main/events/prototypeUpdates.ts | 129 +++++--- .../main/events/registerEventListeners.ts | 2 +- .../main/events/resourceEntityUpdates.ts | 99 ------ .../processor/topology/colourMapChunks.kt | 15 +- 27 files changed, 1570 insertions(+), 1437 deletions(-) create mode 100644 modules/events-mod/src/generated/lua/main/events/handlers/ConfigurationUpdateHandler.lua create mode 100644 modules/events-mod/src/generated/lua/main/events/handlers/EntityUpdateHandler.lua create mode 100644 modules/events-mod/src/generated/lua/main/events/handlers/MapChunkUpdateHandler.lua create mode 100644 modules/events-mod/src/generated/lua/main/events/handlers/PlayerUpdateHandler.lua delete mode 100644 modules/events-mod/src/generated/lua/main/events/resourceEntityUpdates.lua create mode 100644 modules/events-mod/src/main/typescript/main/events/handlers/ConfigurationUpdateHandler.ts create mode 100644 modules/events-mod/src/main/typescript/main/events/handlers/EntityUpdateHandler.ts create mode 100644 modules/events-mod/src/main/typescript/main/events/handlers/MapChunkUpdateHandler.ts create mode 100644 modules/events-mod/src/main/typescript/main/events/handlers/PlayerUpdateHandler.ts delete mode 100644 modules/events-mod/src/main/typescript/main/events/resourceEntityUpdates.ts diff --git a/modules/events-library/src/commonMain/kotlin/dev/adamko/kafkatorio/schema/common/factorioPrototypes.kt b/modules/events-library/src/commonMain/kotlin/dev/adamko/kafkatorio/schema/common/factorioPrototypes.kt index 393ad8a..ec752b1 100644 --- a/modules/events-library/src/commonMain/kotlin/dev/adamko/kafkatorio/schema/common/factorioPrototypes.kt +++ b/modules/events-library/src/commonMain/kotlin/dev/adamko/kafkatorio/schema/common/factorioPrototypes.kt @@ -8,15 +8,16 @@ import kotlinx.serialization.Serializable @Serializable @SerialName("kafkatorio.prototype.FactorioPrototype") sealed interface FactorioPrototype { + val protoId: PrototypeId - val mapColour: Colour @SerialName("kafkatorio.prototype.MapTile") @Serializable data class MapTile( override val protoId: PrototypeId, - override val mapColour: Colour, + + val mapColour: Colour, val layer: UInt, @Contextual @@ -27,27 +28,47 @@ sealed interface FactorioPrototype { ) : FactorioPrototype + /** + * @param[colour] The colour of the prototype, or `null` if the prototype doesn't have colour. + * @param[mapColour] The map colour used when charting this entity if a + * [friendly][mapColourFriend] or [enemy][mapColourEnemy] colour isn't defined or `null`. + * @param[mapColourFriend] The friendly map colour used when charting this entity. + * @param[mapColourEnemy] The enemy map colour used when charting this entity. + */ @SerialName("kafkatorio.prototype.Entity") @Serializable data class Entity( override val protoId: PrototypeId, - override val mapColour: Colour, - val protoType: String, - val objectName: String, - val colour: Colour, + val group: ItemGroup, + val subgroup: ItemGroup, + + val colour: Colour? = null, + val mapColour: Colour? = null, + val mapColourFriend: Colour? = null, + val mapColourEnemy: Colour? = null, + val maxHealth: Float, val isBuilding: Boolean, val isEntityWithOwner: Boolean, val isMilitaryTarget: Boolean, - val miningProperties: MiningProperties + val miningProperties: MiningProperties? = null, ) : FactorioPrototype { @Serializable + @SerialName("kafkatorio.prototype.EntityMiningProperties") data class MiningProperties( val canBeMined: Boolean, val products: List?, ) + @Serializable + @SerialName("kafkatorio.prototype.EntityItemGroup") + data class ItemGroup( + val name: String, + val type: String, + val parentName: String? = null, + ) + } } diff --git a/modules/events-mod/src/generated/lua/main/events/configurationUpdate.lua b/modules/events-mod/src/generated/lua/main/events/configurationUpdate.lua index 1e49bb7..6560c95 100644 --- a/modules/events-mod/src/generated/lua/main/events/configurationUpdate.lua +++ b/modules/events-mod/src/generated/lua/main/events/configurationUpdate.lua @@ -1,65 +1,13 @@ -local ____lualib = require("lualib_bundle") -local __TS__ObjectKeys = ____lualib.__TS__ObjectKeys -local __TS__ArrayConcat = ____lualib.__TS__ArrayConcat -local Set = ____lualib.Set -local __TS__New = ____lualib.__TS__New -local __TS__Spread = ____lualib.__TS__Spread -local __TS__ArrayMap = ____lualib.__TS__ArrayMap local ____exports = {} -local emitConfigurationUpdate, factorioData, allMods, Type -local ____PacketEmitter = require("main.PacketEmitter") -local PacketEmitter = ____PacketEmitter.default -local ____kafkatorio_2Dschema = require("generated.kafkatorio-schema") -local KafkatorioPacketData = ____kafkatorio_2Dschema.KafkatorioPacketData local ____global_2Dinit = require("main.global-init") local initGlobal = ____global_2Dinit.initGlobal local ____prototypeUpdates = require("main.events.prototypeUpdates") local emitPrototypes = ____prototypeUpdates.emitPrototypes -function emitConfigurationUpdate(changeData) - local configUpdateData = { - type = Type.ConfigurationUpdate, - migrationApplied = changeData.migration_applied, - modStartupSettingsChange = changeData.mod_startup_settings_changed, - allMods = allMods(changeData), - factorioData = factorioData(changeData) - } - PacketEmitter:emitInstantPacket(configUpdateData) -end -function factorioData(changeData) - return {oldVersion = changeData.old_version or nil, newVersion = changeData.new_version or nil} -end -function allMods(e) - local namesOfChangedMods = __TS__ObjectKeys(e.mod_changes) - local namesOfCurrentMods = __TS__ObjectKeys(script.active_mods) - local modNames = {__TS__Spread(__TS__New( - Set, - __TS__ArrayConcat(namesOfChangedMods, namesOfCurrentMods) - ))} - return __TS__ArrayMap( - modNames, - function(____, modName) - local ____script_active_mods_modName_2 = script.active_mods[modName] - if ____script_active_mods_modName_2 == nil then - local ____e_mod_changes_modName_new_version_0 = e.mod_changes[modName] - if ____e_mod_changes_modName_new_version_0 ~= nil then - ____e_mod_changes_modName_new_version_0 = ____e_mod_changes_modName_new_version_0.new_version - end - ____script_active_mods_modName_2 = ____e_mod_changes_modName_new_version_0 - end - local currentVer = ____script_active_mods_modName_2 or nil - local ____e_mod_changes_modName_old_version_3 = e.mod_changes[modName] - if ____e_mod_changes_modName_old_version_3 ~= nil then - ____e_mod_changes_modName_old_version_3 = ____e_mod_changes_modName_old_version_3.old_version - end - local previousVer = ____e_mod_changes_modName_old_version_3 or nil - return {modName = modName, currentVersion = currentVer, previousVersion = previousVer} - end - ) -end -Type = KafkatorioPacketData.Type +local ____ConfigurationUpdateHandler = require("main.events.handlers.ConfigurationUpdateHandler") +local ConfigurationUpdates = ____ConfigurationUpdateHandler.default script.on_configuration_changed(function(data) initGlobal(true) - emitConfigurationUpdate(data) + ConfigurationUpdates:emitConfigurationUpdate(data) emitPrototypes() end) return ____exports diff --git a/modules/events-mod/src/generated/lua/main/events/converters.lua b/modules/events-mod/src/generated/lua/main/events/converters.lua index 2131d67..8020aaa 100644 --- a/modules/events-mod/src/generated/lua/main/events/converters.lua +++ b/modules/events-mod/src/generated/lua/main/events/converters.lua @@ -2,6 +2,7 @@ local ____exports = {} local ____kafkatorio_2Dschema = require("generated.kafkatorio-schema") local EntityStatus = ____kafkatorio_2Dschema.EntityStatus local FactorioEntityData = ____kafkatorio_2Dschema.FactorioEntityData +local MinedProduct = ____kafkatorio_2Dschema.MinedProduct ____exports.Converters = {} local Converters = ____exports.Converters do @@ -87,6 +88,34 @@ do return EntityStatusRecord[status] end end + function Converters.miningProperties(properties) + local products = {} + if properties.products ~= nil then + for ____, product in ipairs(properties.products) do + if product.type == "fluid" then + products[#products + 1] = { + type = MinedProduct.Type.MinedProductFluid, + amount = product.amount, + resultProtoId = ____exports.Converters.prototypeId(product.type, product.name) + } + end + if product.type == "item" then + products[#products + 1] = { + type = MinedProduct.Type.MinedProductItem, + amount = product.amount, + resultProtoId = ____exports.Converters.prototypeId(product.type, product.name) + } + end + end + end + return {canBeMined = properties.minable, products = products} + end + function Converters.playerOnlineInfo(player, data) + data.lastOnline = player.last_online + data.onlineTime = player.online_time + data.afkTime = player.afk_time + data.isConnected = player.connected + end EntityStatusRecord = { [defines.entity_status.cant_divide_segments] = EntityStatus.CANT_DIVIDE_SEGMENTS, [defines.entity_status.charging] = EntityStatus.CHARGING, diff --git a/modules/events-mod/src/generated/lua/main/events/entityUpdates.lua b/modules/events-mod/src/generated/lua/main/events/entityUpdates.lua index 86eb956..6f4d323 100644 --- a/modules/events-mod/src/generated/lua/main/events/entityUpdates.lua +++ b/modules/events-mod/src/generated/lua/main/events/entityUpdates.lua @@ -1,177 +1,6 @@ -local ____lualib = require("lualib_bundle") -local __TS__Class = ____lualib.__TS__Class -local __TS__New = ____lualib.__TS__New local ____exports = {} -local ____converters = require("main.events.converters") -local Converters = ____converters.Converters -local ____EventDataCache = require("main.cache.EventDataCache") -local EventDataCache = ____EventDataCache.default -local ____kafkatorio_2Dschema = require("generated.kafkatorio-schema") -local FactorioEntityData = ____kafkatorio_2Dschema.FactorioEntityData -local KafkatorioPacketData = ____kafkatorio_2Dschema.KafkatorioPacketData -____exports.EntityUpdatesHandler = __TS__Class() -local EntityUpdatesHandler = ____exports.EntityUpdatesHandler -EntityUpdatesHandler.name = "EntityUpdatesHandler" -function EntityUpdatesHandler.prototype.____constructor(self) -end -function EntityUpdatesHandler.prototype.handleMinedTileEvent(self, event) - local surface = game.get_surface(event.surface_index) - if surface == nil then - return - end - local tilesByChunk = {} - for ____, tile in ipairs(event.tiles) do - local chunkPosition = Converters.tilePositionToChunkPosition(tile.position) - tilesByChunk[chunkPosition] = tile - end - for chunkPos, tiles in pairs(tilesByChunk) do - local entities = {} - for tile in pairs(tiles) do - local resources = ____exports.EntityUpdatesHandler:getTileResourceEntities(surface, chunkPos) - for ____, resource in ipairs(resources) do - entities[#entities + 1] = resource - end - end - ____exports.EntityUpdatesHandler:throttleResourceEntitiesUpdate( - Converters.eventNameString(event.name), - event.tick, - event.surface_index, - {chunkPos[1], chunkPos[2]}, - entities - ) - end -end -function EntityUpdatesHandler.prototype.handleMinedEntityEvent(self, event) - ____exports.EntityUpdatesHandler:throttleEntityUpdate(event, event.entity) -end -function EntityUpdatesHandler.prototype.handleBuiltEntityEvent(self, event) - ____exports.EntityUpdatesHandler:throttleEntityUpdate(event, event.created_entity) -end -function EntityUpdatesHandler.prototype.handleChunkGeneratedEvent(self, event) - local entities = ____exports.EntityUpdatesHandler:getAreaResourceEntities(event.surface, event.area) - ____exports.EntityUpdatesHandler:throttleResourceEntitiesUpdate( - Converters.eventNameString(event.name), - event.tick, - event.surface.index, - {event.position.x, event.position.y}, - entities - ) -end -function EntityUpdatesHandler.throttleEntityUpdate(self, event, entity) - if entity.unit_number == nil then - return - end - local eventName = Converters.eventNameString(event.name) - local entityUpdateKey = { - protoId = Converters.prototypeIdEntity(entity), - surfaceIndex = entity.surface.index, - chunkPosition = Converters.mapPositionToChunkPosition(entity.position) - } - local ____FactorioEntityData_Type_Standard_2 = FactorioEntityData.Type.Standard - local ____Converters_prototypeIdEntity_result_3 = Converters.prototypeIdEntity(entity) - local ____entity_graphics_variation_4 = entity.graphics_variation - local ____entity_health_5 = entity.health - local ____entity_active_6 = entity.active - local ____entity_rotatable_7 = entity.rotatable - local ____entity_last_user_index_0 = entity.last_user - if ____entity_last_user_index_0 ~= nil then - ____entity_last_user_index_0 = ____entity_last_user_index_0.index - end - local entityUpdate = { - type = ____FactorioEntityData_Type_Standard_2, - protoId = ____Converters_prototypeIdEntity_result_3, - graphicsVariation = ____entity_graphics_variation_4, - health = ____entity_health_5, - isActive = ____entity_active_6, - isRotatable = ____entity_rotatable_7, - lastUser = ____entity_last_user_index_0, - localisedDescription = nil, - localisedName = nil, - position = {entity.position.x, entity.position.y}, - status = Converters.entityStatus(entity.status) - } - local entityKey = tostring(entity.unit_number) - EventDataCache:throttle( - entityUpdateKey, - KafkatorioPacketData.Type.MapChunkEntityUpdate, - function(data) - if data.events == nil then - data.events = {} - end - local ____data_events_8, ____eventName_9 = data.events, eventName - if ____data_events_8[____eventName_9] == nil then - ____data_events_8[____eventName_9] = {} - end - local ____data_events_eventName_10 = data.events[eventName] - ____data_events_eventName_10[#____data_events_eventName_10 + 1] = event.tick - if data.distinctEntities == nil then - data.distinctEntities = {} - end - data.distinctEntities[entityKey] = entityUpdate - end - ) -end -function EntityUpdatesHandler.throttleResourceEntitiesUpdate(self, eventName, eventTick, surfaceIndex, chunkPosition, entities) - local entitiesByProtoId = {} - for ____, entity in ipairs(entities) do - local ____entitiesByProtoId_11, ____entity_protoId_12 = entitiesByProtoId, entity.protoId - if ____entitiesByProtoId_11[____entity_protoId_12] == nil then - ____entitiesByProtoId_11[____entity_protoId_12] = {} - end - local ____entitiesByProtoId_entity_protoId_13 = entitiesByProtoId[entity.protoId] - ____entitiesByProtoId_entity_protoId_13[#____entitiesByProtoId_entity_protoId_13 + 1] = entity - end - for protoId, resourceEntities in pairs(entitiesByProtoId) do - local entityUpdateKey = {protoId = protoId, surfaceIndex = surfaceIndex, chunkPosition = {chunkPosition[1], chunkPosition[2]}} - EventDataCache:throttle( - entityUpdateKey, - KafkatorioPacketData.Type.MapChunkEntityUpdate, - function(data) - if data.events == nil then - data.events = {} - end - local ____data_events_14, ____eventName_15 = data.events, eventName - if ____data_events_14[____eventName_15] == nil then - ____data_events_14[____eventName_15] = {} - end - local ____data_events_eventName_16 = data.events[eventName] - ____data_events_eventName_16[#____data_events_eventName_16 + 1] = eventTick - for ____, entity in ipairs(resourceEntities) do - local x, y = table.unpack(entity.position) - local entityKey = (tostring(x) .. ",") .. tostring(y) - if data.distinctEntities == nil then - data.distinctEntities = {} - end - data.distinctEntities[entityKey] = entity - end - end - ) - end -end -function EntityUpdatesHandler.getTileResourceEntities(self, surface, mapPosition) - local rawEntities = surface.find_entities_filtered({position = mapPosition, collision_mask = "resource-layer"}) - local resources = {} - for ____, rawEntity in ipairs(rawEntities) do - local entity = Converters.convertResourceEntity(rawEntity) - if entity ~= nil then - resources[#resources + 1] = entity - end - end - return resources -end -function EntityUpdatesHandler.getAreaResourceEntities(self, surface, area) - local rawEntities = surface.find_entities_filtered({area = area, collision_mask = "resource-layer"}) - local resources = {} - for ____, rawEntity in ipairs(rawEntities) do - local entity = Converters.convertResourceEntity(rawEntity) - if entity ~= nil then - resources[#resources + 1] = entity - end - end - return resources -end -local EntityUpdates = __TS__New(____exports.EntityUpdatesHandler) -____exports.default = EntityUpdates +local ____EntityUpdateHandler = require("main.events.handlers.EntityUpdateHandler") +local EntityUpdates = ____EntityUpdateHandler.default script.on_event( defines.events.on_built_entity, function(e) diff --git a/modules/events-mod/src/generated/lua/main/events/handlers/ConfigurationUpdateHandler.lua b/modules/events-mod/src/generated/lua/main/events/handlers/ConfigurationUpdateHandler.lua new file mode 100644 index 0000000..b81701c --- /dev/null +++ b/modules/events-mod/src/generated/lua/main/events/handlers/ConfigurationUpdateHandler.lua @@ -0,0 +1,62 @@ +local ____lualib = require("lualib_bundle") +local __TS__Class = ____lualib.__TS__Class +local __TS__ObjectKeys = ____lualib.__TS__ObjectKeys +local __TS__ArrayConcat = ____lualib.__TS__ArrayConcat +local Set = ____lualib.Set +local __TS__New = ____lualib.__TS__New +local __TS__Spread = ____lualib.__TS__Spread +local __TS__ArrayMap = ____lualib.__TS__ArrayMap +local ____exports = {} +local ____kafkatorio_2Dschema = require("generated.kafkatorio-schema") +local KafkatorioPacketData = ____kafkatorio_2Dschema.KafkatorioPacketData +local ____PacketEmitter = require("main.PacketEmitter") +local PacketEmitter = ____PacketEmitter.default +____exports.ConfigurationUpdateHandler = __TS__Class() +local ConfigurationUpdateHandler = ____exports.ConfigurationUpdateHandler +ConfigurationUpdateHandler.name = "ConfigurationUpdateHandler" +function ConfigurationUpdateHandler.prototype.____constructor(self) +end +function ConfigurationUpdateHandler.prototype.emitConfigurationUpdate(self, changeData) + local configUpdateData = { + type = KafkatorioPacketData.Type.ConfigurationUpdate, + migrationApplied = changeData.migration_applied, + modStartupSettingsChange = changeData.mod_startup_settings_changed, + allMods = ____exports.ConfigurationUpdateHandler:allMods(changeData), + factorioData = ____exports.ConfigurationUpdateHandler:factorioData(changeData) + } + PacketEmitter:emitInstantPacket(configUpdateData) +end +function ConfigurationUpdateHandler.factorioData(self, changeData) + return {oldVersion = changeData.old_version or nil, newVersion = changeData.new_version or nil} +end +function ConfigurationUpdateHandler.allMods(self, e) + local namesOfChangedMods = __TS__ObjectKeys(e.mod_changes) + local namesOfCurrentMods = __TS__ObjectKeys(script.active_mods) + local modNames = {__TS__Spread(__TS__New( + Set, + __TS__ArrayConcat(namesOfChangedMods, namesOfCurrentMods) + ))} + return __TS__ArrayMap( + modNames, + function(____, modName) + local ____script_active_mods_modName_2 = script.active_mods[modName] + if ____script_active_mods_modName_2 == nil then + local ____e_mod_changes_modName_new_version_0 = e.mod_changes[modName] + if ____e_mod_changes_modName_new_version_0 ~= nil then + ____e_mod_changes_modName_new_version_0 = ____e_mod_changes_modName_new_version_0.new_version + end + ____script_active_mods_modName_2 = ____e_mod_changes_modName_new_version_0 + end + local currentVer = ____script_active_mods_modName_2 or nil + local ____e_mod_changes_modName_old_version_3 = e.mod_changes[modName] + if ____e_mod_changes_modName_old_version_3 ~= nil then + ____e_mod_changes_modName_old_version_3 = ____e_mod_changes_modName_old_version_3.old_version + end + local previousVer = ____e_mod_changes_modName_old_version_3 or nil + return {modName = modName, currentVersion = currentVer, previousVersion = previousVer} + end + ) +end +local ConfigurationUpdates = __TS__New(____exports.ConfigurationUpdateHandler) +____exports.default = ConfigurationUpdates +return ____exports diff --git a/modules/events-mod/src/generated/lua/main/events/handlers/EntityUpdateHandler.lua b/modules/events-mod/src/generated/lua/main/events/handlers/EntityUpdateHandler.lua new file mode 100644 index 0000000..99afb01 --- /dev/null +++ b/modules/events-mod/src/generated/lua/main/events/handlers/EntityUpdateHandler.lua @@ -0,0 +1,175 @@ +local ____lualib = require("lualib_bundle") +local __TS__Class = ____lualib.__TS__Class +local __TS__New = ____lualib.__TS__New +local ____exports = {} +local ____kafkatorio_2Dschema = require("generated.kafkatorio-schema") +local FactorioEntityData = ____kafkatorio_2Dschema.FactorioEntityData +local KafkatorioPacketData = ____kafkatorio_2Dschema.KafkatorioPacketData +local ____converters = require("main.events.converters") +local Converters = ____converters.Converters +local ____EventDataCache = require("main.cache.EventDataCache") +local EventDataCache = ____EventDataCache.default +____exports.EntityUpdatesHandler = __TS__Class() +local EntityUpdatesHandler = ____exports.EntityUpdatesHandler +EntityUpdatesHandler.name = "EntityUpdatesHandler" +function EntityUpdatesHandler.prototype.____constructor(self) +end +function EntityUpdatesHandler.prototype.handleMinedTileEvent(self, event) + local surface = game.get_surface(event.surface_index) + if surface == nil then + return + end + local tilesByChunk = {} + for ____, tile in ipairs(event.tiles) do + local chunkPosition = Converters.tilePositionToChunkPosition(tile.position) + tilesByChunk[chunkPosition] = tile + end + for chunkPos, tiles in pairs(tilesByChunk) do + local entities = {} + for tile in pairs(tiles) do + local resources = ____exports.EntityUpdatesHandler:getTileResourceEntities(surface, chunkPos) + for ____, resource in ipairs(resources) do + entities[#entities + 1] = resource + end + end + ____exports.EntityUpdatesHandler:throttleResourceEntitiesUpdate( + Converters.eventNameString(event.name), + event.tick, + event.surface_index, + {chunkPos[1], chunkPos[2]}, + entities + ) + end +end +function EntityUpdatesHandler.prototype.handleMinedEntityEvent(self, event) + ____exports.EntityUpdatesHandler:throttleEntityUpdate(event, event.entity) +end +function EntityUpdatesHandler.prototype.handleBuiltEntityEvent(self, event) + ____exports.EntityUpdatesHandler:throttleEntityUpdate(event, event.created_entity) +end +function EntityUpdatesHandler.prototype.handleChunkGeneratedEvent(self, event) + local entities = ____exports.EntityUpdatesHandler:getAreaResourceEntities(event.surface, event.area) + ____exports.EntityUpdatesHandler:throttleResourceEntitiesUpdate( + Converters.eventNameString(event.name), + event.tick, + event.surface.index, + {event.position.x, event.position.y}, + entities + ) +end +function EntityUpdatesHandler.throttleEntityUpdate(self, event, entity) + if entity.unit_number == nil then + return + end + local eventName = Converters.eventNameString(event.name) + local entityUpdateKey = { + protoId = Converters.prototypeIdEntity(entity), + surfaceIndex = entity.surface.index, + chunkPosition = Converters.mapPositionToChunkPosition(entity.position) + } + local ____FactorioEntityData_Type_Standard_2 = FactorioEntityData.Type.Standard + local ____Converters_prototypeIdEntity_result_3 = Converters.prototypeIdEntity(entity) + local ____entity_graphics_variation_4 = entity.graphics_variation + local ____entity_health_5 = entity.health + local ____entity_active_6 = entity.active + local ____entity_rotatable_7 = entity.rotatable + local ____entity_last_user_index_0 = entity.last_user + if ____entity_last_user_index_0 ~= nil then + ____entity_last_user_index_0 = ____entity_last_user_index_0.index + end + local entityUpdate = { + type = ____FactorioEntityData_Type_Standard_2, + protoId = ____Converters_prototypeIdEntity_result_3, + graphicsVariation = ____entity_graphics_variation_4, + health = ____entity_health_5, + isActive = ____entity_active_6, + isRotatable = ____entity_rotatable_7, + lastUser = ____entity_last_user_index_0, + localisedDescription = nil, + localisedName = nil, + position = {entity.position.x, entity.position.y}, + status = Converters.entityStatus(entity.status) + } + local entityKey = tostring(entity.unit_number) + EventDataCache:throttle( + entityUpdateKey, + KafkatorioPacketData.Type.MapChunkEntityUpdate, + function(data) + if data.events == nil then + data.events = {} + end + local ____data_events_8, ____eventName_9 = data.events, eventName + if ____data_events_8[____eventName_9] == nil then + ____data_events_8[____eventName_9] = {} + end + local ____data_events_eventName_10 = data.events[eventName] + ____data_events_eventName_10[#____data_events_eventName_10 + 1] = event.tick + if data.distinctEntities == nil then + data.distinctEntities = {} + end + data.distinctEntities[entityKey] = entityUpdate + end + ) +end +function EntityUpdatesHandler.throttleResourceEntitiesUpdate(self, eventName, eventTick, surfaceIndex, chunkPosition, entities) + local entitiesByProtoId = {} + for ____, entity in ipairs(entities) do + local ____entitiesByProtoId_11, ____entity_protoId_12 = entitiesByProtoId, entity.protoId + if ____entitiesByProtoId_11[____entity_protoId_12] == nil then + ____entitiesByProtoId_11[____entity_protoId_12] = {} + end + local ____entitiesByProtoId_entity_protoId_13 = entitiesByProtoId[entity.protoId] + ____entitiesByProtoId_entity_protoId_13[#____entitiesByProtoId_entity_protoId_13 + 1] = entity + end + for protoId, resourceEntities in pairs(entitiesByProtoId) do + local entityUpdateKey = {protoId = protoId, surfaceIndex = surfaceIndex, chunkPosition = {chunkPosition[1], chunkPosition[2]}} + EventDataCache:throttle( + entityUpdateKey, + KafkatorioPacketData.Type.MapChunkEntityUpdate, + function(data) + if data.events == nil then + data.events = {} + end + local ____data_events_14, ____eventName_15 = data.events, eventName + if ____data_events_14[____eventName_15] == nil then + ____data_events_14[____eventName_15] = {} + end + local ____data_events_eventName_16 = data.events[eventName] + ____data_events_eventName_16[#____data_events_eventName_16 + 1] = eventTick + for ____, entity in ipairs(resourceEntities) do + local x, y = table.unpack(entity.position) + local entityKey = (tostring(x) .. ",") .. tostring(y) + if data.distinctEntities == nil then + data.distinctEntities = {} + end + data.distinctEntities[entityKey] = entity + end + end + ) + end +end +function EntityUpdatesHandler.getTileResourceEntities(self, surface, mapPosition) + local rawEntities = surface.find_entities_filtered({position = mapPosition, collision_mask = "resource-layer"}) + local resources = {} + for ____, rawEntity in ipairs(rawEntities) do + local entity = Converters.convertResourceEntity(rawEntity) + if entity ~= nil then + resources[#resources + 1] = entity + end + end + return resources +end +function EntityUpdatesHandler.getAreaResourceEntities(self, surface, area) + local rawEntities = surface.find_entities_filtered({area = area, collision_mask = "resource-layer"}) + local resources = {} + for ____, rawEntity in ipairs(rawEntities) do + local entity = Converters.convertResourceEntity(rawEntity) + if entity ~= nil then + resources[#resources + 1] = entity + end + end + return resources +end +local EntityUpdates = __TS__New(____exports.EntityUpdatesHandler) +____exports.default = EntityUpdates +return ____exports diff --git a/modules/events-mod/src/generated/lua/main/events/handlers/MapChunkUpdateHandler.lua b/modules/events-mod/src/generated/lua/main/events/handlers/MapChunkUpdateHandler.lua new file mode 100644 index 0000000..f047ad7 --- /dev/null +++ b/modules/events-mod/src/generated/lua/main/events/handlers/MapChunkUpdateHandler.lua @@ -0,0 +1,208 @@ +local ____lualib = require("lualib_bundle") +local __TS__Class = ____lualib.__TS__Class +local Map = ____lualib.Map +local __TS__Iterator = ____lualib.__TS__Iterator +local __TS__New = ____lualib.__TS__New +local ____exports = {} +local ____converters = require("main.events.converters") +local Converters = ____converters.Converters +local ____eventTypeCheck = require("main.events.eventTypeCheck") +local isEventType = ____eventTypeCheck.isEventType +local ____kafkatorio_2Dschema = require("generated.kafkatorio-schema") +local KafkatorioPacketData = ____kafkatorio_2Dschema.KafkatorioPacketData +local ____EventDataCache = require("main.cache.EventDataCache") +local EventUpdatesManager = ____EventDataCache.default +local MapChunkUpdateHandler = __TS__Class() +MapChunkUpdateHandler.name = "MapChunkUpdateHandler" +function MapChunkUpdateHandler.prototype.____constructor(self) +end +function MapChunkUpdateHandler.prototype.handleChunkGeneratedEvent(self, event, expirationDurationTicks) + local tiles = event.surface.find_tiles_filtered({area = event.area}) + MapChunkUpdateHandler:mapTilesUpdateDebounce( + event.surface, + Converters.convertMapTablePosition(event.position), + tiles, + event, + nil, + expirationDurationTicks + ) +end +function MapChunkUpdateHandler.prototype.handleBuiltTileEvent(self, event) + local surface = game.get_surface(event.surface_index) + if surface == nil then + local eventName = Converters.eventNameString(event.name) + log("[handleBuiltTileEvent] undefined surface " .. eventName) + return + end + local tiles = Converters.convertPlacedTiles(event.tile, event.tiles) + local groupedTiles = MapChunkUpdateHandler:groupTiles(tiles) + for ____, ____value in __TS__Iterator(groupedTiles) do + local chunkPos = ____value[1] + local tiles = ____value[2] + MapChunkUpdateHandler:mapTilesUpdateDebounce( + surface, + chunkPos, + tiles, + event, + function(data) + if isEventType(event, defines.events.on_player_built_tile) then + data.player = event.player_index + return + end + if isEventType(event, defines.events.on_robot_built_tile) then + local ____data_2 = data + local ____event_robot_unit_number_0 = event.robot + if ____event_robot_unit_number_0 ~= nil then + ____event_robot_unit_number_0 = ____event_robot_unit_number_0.unit_number + end + ____data_2.robot = { + unitNumber = ____event_robot_unit_number_0 or nil, + protoId = Converters.prototypeId(event.robot.type, event.robot.name) + } + return + end + local exhaustiveCheck = event + end + ) + end +end +function MapChunkUpdateHandler.prototype.handleMinedTileEvent(self, event) + local surface = game.get_surface(event.surface_index) + if surface == nil then + local eventName = Converters.eventNameString(event.name) + log("[handleMinedTileEvent] undefined surface " .. eventName) + return + end + local tiles = Converters.convertRemovedTiles(surface, event.tiles) + local groupedTiles = MapChunkUpdateHandler:groupTiles(tiles) + for ____, ____value in __TS__Iterator(groupedTiles) do + local chunkPos = ____value[1] + local tiles = ____value[2] + MapChunkUpdateHandler:mapTilesUpdateDebounce( + surface, + chunkPos, + tiles, + event, + function(data) + if isEventType(event, defines.events.on_player_mined_tile) then + data.player = event.player_index + return + end + if isEventType(event, defines.events.on_robot_mined_tile) then + local ____data_5 = data + local ____event_robot_unit_number_3 = event.robot + if ____event_robot_unit_number_3 ~= nil then + ____event_robot_unit_number_3 = ____event_robot_unit_number_3.unit_number + end + ____data_5.robot = { + unitNumber = ____event_robot_unit_number_3 or nil, + protoId = Converters.prototypeId(event.robot.type, event.robot.name) + } + return + end + local exhaustiveCheck = event + end + ) + end +end +function MapChunkUpdateHandler.prototype.handleScriptSetTilesEvent(self, event) + local surface = game.get_surface(event.surface_index) + if surface == nil then + return + end + local groupedTiles = MapChunkUpdateHandler:groupTiles(event.tiles) + for ____, ____value in __TS__Iterator(groupedTiles) do + local chunkPos = ____value[1] + local tiles = ____value[2] + MapChunkUpdateHandler:mapTilesUpdateDebounce(surface, chunkPos, tiles, event) + end +end +function MapChunkUpdateHandler.prototype.handlePreChunkDeleted(self, event) + local surface = game.get_surface(event.surface_index) + if surface == nil then + return + end + for ____, position in ipairs(event.positions) do + local key = {surfaceIndex = surface.index, chunkPosition = {position.x, position.y}} + EventUpdatesManager:debounce( + key, + KafkatorioPacketData.Type.MapChunkTileUpdate, + function(data) + data.isDeleted = true + return true + end, + 0 + ) + end +end +function MapChunkUpdateHandler.mapTilesUpdateDebounce(self, surface, chunkPosition, tiles, event, updater, expirationDurationTicks) + if surface == nil then + return + end + local eventName = Converters.eventNameString(event.name) + local key = {surfaceIndex = surface.index, chunkPosition = chunkPosition} + EventUpdatesManager:debounce( + key, + KafkatorioPacketData.Type.MapChunkTileUpdate, + function(data) + if data.tileDictionary == nil then + data.tileDictionary = {tilesXY = {}, protos = {}} + end + local protosCount = table_size(data.tileDictionary.protos) + for ____, tile in ipairs(tiles) do + local protoId = Converters.prototypeId("tile", tile.name) + if data.tileDictionary.protos[protoId] == nil then + end + local ____data_tileDictionary_protos_7, ____protoId_8 = data.tileDictionary.protos, protoId + if ____data_tileDictionary_protos_7[____protoId_8] == nil then + local ____protosCount_6 = protosCount + protosCount = ____protosCount_6 + 1 + ____data_tileDictionary_protos_7[____protoId_8] = ____protosCount_6 + end + local protoKey = data.tileDictionary.protos[protoId] + local xString = tostring(tile.position.x) + local yString = tostring(tile.position.y) + local ____data_tileDictionary_tilesXY_9, ____xString_10 = data.tileDictionary.tilesXY, xString + if ____data_tileDictionary_tilesXY_9[____xString_10] == nil then + ____data_tileDictionary_tilesXY_9[____xString_10] = {} + end + data.tileDictionary.tilesXY[xString][yString] = protoKey + end + if data.events == nil then + data.events = {} + end + local ____data_events_11, ____eventName_12 = data.events, eventName + if ____data_events_11[____eventName_12] == nil then + ____data_events_11[____eventName_12] = {} + end + local ____data_events_eventName_13 = data.events[eventName] + ____data_events_eventName_13[#____data_events_eventName_13 + 1] = event.tick + if updater ~= nil then + updater(data) + end + end, + expirationDurationTicks + ) +end +function MapChunkUpdateHandler.groupTiles(self, tiles) + local mapChunkPositionToTiles = __TS__New(Map) + for ____, tile in ipairs(tiles) do + local chunkPosition = { + math.floor(tile.position.x / 32), + math.floor(tile.position.y / 32) + } + if not mapChunkPositionToTiles:has(chunkPosition) then + mapChunkPositionToTiles:set(chunkPosition, {}) + end + local ____mapChunkPositionToTiles_get_result_push_result_14 = mapChunkPositionToTiles:get(chunkPosition) + if ____mapChunkPositionToTiles_get_result_push_result_14 ~= nil then + local ____temp_15 = mapChunkPositionToTiles:get(chunkPosition) + ____temp_15[#____temp_15 + 1] = tile + ____mapChunkPositionToTiles_get_result_push_result_14 = nil + end + end + return mapChunkPositionToTiles +end +local MapChunkUpdate = __TS__New(MapChunkUpdateHandler) +____exports.default = MapChunkUpdate +return ____exports diff --git a/modules/events-mod/src/generated/lua/main/events/handlers/PlayerUpdateHandler.lua b/modules/events-mod/src/generated/lua/main/events/handlers/PlayerUpdateHandler.lua new file mode 100644 index 0000000..0591e9b --- /dev/null +++ b/modules/events-mod/src/generated/lua/main/events/handlers/PlayerUpdateHandler.lua @@ -0,0 +1,60 @@ +local ____lualib = require("lualib_bundle") +local __TS__Class = ____lualib.__TS__Class +local __TS__New = ____lualib.__TS__New +local ____exports = {} +local ____kafkatorio_2Dschema = require("generated.kafkatorio-schema") +local KafkatorioPacketData = ____kafkatorio_2Dschema.KafkatorioPacketData +local ____converters = require("main.events.converters") +local Converters = ____converters.Converters +local ____EventDataCache = require("main.cache.EventDataCache") +local EventUpdatesManager = ____EventDataCache.default +____exports.PlayerUpdateHandler = __TS__Class() +local PlayerUpdateHandler = ____exports.PlayerUpdateHandler +PlayerUpdateHandler.name = "PlayerUpdateHandler" +function PlayerUpdateHandler.prototype.____constructor(self) +end +function PlayerUpdateHandler.prototype.handleBannedEvent(self, event) + self:playerUpdateThrottle( + event, + function(player, data) + data.bannedReason = event.reason or nil + Converters.playerOnlineInfo(player, data) + end + ) +end +function PlayerUpdateHandler.prototype.playerUpdateThrottle(self, event, mutate, expirationDurationTicks) + if expirationDurationTicks == nil then + expirationDurationTicks = nil + end + local playerIndex = event.player_index + if playerIndex == nil then + return + end + local eventName = Converters.eventNameString(event.name) + EventUpdatesManager:throttle( + {index = playerIndex}, + KafkatorioPacketData.Type.PlayerUpdate, + function(data) + local player = game.players[playerIndex] + if player ~= nil then + mutate(player, data) + end + if data.events == nil then + data.events = {} + end + local ____data_events_0, ____eventName_1 = data.events, eventName + if ____data_events_0[____eventName_1] == nil then + ____data_events_0[____eventName_1] = {} + end + local ____data_events_eventName_2 = data.events[eventName] + ____data_events_eventName_2[#____data_events_eventName_2 + 1] = event.tick + end, + expirationDurationTicks + ) +end +function PlayerUpdateHandler.prototype.playerUpdateImmediate(self, event, mutate) + self:playerUpdateThrottle(event, mutate, 0) +end +local PlayerUpdates = __TS__New(____exports.PlayerUpdateHandler) +____exports.default = PlayerUpdates +return ____exports diff --git a/modules/events-mod/src/generated/lua/main/events/mapChunkUpdates.lua b/modules/events-mod/src/generated/lua/main/events/mapChunkUpdates.lua index a21a929..b3c5857 100644 --- a/modules/events-mod/src/generated/lua/main/events/mapChunkUpdates.lua +++ b/modules/events-mod/src/generated/lua/main/events/mapChunkUpdates.lua @@ -1,213 +1,8 @@ -local ____lualib = require("lualib_bundle") -local __TS__Class = ____lualib.__TS__Class -local Map = ____lualib.Map -local __TS__Iterator = ____lualib.__TS__Iterator -local __TS__New = ____lualib.__TS__New local ____exports = {} -local ____eventTypeCheck = require("main.events.eventTypeCheck") -local isEventType = ____eventTypeCheck.isEventType -local ____converters = require("main.events.converters") -local Converters = ____converters.Converters -local ____EventDataCache = require("main.cache.EventDataCache") -local EventUpdatesManager = ____EventDataCache.default -local ____kafkatorio_2Dschema = require("generated.kafkatorio-schema") -local KafkatorioPacketData = ____kafkatorio_2Dschema.KafkatorioPacketData -local ____entityUpdates = require("main.events.entityUpdates") -local EntityUpdates = ____entityUpdates.default -local Type = KafkatorioPacketData.Type -local MapChunkUpdateHandler = __TS__Class() -MapChunkUpdateHandler.name = "MapChunkUpdateHandler" -function MapChunkUpdateHandler.prototype.____constructor(self) -end -function MapChunkUpdateHandler.prototype.handleChunkGeneratedEvent(self, event, expirationDurationTicks) - local tiles = event.surface.find_tiles_filtered({area = event.area}) - MapChunkUpdateHandler:mapTilesUpdateDebounce( - event.surface, - Converters.convertMapTablePosition(event.position), - tiles, - event, - nil, - expirationDurationTicks - ) -end -function MapChunkUpdateHandler.prototype.handleBuiltTileEvent(self, event) - local surface = game.get_surface(event.surface_index) - if surface == nil then - local eventName = Converters.eventNameString(event.name) - log("[handleBuiltTileEvent] undefined surface " .. eventName) - return - end - local tiles = Converters.convertPlacedTiles(event.tile, event.tiles) - local groupedTiles = MapChunkUpdateHandler:groupTiles(tiles) - for ____, ____value in __TS__Iterator(groupedTiles) do - local chunkPos = ____value[1] - local tiles = ____value[2] - MapChunkUpdateHandler:mapTilesUpdateDebounce( - surface, - chunkPos, - tiles, - event, - function(data) - if isEventType(event, defines.events.on_player_built_tile) then - data.player = event.player_index - return - end - if isEventType(event, defines.events.on_robot_built_tile) then - local ____data_2 = data - local ____event_robot_unit_number_0 = event.robot - if ____event_robot_unit_number_0 ~= nil then - ____event_robot_unit_number_0 = ____event_robot_unit_number_0.unit_number - end - ____data_2.robot = { - unitNumber = ____event_robot_unit_number_0 or nil, - protoId = Converters.prototypeId(event.robot.type, event.robot.name) - } - return - end - local exhaustiveCheck = event - end - ) - end -end -function MapChunkUpdateHandler.prototype.handleMinedTileEvent(self, event) - local surface = game.get_surface(event.surface_index) - if surface == nil then - local eventName = Converters.eventNameString(event.name) - log("[handleMinedTileEvent] undefined surface " .. eventName) - return - end - local tiles = Converters.convertRemovedTiles(surface, event.tiles) - local groupedTiles = MapChunkUpdateHandler:groupTiles(tiles) - for ____, ____value in __TS__Iterator(groupedTiles) do - local chunkPos = ____value[1] - local tiles = ____value[2] - MapChunkUpdateHandler:mapTilesUpdateDebounce( - surface, - chunkPos, - tiles, - event, - function(data) - if isEventType(event, defines.events.on_player_mined_tile) then - data.player = event.player_index - return - end - if isEventType(event, defines.events.on_robot_mined_tile) then - local ____data_5 = data - local ____event_robot_unit_number_3 = event.robot - if ____event_robot_unit_number_3 ~= nil then - ____event_robot_unit_number_3 = ____event_robot_unit_number_3.unit_number - end - ____data_5.robot = { - unitNumber = ____event_robot_unit_number_3 or nil, - protoId = Converters.prototypeId(event.robot.type, event.robot.name) - } - return - end - local exhaustiveCheck = event - end - ) - end -end -function MapChunkUpdateHandler.prototype.handleScriptSetTilesEvent(self, event) - local surface = game.get_surface(event.surface_index) - if surface == nil then - return - end - local groupedTiles = MapChunkUpdateHandler:groupTiles(event.tiles) - for ____, ____value in __TS__Iterator(groupedTiles) do - local chunkPos = ____value[1] - local tiles = ____value[2] - MapChunkUpdateHandler:mapTilesUpdateDebounce(surface, chunkPos, tiles, event) - end -end -function MapChunkUpdateHandler.prototype.handlePreChunkDeleted(self, event) - local surface = game.get_surface(event.surface_index) - if surface == nil then - return - end - for ____, position in ipairs(event.positions) do - local key = {surfaceIndex = surface.index, chunkPosition = {position.x, position.y}} - EventUpdatesManager:debounce( - key, - Type.MapChunkTileUpdate, - function(data) - data.isDeleted = true - return true - end, - 0 - ) - end -end -function MapChunkUpdateHandler.mapTilesUpdateDebounce(self, surface, chunkPosition, tiles, event, updater, expirationDurationTicks) - if surface == nil then - return - end - local eventName = Converters.eventNameString(event.name) - local key = {surfaceIndex = surface.index, chunkPosition = chunkPosition} - EventUpdatesManager:debounce( - key, - Type.MapChunkTileUpdate, - function(data) - if data.tileDictionary == nil then - data.tileDictionary = {tilesXY = {}, protos = {}} - end - local protosCount = table_size(data.tileDictionary.protos) - for ____, tile in ipairs(tiles) do - local protoId = Converters.prototypeId("tile", tile.name) - if data.tileDictionary.protos[protoId] == nil then - end - local ____data_tileDictionary_protos_7, ____protoId_8 = data.tileDictionary.protos, protoId - if ____data_tileDictionary_protos_7[____protoId_8] == nil then - local ____protosCount_6 = protosCount - protosCount = ____protosCount_6 + 1 - ____data_tileDictionary_protos_7[____protoId_8] = ____protosCount_6 - end - local protoKey = data.tileDictionary.protos[protoId] - local xString = tostring(tile.position.x) - local yString = tostring(tile.position.y) - local ____data_tileDictionary_tilesXY_9, ____xString_10 = data.tileDictionary.tilesXY, xString - if ____data_tileDictionary_tilesXY_9[____xString_10] == nil then - ____data_tileDictionary_tilesXY_9[____xString_10] = {} - end - data.tileDictionary.tilesXY[xString][yString] = protoKey - end - if data.events == nil then - data.events = {} - end - local ____data_events_11, ____eventName_12 = data.events, eventName - if ____data_events_11[____eventName_12] == nil then - ____data_events_11[____eventName_12] = {} - end - local ____data_events_eventName_13 = data.events[eventName] - ____data_events_eventName_13[#____data_events_eventName_13 + 1] = event.tick - if updater ~= nil then - updater(data) - end - end, - expirationDurationTicks - ) -end -function MapChunkUpdateHandler.groupTiles(self, tiles) - local mapChunkPositionToTiles = __TS__New(Map) - for ____, tile in ipairs(tiles) do - local chunkPosition = { - math.floor(tile.position.x / 32), - math.floor(tile.position.y / 32) - } - if not mapChunkPositionToTiles:has(chunkPosition) then - mapChunkPositionToTiles:set(chunkPosition, {}) - end - local ____mapChunkPositionToTiles_get_result_push_result_14 = mapChunkPositionToTiles:get(chunkPosition) - if ____mapChunkPositionToTiles_get_result_push_result_14 ~= nil then - local ____temp_15 = mapChunkPositionToTiles:get(chunkPosition) - ____temp_15[#____temp_15 + 1] = tile - ____mapChunkPositionToTiles_get_result_push_result_14 = nil - end - end - return mapChunkPositionToTiles -end -local MapChunkUpdate = __TS__New(MapChunkUpdateHandler) -____exports.default = MapChunkUpdate +local ____EntityUpdateHandler = require("main.events.handlers.EntityUpdateHandler") +local EntityUpdates = ____EntityUpdateHandler.default +local ____MapChunkUpdateHandler = require("main.events.handlers.MapChunkUpdateHandler") +local MapChunkUpdate = ____MapChunkUpdateHandler.default script.on_event( defines.events.on_chunk_generated, function(e) diff --git a/modules/events-mod/src/generated/lua/main/events/playerUpdates.lua b/modules/events-mod/src/generated/lua/main/events/playerUpdates.lua index 47840de..885348b 100644 --- a/modules/events-mod/src/generated/lua/main/events/playerUpdates.lua +++ b/modules/events-mod/src/generated/lua/main/events/playerUpdates.lua @@ -1,75 +1,26 @@ local ____exports = {} -local playerUpdateThrottle, playerOnlineInfo, handleBannedEvent, Type +local disconnectReasons local ____converters = require("main.events.converters") local Converters = ____converters.Converters -local ____EventDataCache = require("main.cache.EventDataCache") -local EventUpdatesManager = ____EventDataCache.default local ____kafkatorio_2Dschema = require("generated.kafkatorio-schema") local KafkatorioPacketData = ____kafkatorio_2Dschema.KafkatorioPacketData local ____PacketEmitter = require("main.PacketEmitter") local packetEmitter = ____PacketEmitter.default -function playerUpdateThrottle(event, mutate, expirationDurationTicks) - if expirationDurationTicks == nil then - expirationDurationTicks = nil - end - local playerIndex = event.player_index - if playerIndex == nil then - return - end - local eventName = Converters.eventNameString(event.name) - EventUpdatesManager:throttle( - {index = playerIndex}, - Type.PlayerUpdate, - function(data) - local player = game.players[playerIndex] - if player ~= nil then - mutate(player, data) - end - if data.events == nil then - data.events = {} - end - local ____data_events_0, ____eventName_1 = data.events, eventName - if ____data_events_0[____eventName_1] == nil then - ____data_events_0[____eventName_1] = {} - end - local ____data_events_eventName_2 = data.events[eventName] - ____data_events_eventName_2[#____data_events_eventName_2 + 1] = event.tick - end, - expirationDurationTicks - ) -end -function playerOnlineInfo(player, data) - data.lastOnline = player.last_online - data.onlineTime = player.online_time - data.afkTime = player.afk_time - data.isConnected = player.connected -end -function handleBannedEvent(event) - playerUpdateThrottle( - event, - function(player, data) - data.bannedReason = event.reason or nil - playerOnlineInfo(player, data) - end - ) -end -Type = KafkatorioPacketData.Type -local function playerUpdateImmediate(event, mutate) - playerUpdateThrottle(event, mutate, 0) -end +local ____PlayerUpdateHandler = require("main.events.handlers.PlayerUpdateHandler") +local PlayerUpdates = ____PlayerUpdateHandler.default script.on_event( defines.events.on_player_joined_game, function(e) - playerUpdateThrottle( + PlayerUpdates:playerUpdateThrottle( e, function(player, data) data.isAdmin = player.admin - local ____data_5 = data - local ____player_character_unit_number_3 = player.character - if ____player_character_unit_number_3 ~= nil then - ____player_character_unit_number_3 = ____player_character_unit_number_3.unit_number + local ____data_2 = data + local ____player_character_unit_number_0 = player.character + if ____player_character_unit_number_0 ~= nil then + ____player_character_unit_number_0 = ____player_character_unit_number_0.unit_number end - ____data_5.characterUnitNumber = ____player_character_unit_number_3 or nil + ____data_2.characterUnitNumber = ____player_character_unit_number_0 or nil data.chatColour = Converters.mapColour(player.chat_color) data.colour = Converters.mapColour(player.color) data.forceIndex = player.force.index @@ -78,7 +29,7 @@ script.on_event( data.isSpectator = player.spectator data.surfaceIndex = player.surface.index data.tag = player.tag - playerOnlineInfo(player, data) + Converters.playerOnlineInfo(player, data) end ) end @@ -86,7 +37,7 @@ script.on_event( script.on_event( defines.events.on_player_changed_position, function(e) - playerUpdateThrottle( + PlayerUpdates:playerUpdateThrottle( e, function(player, data) data.position = {player.position.x, player.position.y} @@ -97,7 +48,7 @@ script.on_event( script.on_event( defines.events.on_player_changed_surface, function(e) - playerUpdateThrottle( + PlayerUpdates:playerUpdateThrottle( e, function(player, data) data.position = {player.position.x, player.position.y} @@ -109,11 +60,11 @@ script.on_event( script.on_event( defines.events.on_player_died, function(e) - playerUpdateThrottle( + PlayerUpdates:playerUpdateThrottle( e, function(player, data) data.ticksToRespawn = player.ticks_to_respawn or nil - playerOnlineInfo(player, data) + Converters.playerOnlineInfo(player, data) if e.cause ~= nil then data.diedCause = { unitNumber = e.cause.unit_number or nil, @@ -124,25 +75,31 @@ script.on_event( ) end ) -script.on_event(defines.events.on_player_banned, handleBannedEvent) -script.on_event(defines.events.on_player_unbanned, handleBannedEvent) +script.on_event( + defines.events.on_player_banned, + function(event) + PlayerUpdates:handleBannedEvent(event) + end +) +script.on_event( + defines.events.on_player_unbanned, + function(event) + PlayerUpdates:handleBannedEvent(event) + end +) script.on_event( defines.events.on_player_kicked, function(event) log((("on_player_kicked " .. tostring(event.tick)) .. " ") .. tostring(event.name)) - playerUpdateImmediate( + PlayerUpdates:playerUpdateImmediate( event, function(player, data) data.kickedReason = event.reason or nil - playerOnlineInfo(player, data) + Converters.playerOnlineInfo(player, data) end ) end ) -local disconnectReasons = {} -for name, disconnectId in pairs(defines.disconnect_reason) do - disconnectReasons[disconnectId] = name -end script.on_event( defines.events.on_pre_player_left_game, function(event) @@ -156,13 +113,17 @@ script.on_event( defines.events.on_player_removed, function(event) log((("on_player_removed " .. tostring(event.tick)) .. " ") .. tostring(event.name)) - playerUpdateImmediate( + PlayerUpdates:playerUpdateImmediate( event, function(player, data) data.isRemoved = true - playerOnlineInfo(player, data) + Converters.playerOnlineInfo(player, data) end ) end ) +disconnectReasons = {} +for name, disconnectId in pairs(defines.disconnect_reason) do + disconnectReasons[disconnectId] = name +end return ____exports diff --git a/modules/events-mod/src/generated/lua/main/events/prototypeUpdates.lua b/modules/events-mod/src/generated/lua/main/events/prototypeUpdates.lua index a1d6f07..551e592 100644 --- a/modules/events-mod/src/generated/lua/main/events/prototypeUpdates.lua +++ b/modules/events-mod/src/generated/lua/main/events/prototypeUpdates.lua @@ -1,7 +1,5 @@ -local ____lualib = require("lualib_bundle") -local __TS__ArrayPushArray = ____lualib.__TS__ArrayPushArray local ____exports = {} -local prototypeUpdates, getMapTilePrototypes +local emit, getMapTilePrototypes, getEntityPrototypes, convertItemGroup, convertItemSubgroup local ____PacketEmitter = require("main.PacketEmitter") local PacketEmitter = ____PacketEmitter.default local ____kafkatorio_2Dschema = require("generated.kafkatorio-schema") @@ -9,18 +7,19 @@ local FactorioPrototype = ____kafkatorio_2Dschema.FactorioPrototype local KafkatorioPacketData = ____kafkatorio_2Dschema.KafkatorioPacketData local ____converters = require("main.events.converters") local Converters = ____converters.Converters -function prototypeUpdates() - local prototypes = {} - __TS__ArrayPushArray( - prototypes, - getMapTilePrototypes() - ) - return prototypes +function emit(protosByType) + for ____, protos in pairs(protosByType) do + PacketEmitter:emitInstantPacket({type = KafkatorioPacketData.Type.PrototypesUpdate, prototypes = protos}) + end end function getMapTilePrototypes() local tiles = {} + if not (tiles.tile ~= nil) then + tiles.tile = {} + end for ____, tile in pairs(game.tile_prototypes) do - tiles[#tiles + 1] = { + local ____tiles_tile_0 = tiles.tile + ____tiles_tile_0[#____tiles_tile_0 + 1] = { type = FactorioPrototype.Type.MapTile, protoId = Converters.prototypeId("tile", tile.name), order = tile.order, @@ -32,11 +31,56 @@ function getMapTilePrototypes() end return tiles end +function getEntityPrototypes() + local protos = {} + for ____, entity in pairs(game.entity_prototypes) do + local key = (entity.group.name .. "/") .. entity.subgroup.name + if not (protos[key] ~= nil) then + protos[key] = {} + end + local entityProto = { + type = FactorioPrototype.Type.Entity, + protoId = Converters.prototypeId(entity.type, entity.name), + group = convertItemGroup(entity.group), + subgroup = convertItemSubgroup(entity.subgroup), + isBuilding = entity.is_building, + isEntityWithOwner = entity.is_entity_with_owner, + isMilitaryTarget = entity.is_military_target, + maxHealth = entity.max_health + } + if entity.map_color ~= nil then + entityProto.mapColour = Converters.mapColour(entity.map_color) + end + if entity.friendly_map_color ~= nil then + entityProto.mapColourFriend = Converters.mapColour(entity.friendly_map_color) + end + if entity.enemy_map_color ~= nil then + entityProto.mapColourEnemy = Converters.mapColour(entity.enemy_map_color) + end + entityProto.miningProperties = Converters.miningProperties(entity.mineable_properties) + local ____protos_key_1 = protos[key] + ____protos_key_1[#____protos_key_1 + 1] = entityProto + end + return protos +end +function convertItemGroup(itemGroup) + return {name = itemGroup.name, type = itemGroup.type, parentName = nil} +end +function convertItemSubgroup(itemGroup) + local ____itemGroup_name_4 = itemGroup.name + local ____itemGroup_type_5 = itemGroup.type + local ____itemGroup_group_name_2 = itemGroup.group + if ____itemGroup_group_name_2 ~= nil then + ____itemGroup_group_name_2 = ____itemGroup_group_name_2.name + end + return {name = ____itemGroup_name_4, type = ____itemGroup_type_5, parentName = ____itemGroup_group_name_2} +end function ____exports.emitPrototypes() - local data = { - prototypes = prototypeUpdates(), - type = KafkatorioPacketData.Type.PrototypesUpdate - } - PacketEmitter:emitInstantPacket(data) + local mapTileProtos = getMapTilePrototypes() + emit(mapTileProtos) + local ____ = game.item_group_prototypes + local ____ = game.item_subgroup_prototypes + local entityProtos = getEntityPrototypes() + emit(entityProtos) end return ____exports diff --git a/modules/events-mod/src/generated/lua/main/events/registerEventListeners.lua b/modules/events-mod/src/generated/lua/main/events/registerEventListeners.lua index 757ef9a..421c0b0 100644 --- a/modules/events-mod/src/generated/lua/main/events/registerEventListeners.lua +++ b/modules/events-mod/src/generated/lua/main/events/registerEventListeners.lua @@ -9,8 +9,8 @@ local ____surfaceUpdates = require("main.events.surfaceUpdates") local handleSurfaceUpdate = ____surfaceUpdates.handleSurfaceUpdate local ____EventDataCache = require("main.cache.EventDataCache") local EventCacheService = ____EventDataCache.default -local ____mapChunkUpdates = require("main.events.mapChunkUpdates") -local MapChunkUpdate = ____mapChunkUpdates.default +local ____MapChunkUpdateHandler = require("main.events.handlers.MapChunkUpdateHandler") +local MapChunkUpdate = ____MapChunkUpdateHandler.default script.on_event( defines.events.on_tick, function(event) diff --git a/modules/events-mod/src/generated/lua/main/events/resourceEntityUpdates.lua b/modules/events-mod/src/generated/lua/main/events/resourceEntityUpdates.lua deleted file mode 100644 index e69de29..0000000 diff --git a/modules/events-mod/src/main/typescript/generated/kafkatorio-schema.ts b/modules/events-mod/src/main/typescript/generated/kafkatorio-schema.ts index 0ff6cea..3598c28 100644 --- a/modules/events-mod/src/main/typescript/generated/kafkatorio-schema.ts +++ b/modules/events-mod/src/main/typescript/generated/kafkatorio-schema.ts @@ -211,15 +211,17 @@ export namespace FactorioPrototype { export interface Entity { type: FactorioPrototype.Type.Entity; protoId: PrototypeId; - mapColour: Colour; - protoType: string; - objectName: string; - colour: Colour; + group: EntityItemGroup; + subgroup: EntityItemGroup; + colour?: Colour | null; + mapColour?: Colour | null; + mapColourFriend?: Colour | null; + mapColourEnemy?: Colour | null; maxHealth: Float; isBuilding: boolean; isEntityWithOwner: boolean; isMilitaryTarget: boolean; - miningProperties: MiningProperties; + miningProperties?: EntityMiningProperties | null; } export interface MapTile { @@ -278,7 +280,13 @@ export namespace FactorioEntityData { } } -export interface MiningProperties { +export interface EntityItemGroup { + name: string; + type: string; + parentName?: string | null; +} + +export interface EntityMiningProperties { canBeMined: boolean; products: MinedProduct[] | null; } diff --git a/modules/events-mod/src/main/typescript/main/events/configurationUpdate.ts b/modules/events-mod/src/main/typescript/main/events/configurationUpdate.ts index b11863f..a49b740 100644 --- a/modules/events-mod/src/main/typescript/main/events/configurationUpdate.ts +++ b/modules/events-mod/src/main/typescript/main/events/configurationUpdate.ts @@ -1,65 +1,12 @@ -import PacketEmitter from "../PacketEmitter"; -import { - ConfigurationUpdateGameData, - ConfigurationUpdateModData, - KafkatorioPacketData -} from "../../generated/kafkatorio-schema"; import {initGlobal} from "../global-init"; import {emitPrototypes} from "./prototypeUpdates"; -import Type = KafkatorioPacketData.Type; -import ConfigurationUpdate = KafkatorioPacketData.ConfigurationUpdate; +import ConfigurationUpdates from "./handlers/ConfigurationUpdateHandler"; script.on_configuration_changed((data: ConfigurationChangedData) => { // runs whenever the version of the base game, or a mod, changes initGlobal(true) // KafkatorioSettings.loadSettings() - emitConfigurationUpdate(data) + ConfigurationUpdates.emitConfigurationUpdate(data) emitPrototypes() }) - - -function emitConfigurationUpdate(changeData: ConfigurationChangedData) { - - const configUpdateData: ConfigurationUpdate = { - type: Type.ConfigurationUpdate, - migrationApplied: changeData.migration_applied, - modStartupSettingsChange: changeData.mod_startup_settings_changed, - allMods: allMods(changeData), - factorioData: factorioData(changeData) - } - - PacketEmitter.emitInstantPacket(configUpdateData) -} - - -function factorioData(changeData: ConfigurationChangedData): ConfigurationUpdateGameData { - return { - oldVersion: changeData.old_version ?? null, - newVersion: changeData.new_version ?? null, - } -} - - -function allMods(e: ConfigurationChangedData): ConfigurationUpdateModData[] { - - let namesOfChangedMods: string[] = Object.keys(e.mod_changes) - let namesOfCurrentMods: string[] = Object.keys(script.active_mods) - - let modNames = [...new Set( - namesOfChangedMods.concat(namesOfCurrentMods) - )] - - return modNames.map((modName) => { - - let currentVer = script.active_mods[modName] ?? e.mod_changes[modName]?.new_version ?? null - let previousVer = e.mod_changes[modName]?.old_version ?? null - - return { - modName: modName, - currentVersion: currentVer, - previousVersion: previousVer, - } - }) - -} 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 220484e..861c546 100644 --- a/modules/events-mod/src/main/typescript/main/events/converters.ts +++ b/modules/events-mod/src/main/typescript/main/events/converters.ts @@ -1,10 +1,13 @@ import {DefinedEventName} from "../types"; import { Colour, + EntityMiningProperties, EntityStatus, EventName, FactorioEntityData, + KafkatorioPacketData, MapChunkPosition, + MinedProduct, PrototypeId, } from "../../generated/kafkatorio-schema"; @@ -133,6 +136,46 @@ export namespace Converters { } + export function miningProperties( + properties: LuaEntityPrototype["mineable_properties"] + ): EntityMiningProperties { + + const products: MinedProduct[] = [] + + if (properties.products != null) { + for (const product of properties.products) { + if (product.type == "fluid") { + products[products.length] = { + type: MinedProduct.Type.MinedProductFluid, + amount: product.amount, + resultProtoId: Converters.prototypeId(product.type, product.name), + } + } + if (product.type == "item") { + products[products.length] = { + type: MinedProduct.Type.MinedProductItem, + amount: product.amount, + resultProtoId: Converters.prototypeId(product.type, product.name), + } + } + } + } + + return { + canBeMined: properties.minable, + products: products, + } + } + + + export function playerOnlineInfo(player: LuaPlayer, data: KafkatorioPacketData.PlayerUpdate) { + data.lastOnline = player.last_online + data.onlineTime = player.online_time + data.afkTime = player.afk_time + data.isConnected = player.connected + } + + const EntityStatusRecord: Record = { //@formatter:off [ defines.entity_status.cant_divide_segments ]: EntityStatus.CANT_DIVIDE_SEGMENTS, diff --git a/modules/events-mod/src/main/typescript/main/events/entityUpdates.ts b/modules/events-mod/src/main/typescript/main/events/entityUpdates.ts index f262eb3..05507ae 100644 --- a/modules/events-mod/src/main/typescript/main/events/entityUpdates.ts +++ b/modules/events-mod/src/main/typescript/main/events/entityUpdates.ts @@ -1,230 +1,4 @@ -import {Converters} from "./converters"; -import EventDataCache from "../cache/EventDataCache"; -import { - EventName, - FactorioEntityData, - KafkatorioPacketData, - MapChunkPosition, - PrototypeId, - Tick, -} from "../../generated/kafkatorio-schema"; - - -export class EntityUpdatesHandler { - - - handleMinedTileEvent(event: OnPlayerMinedTileEvent | OnRobotMinedTileEvent) { - - const surface = game.get_surface(event.surface_index) - if (surface == null) { - return - } - - const tilesByChunk: LuaTable = new LuaTable() - - for (const tile of event.tiles) { - const chunkPosition = Converters.tilePositionToChunkPosition(tile.position) - tilesByChunk.set(chunkPosition, tile) - } - - for (const [chunkPos, tiles] of pairs(tilesByChunk)) { - - const entities: FactorioEntityData.Resource[] = [] - - for (const tile in tiles) { - const resources: FactorioEntityData.Resource[] = EntityUpdatesHandler.getTileResourceEntities(surface, chunkPos) - for (const resource of resources) { - entities[entities.length] = resource - } - } - - EntityUpdatesHandler.throttleResourceEntitiesUpdate( - Converters.eventNameString(event.name), - event.tick as Tick, - event.surface_index, - [chunkPos[0], chunkPos[1]], - entities, - ) - } - } - - - handleMinedEntityEvent( - event: OnPlayerMinedEntityEvent | OnRobotMinedEntityEvent, - ) { - EntityUpdatesHandler.throttleEntityUpdate(event, event.entity) - } - - - handleBuiltEntityEvent( - event: OnBuiltEntityEvent | OnRobotBuiltEntityEvent, - ) { - EntityUpdatesHandler.throttleEntityUpdate(event, event.created_entity) - } - - - handleChunkGeneratedEvent(event: OnChunkGeneratedEvent) { - const entities = EntityUpdatesHandler.getAreaResourceEntities(event.surface, event.area) - EntityUpdatesHandler.throttleResourceEntitiesUpdate( - Converters.eventNameString(event.name), - event.tick as Tick, - event.surface.index, - [event.position.x, event.position.y], - entities, - ) - } - - - private static throttleEntityUpdate(event: EntityUpdateEvent, entity: LuaEntity) { - - if (entity.unit_number == undefined) { - // ignore for now - I'm not sure how to track entities without a unit_number - return - } - const eventName = Converters.eventNameString(event.name) - - const entityUpdateKey: KafkatorioPacketData.MapChunkEntityUpdate["key"] = { - protoId: Converters.prototypeIdEntity(entity), - surfaceIndex: entity.surface.index, - chunkPosition: Converters.mapPositionToChunkPosition(entity.position) - } - - const entityUpdate: FactorioEntityData.Standard = { - type: FactorioEntityData.Type.Standard, - protoId: Converters.prototypeIdEntity(entity), - graphicsVariation: entity.graphics_variation, - health: entity.health, - isActive: entity.active, - isRotatable: entity.rotatable, - lastUser: entity.last_user?.index, - localisedDescription: null, - localisedName: null, - position: [entity.position.x, entity.position.y], - status: Converters.entityStatus(entity.status), - } - - const entityKey: string = `${entity.unit_number}` - - EventDataCache.throttle( - entityUpdateKey, - KafkatorioPacketData.Type.MapChunkEntityUpdate, - data => { - - data.events ??= {} - data.events[eventName] ??= [] - data.events[eventName].push(event.tick) - - data.distinctEntities ??= {} - data.distinctEntities[entityKey] = entityUpdate - } - ) - } - - - private static throttleResourceEntitiesUpdate( - eventName: EventName, - eventTick: Tick, - surfaceIndex: SurfaceIndex, - chunkPosition: MapChunkPosition, - entities: FactorioEntityData.Resource[], - ) { - - // first group by prototype ID - const entitiesByProtoId: { [protoId: PrototypeId]: FactorioEntityData.Resource[] } = {} - - for (const entity of entities) { - entitiesByProtoId[entity.protoId] ??= [] - entitiesByProtoId[entity.protoId].push(entity) - } - - for (const [protoId, resourceEntities] of pairs(entitiesByProtoId)) { - - // create an update for each prototype - - const entityUpdateKey: KafkatorioPacketData.MapChunkEntityUpdate["key"] = { - protoId: protoId, - surfaceIndex: surfaceIndex, - chunkPosition: [chunkPosition[0], chunkPosition[1]], - } - - EventDataCache.throttle( - entityUpdateKey, - KafkatorioPacketData.Type.MapChunkEntityUpdate, - data => { - - data.events ??= {} - data.events[eventName] ??= [] - data.events[eventName].push(eventTick) - - for (const entity of resourceEntities) { - const [x, y] = entity.position - const entityKey: string = `${x},${y}` - - data.distinctEntities ??= {} - data.distinctEntities[entityKey] = entity - } - } - ) - } - - } - - - /** Get all resources on a tile-position */ - private static getTileResourceEntities( - surface: LuaSurface, - mapPosition: MapPosition, - ): FactorioEntityData.Resource[] { - - const rawEntities = surface.find_entities_filtered({ - position: mapPosition, - collision_mask: "resource-layer", - } - ) - - const resources: FactorioEntityData.Resource[] = [] - - for (const rawEntity of rawEntities) { - const entity = Converters.convertResourceEntity(rawEntity) - if (entity != null) { - resources[resources.length] = entity - } - } - - return resources - } - - - /** Get all resources within a map-area */ - private static getAreaResourceEntities( - surface: LuaSurface, - area: BoundingBoxTable, - ): FactorioEntityData.Resource[] { - - const rawEntities = surface.find_entities_filtered({ - area: area, - collision_mask: "resource-layer", - } - ) - - const resources: FactorioEntityData.Resource[] = [] - - for (const rawEntity of rawEntities) { - const entity = Converters.convertResourceEntity(rawEntity) - if (entity != null) { - resources[resources.length] = entity - } - } - - return resources - } -} - - -const EntityUpdates = new EntityUpdatesHandler() - -export default EntityUpdates - +import EntityUpdates from "./handlers/EntityUpdateHandler"; script.on_event(defines.events.on_built_entity, (e: OnBuiltEntityEvent) => { log(`on_built_entity ${e.tick}`) @@ -248,29 +22,3 @@ script.on_event(defines.events.on_robot_mined_entity, (e: OnRobotMinedEntityEven log(`on_robot_mined_entity ${e.tick}`) EntityUpdates.handleMinedEntityEvent(e) }) - - -type EntityUpdateEvent = - | OnBuiltEntityEvent - - | OnEntityClonedEvent - | OnEntityDamagedEvent - | OnEntityDestroyedEvent - | OnEntityDiedEvent - | OnEntityLogisticSlotChangedEvent - | OnEntityRenamedEvent - | OnEntitySettingsPastedEvent - | OnEntitySpawnedEvent - - | OnPlayerMinedEntityEvent - | OnPlayerRepairedEntityEvent - | OnPlayerRotatedEntityEvent - - | OnRobotMinedEntityEvent - | OnRobotBuiltEntityEvent - - | OnPostEntityDiedEvent - | OnPreEntitySettingsPastedEvent - - | OnSelectedEntityChangedEvent - | OnTriggerCreatedEntityEvent diff --git a/modules/events-mod/src/main/typescript/main/events/handlers/ConfigurationUpdateHandler.ts b/modules/events-mod/src/main/typescript/main/events/handlers/ConfigurationUpdateHandler.ts new file mode 100644 index 0000000..b90fec1 --- /dev/null +++ b/modules/events-mod/src/main/typescript/main/events/handlers/ConfigurationUpdateHandler.ts @@ -0,0 +1,62 @@ +import { + ConfigurationUpdateGameData, + ConfigurationUpdateModData, + KafkatorioPacketData +} from "../../../generated/kafkatorio-schema"; +import PacketEmitter from "../../PacketEmitter"; +import ConfigurationUpdate = KafkatorioPacketData.ConfigurationUpdate; + + +export class ConfigurationUpdateHandler { + + + emitConfigurationUpdate(changeData: ConfigurationChangedData) { + + const configUpdateData: ConfigurationUpdate = { + type: KafkatorioPacketData.Type.ConfigurationUpdate, + migrationApplied: changeData.migration_applied, + modStartupSettingsChange: changeData.mod_startup_settings_changed, + allMods: ConfigurationUpdateHandler.allMods(changeData), + factorioData: ConfigurationUpdateHandler.factorioData(changeData) + } + + PacketEmitter.emitInstantPacket(configUpdateData) + } + + + private static factorioData(changeData: ConfigurationChangedData): ConfigurationUpdateGameData { + return { + oldVersion: changeData.old_version ?? null, + newVersion: changeData.new_version ?? null, + } + } + + + private static allMods(e: ConfigurationChangedData): ConfigurationUpdateModData[] { + + let namesOfChangedMods: string[] = Object.keys(e.mod_changes) + let namesOfCurrentMods: string[] = Object.keys(script.active_mods) + + let modNames = [...new Set( + namesOfChangedMods.concat(namesOfCurrentMods) + )] + + return modNames.map((modName) => { + + let currentVer = script.active_mods[modName] ?? e.mod_changes[modName]?.new_version ?? null + let previousVer = e.mod_changes[modName]?.old_version ?? null + + return { + modName: modName, + currentVersion: currentVer, + previousVersion: previousVer, + } + }) + + } + +} + +const ConfigurationUpdates = new ConfigurationUpdateHandler() + +export default ConfigurationUpdates diff --git a/modules/events-mod/src/main/typescript/main/events/handlers/EntityUpdateHandler.ts b/modules/events-mod/src/main/typescript/main/events/handlers/EntityUpdateHandler.ts new file mode 100644 index 0000000..7ac7d13 --- /dev/null +++ b/modules/events-mod/src/main/typescript/main/events/handlers/EntityUpdateHandler.ts @@ -0,0 +1,250 @@ +import { + EventName, + FactorioEntityData, + KafkatorioPacketData, + MapChunkPosition, PrototypeId, + Tick +} from "../../../generated/kafkatorio-schema"; +import {Converters} from "../converters"; +import EventDataCache from "../../cache/EventDataCache"; + + +export class EntityUpdatesHandler { + + + handleMinedTileEvent(event: OnPlayerMinedTileEvent | OnRobotMinedTileEvent) { + + const surface = game.get_surface(event.surface_index) + if (surface == null) { + return + } + + const tilesByChunk: LuaTable = new LuaTable() + + for (const tile of event.tiles) { + const chunkPosition = Converters.tilePositionToChunkPosition(tile.position) + tilesByChunk.set(chunkPosition, tile) + } + + for (const [chunkPos, tiles] of pairs(tilesByChunk)) { + + const entities: FactorioEntityData.Resource[] = [] + + for (const tile in tiles) { + const resources: FactorioEntityData.Resource[] = EntityUpdatesHandler.getTileResourceEntities(surface, chunkPos) + for (const resource of resources) { + entities[entities.length] = resource + } + } + + EntityUpdatesHandler.throttleResourceEntitiesUpdate( + Converters.eventNameString(event.name), + event.tick as Tick, + event.surface_index, + [chunkPos[0], chunkPos[1]], + entities, + ) + } + } + + + handleMinedEntityEvent( + event: OnPlayerMinedEntityEvent | OnRobotMinedEntityEvent, + ) { + EntityUpdatesHandler.throttleEntityUpdate(event, event.entity) + } + + + handleBuiltEntityEvent( + event: OnBuiltEntityEvent | OnRobotBuiltEntityEvent, + ) { + EntityUpdatesHandler.throttleEntityUpdate(event, event.created_entity) + } + + + handleChunkGeneratedEvent(event: OnChunkGeneratedEvent) { + const entities = EntityUpdatesHandler.getAreaResourceEntities(event.surface, event.area) + EntityUpdatesHandler.throttleResourceEntitiesUpdate( + Converters.eventNameString(event.name), + event.tick as Tick, + event.surface.index, + [event.position.x, event.position.y], + entities, + ) + } + + + private static throttleEntityUpdate(event: EntityUpdateEvent, entity: LuaEntity) { + + if (entity.unit_number == undefined) { + // ignore for now - I'm not sure how to track entities without a unit_number + return + } + const eventName = Converters.eventNameString(event.name) + + const entityUpdateKey: KafkatorioPacketData.MapChunkEntityUpdate["key"] = { + protoId: Converters.prototypeIdEntity(entity), + surfaceIndex: entity.surface.index, + chunkPosition: Converters.mapPositionToChunkPosition(entity.position) + } + + const entityUpdate: FactorioEntityData.Standard = { + type: FactorioEntityData.Type.Standard, + protoId: Converters.prototypeIdEntity(entity), + graphicsVariation: entity.graphics_variation, + health: entity.health, + isActive: entity.active, + isRotatable: entity.rotatable, + lastUser: entity.last_user?.index, + localisedDescription: null, + localisedName: null, + position: [entity.position.x, entity.position.y], + status: Converters.entityStatus(entity.status), + } + + const entityKey: string = `${entity.unit_number}` + + EventDataCache.throttle( + entityUpdateKey, + KafkatorioPacketData.Type.MapChunkEntityUpdate, + data => { + + data.events ??= {} + data.events[eventName] ??= [] + data.events[eventName].push(event.tick) + + data.distinctEntities ??= {} + data.distinctEntities[entityKey] = entityUpdate + } + ) + } + + + private static throttleResourceEntitiesUpdate( + eventName: EventName, + eventTick: Tick, + surfaceIndex: SurfaceIndex, + chunkPosition: MapChunkPosition, + entities: FactorioEntityData.Resource[], + ) { + + // first group by prototype ID + const entitiesByProtoId: { [protoId: PrototypeId]: FactorioEntityData.Resource[] } = {} + + for (const entity of entities) { + entitiesByProtoId[entity.protoId] ??= [] + entitiesByProtoId[entity.protoId].push(entity) + } + + for (const [protoId, resourceEntities] of pairs(entitiesByProtoId)) { + + // create an update for each prototype + + const entityUpdateKey: KafkatorioPacketData.MapChunkEntityUpdate["key"] = { + protoId: protoId, + surfaceIndex: surfaceIndex, + chunkPosition: [chunkPosition[0], chunkPosition[1]], + } + + EventDataCache.throttle( + entityUpdateKey, + KafkatorioPacketData.Type.MapChunkEntityUpdate, + data => { + + data.events ??= {} + data.events[eventName] ??= [] + data.events[eventName].push(eventTick) + + for (const entity of resourceEntities) { + const [x, y] = entity.position + const entityKey: string = `${x},${y}` + + data.distinctEntities ??= {} + data.distinctEntities[entityKey] = entity + } + } + ) + } + + } + + + /** Get all resources on a tile-position */ + private static getTileResourceEntities( + surface: LuaSurface, + mapPosition: MapPosition, + ): FactorioEntityData.Resource[] { + + const rawEntities = surface.find_entities_filtered({ + position: mapPosition, + collision_mask: "resource-layer", + } + ) + + const resources: FactorioEntityData.Resource[] = [] + + for (const rawEntity of rawEntities) { + const entity = Converters.convertResourceEntity(rawEntity) + if (entity != null) { + resources[resources.length] = entity + } + } + + return resources + } + + + /** Get all resources within a map-area */ + private static getAreaResourceEntities( + surface: LuaSurface, + area: BoundingBoxTable, + ): FactorioEntityData.Resource[] { + + const rawEntities = surface.find_entities_filtered({ + area: area, + collision_mask: "resource-layer", + } + ) + + const resources: FactorioEntityData.Resource[] = [] + + for (const rawEntity of rawEntities) { + const entity = Converters.convertResourceEntity(rawEntity) + if (entity != null) { + resources[resources.length] = entity + } + } + + return resources + } +} + +const EntityUpdates = new EntityUpdatesHandler() + +export default EntityUpdates + + +type EntityUpdateEvent = + | OnBuiltEntityEvent + + | OnEntityClonedEvent + | OnEntityDamagedEvent + | OnEntityDestroyedEvent + | OnEntityDiedEvent + | OnEntityLogisticSlotChangedEvent + | OnEntityRenamedEvent + | OnEntitySettingsPastedEvent + | OnEntitySpawnedEvent + + | OnPlayerMinedEntityEvent + | OnPlayerRepairedEntityEvent + | OnPlayerRotatedEntityEvent + + | OnRobotMinedEntityEvent + | OnRobotBuiltEntityEvent + + | OnPostEntityDiedEvent + | OnPreEntitySettingsPastedEvent + + | OnSelectedEntityChangedEvent + | OnTriggerCreatedEntityEvent diff --git a/modules/events-mod/src/main/typescript/main/events/handlers/MapChunkUpdateHandler.ts b/modules/events-mod/src/main/typescript/main/events/handlers/MapChunkUpdateHandler.ts new file mode 100644 index 0000000..fabbe7c --- /dev/null +++ b/modules/events-mod/src/main/typescript/main/events/handlers/MapChunkUpdateHandler.ts @@ -0,0 +1,242 @@ +import {Converters} from "../converters"; +import {isEventType} from "../eventTypeCheck"; +import { + KafkatorioPacketData, + MapChunkPosition, + MinedProduct, + PrototypeKey +} from "../../../generated/kafkatorio-schema"; +import EventUpdatesManager, {EventUpdates} from "../../cache/EventDataCache"; +import {MapChunkUpdateEvent, MapTileChangeEvent} from "../mapChunkUpdates"; +import PacketKey = EventUpdates.PacketKey; +import Type = MinedProduct.Type; + +type MapChunkTileUpdater = (data: KafkatorioPacketData.MapChunkTileUpdate) => void + + +class MapChunkUpdateHandler { + + handleChunkGeneratedEvent( + event: OnChunkGeneratedEvent, + expirationDurationTicks?: uint, + ) { + const tiles = event.surface.find_tiles_filtered({area: event.area}) + + MapChunkUpdateHandler.mapTilesUpdateDebounce( + event.surface, + Converters.convertMapTablePosition(event.position), + tiles, + event, + undefined, + expirationDurationTicks, + ) + } + + + handleBuiltTileEvent(event: OnPlayerBuiltTileEvent | OnRobotBuiltTileEvent) { + + const surface = game.get_surface(event.surface_index) + if (surface == undefined) { + const eventName = Converters.eventNameString(event.name) + log(`[handleBuiltTileEvent] undefined surface ${eventName}`) + return + } + + const tiles: TileRead[] = Converters.convertPlacedTiles(event.tile, event.tiles) + const groupedTiles = MapChunkUpdateHandler.groupTiles(tiles) + + for (const [chunkPos, tiles] of groupedTiles) { + MapChunkUpdateHandler.mapTilesUpdateDebounce( + surface, + chunkPos, + tiles, + event, + (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, + protoId: Converters.prototypeId(event.robot.type, event.robot.name), + } + return + } + // this line will not compile if the previous 'if' statements are not exhaustive + // noinspection UnnecessaryLocalVariableJS,JSUnusedLocalSymbols + const exhaustiveCheck: never = event + } + ) + ) + } + } + + + handleMinedTileEvent(event: OnPlayerMinedTileEvent | OnRobotMinedTileEvent) { + const surface = game.get_surface(event.surface_index) + if (surface == undefined) { + const eventName = Converters.eventNameString(event.name) + log(`[handleMinedTileEvent] undefined surface ${eventName}`) + return + } + + const tiles: TileRead[] = Converters.convertRemovedTiles(surface, event.tiles) + const groupedTiles = MapChunkUpdateHandler.groupTiles(tiles) + + for (const [chunkPos, tiles] of groupedTiles) { + + MapChunkUpdateHandler.mapTilesUpdateDebounce( + surface, + chunkPos, + tiles, + event, + (data => { + if (isEventType(event, defines.events.on_player_mined_tile)) { + data.player = event.player_index + return + } + if (isEventType(event, defines.events.on_robot_mined_tile)) { + data.robot = { + unitNumber: event.robot?.unit_number ?? null, + protoId: Converters.prototypeId(event.robot.type, event.robot.name), + } + return + } + // this line will not compile if the previous 'if' statements are not exhaustive + // noinspection UnnecessaryLocalVariableJS,JSUnusedLocalSymbols + const exhaustiveCheck: never = event + } + ) + ) + } + } + + + handleScriptSetTilesEvent(event: ScriptRaisedSetTilesEvent) { + + const surface = game.get_surface(event.surface_index) + if (surface == undefined) { + return + } + + const groupedTiles = MapChunkUpdateHandler.groupTiles(event.tiles) + + for (const [chunkPos, tiles] of groupedTiles) { + MapChunkUpdateHandler.mapTilesUpdateDebounce(surface, chunkPos, tiles, event) + } + } + + + handlePreChunkDeleted(event: OnPreChunkDeletedEvent) { + + const surface = game.get_surface(event.surface_index) + if (surface == undefined) { + return + } + + for (const position of event.positions) { + const key: PacketKey = { + surfaceIndex: surface.index, + chunkPosition: [position.x, position.y], + } + + EventUpdatesManager.debounce( + key, + KafkatorioPacketData.Type.MapChunkTileUpdate, + data => data.isDeleted = true, + 0, // deletion is important - emit ASAP + ) + } + } + + + private static mapTilesUpdateDebounce( + surface: LuaSurface | undefined, + chunkPosition: MapChunkPosition, + tiles: TileRead[], + event: MapChunkUpdateEvent | MapTileChangeEvent, + updater?: MapChunkTileUpdater, + expirationDurationTicks?: uint, + ) { + + if (surface == undefined) { + return + } + + const eventName = Converters.eventNameString(event.name) + + const key: KafkatorioPacketData.MapChunkTileUpdate["key"] = { + surfaceIndex: surface.index, + chunkPosition: chunkPosition, + } + + EventUpdatesManager.debounce( + key, + KafkatorioPacketData.Type.MapChunkTileUpdate, + data => { + + // tile dictionary update + if (data.tileDictionary == undefined) { + data.tileDictionary = { + tilesXY: {}, + protos: {}, + } + } + + let protosCount: uint = table_size(data.tileDictionary.protos) + for (const tile of tiles) { + const protoId = Converters.prototypeId("tile", tile.name) + + if (data.tileDictionary.protos[protoId] == null) { + + } + data.tileDictionary.protos[protoId] ??= protosCount++ as PrototypeKey + + const protoKey = data.tileDictionary.protos[protoId] + + const xString = `${tile.position.x}` + const yString = `${tile.position.y}` + + data.tileDictionary.tilesXY[xString] ??= {} + data.tileDictionary.tilesXY[xString][yString] = protoKey + } + + // events count update + data.events ??= {} + data.events[eventName] ??= [] + data.events[eventName].push(event.tick) + + // apply mutator + if (updater != undefined) { + updater(data) + } + }, + expirationDurationTicks, + ) + } + + + private static groupTiles(tiles: TileRead[]): Map { + + const mapChunkPositionToTiles = new Map() + for (const tile of tiles) { + const chunkPosition: MapChunkPosition = [ + math.floor((tile.position.x / 32)), + math.floor((tile.position.y / 32)), + ] + if (!mapChunkPositionToTiles.has(chunkPosition)) { + mapChunkPositionToTiles.set(chunkPosition, []) + } + mapChunkPositionToTiles.get(chunkPosition)?.push(tile) + } + return mapChunkPositionToTiles + } + + +} + + +const MapChunkUpdate = new MapChunkUpdateHandler() + +export default MapChunkUpdate diff --git a/modules/events-mod/src/main/typescript/main/events/handlers/PlayerUpdateHandler.ts b/modules/events-mod/src/main/typescript/main/events/handlers/PlayerUpdateHandler.ts new file mode 100644 index 0000000..d9a9a14 --- /dev/null +++ b/modules/events-mod/src/main/typescript/main/events/handlers/PlayerUpdateHandler.ts @@ -0,0 +1,75 @@ +import {KafkatorioPacketData} from "../../../generated/kafkatorio-schema"; +import {Converters} from "../converters"; +import EventUpdatesManager from "../../cache/EventDataCache"; + + +export type PlayerUpdater = (player: LuaPlayer, data: KafkatorioPacketData.PlayerUpdate) => void + + +export type PlayerUpdateEvent = + | OnPlayerJoinedGameEvent + | OnPlayerChangedPositionEvent + | OnPlayerChangedSurfaceEvent + | OnPlayerDiedEvent + | OnPlayerBannedEvent + | OnPlayerUnbannedEvent + | OnPlayerKickedEvent + | OnPrePlayerLeftGameEvent + | OnPlayerRemovedEvent + + +export class PlayerUpdateHandler { + + handleBannedEvent(event: OnPlayerBannedEvent | OnPlayerUnbannedEvent) { + this.playerUpdateThrottle( + event, + (player, data) => { + data.bannedReason = event.reason ?? null + Converters.playerOnlineInfo(player, data) + } + ) + } + + + playerUpdateThrottle( + event: PlayerUpdateEvent, + mutate: PlayerUpdater, + expirationDurationTicks: uint | undefined = undefined, + ) { + const playerIndex = event.player_index + if (playerIndex == undefined) { + return + } + + const eventName = Converters.eventNameString(event.name) + + EventUpdatesManager.throttle( + {index: playerIndex}, + KafkatorioPacketData.Type.PlayerUpdate, + data => { + const player = game.players[playerIndex] + if (player != undefined) { + mutate(player, data) + } + + data.events ??= {} + data.events[eventName] ??= [] + data.events[eventName].push(event.tick) + }, + expirationDurationTicks, + ) + } + + + playerUpdateImmediate( + event: PlayerUpdateEvent, + mutate: PlayerUpdater, + ) { + this.playerUpdateThrottle(event, mutate, 0) + } + +} + +const PlayerUpdates = new PlayerUpdateHandler() + +export default PlayerUpdates diff --git a/modules/events-mod/src/main/typescript/main/events/mapChunkUpdates.ts b/modules/events-mod/src/main/typescript/main/events/mapChunkUpdates.ts index e914a5e..ca3cda0 100644 --- a/modules/events-mod/src/main/typescript/main/events/mapChunkUpdates.ts +++ b/modules/events-mod/src/main/typescript/main/events/mapChunkUpdates.ts @@ -1,17 +1,5 @@ -import {isEventType} from "./eventTypeCheck"; -import {Converters} from "./converters"; -import EventUpdatesManager, {EventUpdates} from "../cache/EventDataCache"; -import { - KafkatorioPacketData, - MapChunkPosition, PrototypeId, - PrototypeKey, -} from "../../generated/kafkatorio-schema"; -import EntityUpdates from "./entityUpdates"; -import CacheKey = EventUpdates.PacketKey; -import Type = KafkatorioPacketData.Type; - - -type MapChunkTileUpdater = (data: KafkatorioPacketData.MapChunkTileUpdate) => void +import EntityUpdates from "./handlers/EntityUpdateHandler"; +import MapChunkUpdate from "./handlers/MapChunkUpdateHandler"; export type MapTileChangeEvent = @@ -29,242 +17,11 @@ export type MapChunkUpdateEvent = | OnPreChunkDeletedEvent -class MapChunkUpdateHandler { - - handleChunkGeneratedEvent( - event: OnChunkGeneratedEvent, - expirationDurationTicks?: uint, - ) { - const tiles = event.surface.find_tiles_filtered({area: event.area}) - - MapChunkUpdateHandler.mapTilesUpdateDebounce( - event.surface, - Converters.convertMapTablePosition(event.position), - tiles, - event, - undefined, - expirationDurationTicks, - ) - } - - - handleBuiltTileEvent(event: OnPlayerBuiltTileEvent | OnRobotBuiltTileEvent) { - - const surface = game.get_surface(event.surface_index) - if (surface == undefined) { - const eventName = Converters.eventNameString(event.name) - log(`[handleBuiltTileEvent] undefined surface ${eventName}`) - return - } - - const tiles: TileRead[] = Converters.convertPlacedTiles(event.tile, event.tiles) - const groupedTiles = MapChunkUpdateHandler.groupTiles(tiles) - - for (const [chunkPos, tiles] of groupedTiles) { - MapChunkUpdateHandler.mapTilesUpdateDebounce( - surface, - chunkPos, - tiles, - event, - (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, - protoId: Converters.prototypeId(event.robot.type, event.robot.name), - } - return - } - // this line will not compile if the previous 'if' statements are not exhaustive - // noinspection UnnecessaryLocalVariableJS,JSUnusedLocalSymbols - const exhaustiveCheck: never = event - } - ) - ) - } - } - - - handleMinedTileEvent(event: OnPlayerMinedTileEvent | OnRobotMinedTileEvent) { - const surface = game.get_surface(event.surface_index) - if (surface == undefined) { - const eventName = Converters.eventNameString(event.name) - log(`[handleMinedTileEvent] undefined surface ${eventName}`) - return - } - - const tiles: TileRead[] = Converters.convertRemovedTiles(surface, event.tiles) - const groupedTiles = MapChunkUpdateHandler.groupTiles(tiles) - - for (const [chunkPos, tiles] of groupedTiles) { - - MapChunkUpdateHandler.mapTilesUpdateDebounce( - surface, - chunkPos, - tiles, - event, - (data => { - if (isEventType(event, defines.events.on_player_mined_tile)) { - data.player = event.player_index - return - } - if (isEventType(event, defines.events.on_robot_mined_tile)) { - data.robot = { - unitNumber: event.robot?.unit_number ?? null, - protoId: Converters.prototypeId(event.robot.type, event.robot.name), - } - return - } - // this line will not compile if the previous 'if' statements are not exhaustive - // noinspection UnnecessaryLocalVariableJS,JSUnusedLocalSymbols - const exhaustiveCheck: never = event - } - ) - ) - } - } - - - handleScriptSetTilesEvent(event: ScriptRaisedSetTilesEvent) { - - const surface = game.get_surface(event.surface_index) - if (surface == undefined) { - return - } - - const groupedTiles = MapChunkUpdateHandler.groupTiles(event.tiles) - - for (const [chunkPos, tiles] of groupedTiles) { - MapChunkUpdateHandler.mapTilesUpdateDebounce(surface, chunkPos, tiles, event) - } - } - - - handlePreChunkDeleted(event: OnPreChunkDeletedEvent) { - - const surface = game.get_surface(event.surface_index) - if (surface == undefined) { - return - } - - for (const position of event.positions) { - const key: CacheKey = { - surfaceIndex: surface.index, - chunkPosition: [position.x, position.y], - } - - EventUpdatesManager.debounce( - key, - Type.MapChunkTileUpdate, - data => data.isDeleted = true, - 0, // deletion is important - emit ASAP - ) - } - } - - - private static mapTilesUpdateDebounce( - surface: LuaSurface | undefined, - chunkPosition: MapChunkPosition, - tiles: TileRead[], - event: MapChunkUpdateEvent | MapTileChangeEvent, - updater?: MapChunkTileUpdater, - expirationDurationTicks?: uint, - ) { - - if (surface == undefined) { - return - } - - const eventName = Converters.eventNameString(event.name) - - const key: KafkatorioPacketData.MapChunkTileUpdate["key"] = { - surfaceIndex: surface.index, - chunkPosition: chunkPosition, - } - - EventUpdatesManager.debounce( - key, - Type.MapChunkTileUpdate, - data => { - - // tile dictionary update - if (data.tileDictionary == undefined) { - data.tileDictionary = { - tilesXY: {}, - protos: {}, - } - } - - let protosCount: uint = table_size(data.tileDictionary.protos) - for (const tile of tiles) { - const protoId = Converters.prototypeId("tile", tile.name) - - if (data.tileDictionary.protos[protoId] == null) { - - } - data.tileDictionary.protos[protoId] ??= protosCount++ as PrototypeKey - - const protoKey = data.tileDictionary.protos[protoId] - - const xString = `${tile.position.x}` - const yString = `${tile.position.y}` - - data.tileDictionary.tilesXY[xString] ??= {} - data.tileDictionary.tilesXY[xString][yString] = protoKey - } - - // events count update - data.events ??= {} - data.events[eventName] ??= [] - data.events[eventName].push(event.tick) - - // apply mutator - if (updater != undefined) { - updater(data) - } - }, - expirationDurationTicks, - ) - } - - - private static groupTiles(tiles: TileRead[]): Map { - - const mapChunkPositionToTiles = new Map() - for (const tile of tiles) { - const chunkPosition: MapChunkPosition = [ - math.floor((tile.position.x / 32)), - math.floor((tile.position.y / 32)), - ] - if (!mapChunkPositionToTiles.has(chunkPosition)) { - mapChunkPositionToTiles.set(chunkPosition, []) - } - mapChunkPositionToTiles.get(chunkPosition)?.push(tile) - } - return mapChunkPositionToTiles - } - - -} - - -const MapChunkUpdate = new MapChunkUpdateHandler() - -export default MapChunkUpdate - - -script.on_event( - defines.events.on_chunk_generated, - (e: OnChunkGeneratedEvent) => { - log(`on_chunk_generated ${e.tick}`) - MapChunkUpdate.handleChunkGeneratedEvent(e) - EntityUpdates.handleChunkGeneratedEvent(e) - } -) +script.on_event(defines.events.on_chunk_generated, (e: OnChunkGeneratedEvent) => { + log(`on_chunk_generated ${e.tick}`) + MapChunkUpdate.handleChunkGeneratedEvent(e) + EntityUpdates.handleChunkGeneratedEvent(e) +}) // script.on_event( diff --git a/modules/events-mod/src/main/typescript/main/events/playerUpdates.ts b/modules/events-mod/src/main/typescript/main/events/playerUpdates.ts index 18b46f2..d20afb4 100644 --- a/modules/events-mod/src/main/typescript/main/events/playerUpdates.ts +++ b/modules/events-mod/src/main/typescript/main/events/playerUpdates.ts @@ -1,61 +1,7 @@ import {Converters} from "./converters"; -import EventUpdatesManager from "../cache/EventDataCache"; import {ForceIndex, KafkatorioPacketData, PlayerUpdateKey} from "../../generated/kafkatorio-schema"; import packetEmitter from "../PacketEmitter"; -import Type = KafkatorioPacketData.Type; - - -type PlayerUpdater = (player: LuaPlayer, data: KafkatorioPacketData.PlayerUpdate) => void - - -type PlayerUpdateEvent = - | OnPlayerJoinedGameEvent - | OnPlayerChangedPositionEvent - | OnPlayerChangedSurfaceEvent - | OnPlayerDiedEvent - | OnPlayerBannedEvent - | OnPlayerUnbannedEvent - | OnPlayerKickedEvent - | OnPrePlayerLeftGameEvent - | OnPlayerRemovedEvent - - -function playerUpdateThrottle( - event: PlayerUpdateEvent, - mutate: PlayerUpdater, - expirationDurationTicks: uint | undefined = undefined, -) { - const playerIndex = event.player_index - if (playerIndex == undefined) { - return - } - - const eventName = Converters.eventNameString(event.name) - - EventUpdatesManager.throttle( - {index: playerIndex }, - Type.PlayerUpdate, - data => { - const player = game.players[playerIndex] - if (player != undefined) { - mutate(player, data) - } - - data.events ??= {} - data.events[eventName] ??= [] - data.events[eventName].push(event.tick) - }, - expirationDurationTicks, - ) -} - - -function playerUpdateImmediate( - event: PlayerUpdateEvent, - mutate: PlayerUpdater, -) { - playerUpdateThrottle(event, mutate, 0) -} +import PlayerUpdates from "./handlers/PlayerUpdateHandler"; // function playerUpdateDebounce(playerIndex: uint, mutate: PlayerUpdater) { @@ -68,154 +14,122 @@ function playerUpdateImmediate( // ) // } -function playerOnlineInfo(player: LuaPlayer, data: KafkatorioPacketData.PlayerUpdate) { - 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, data) => { - data.isAdmin = player.admin - data.characterUnitNumber = player.character?.unit_number ?? null - data.chatColour = Converters.mapColour(player.chat_color) - data.colour = Converters.mapColour(player.color) - data.forceIndex = player.force.index as ForceIndex - data.name = player.name - data.isShowOnMap = player.show_on_map - data.isSpectator = player.spectator - data.surfaceIndex = player.surface.index - data.tag = player.tag - playerOnlineInfo(player, data) - } - ) - } -) - - -script.on_event( - defines.events.on_player_changed_position, - (e: OnPlayerChangedPositionEvent) => { - playerUpdateThrottle( - e, - (player, data) => { - data.position = [player.position.x, player.position.y] - } - ) - } -) - - -script.on_event( - defines.events.on_player_changed_surface, - (e: OnPlayerChangedSurfaceEvent) => { - playerUpdateThrottle( - e, - (player, data) => { - data.position = [player.position.x, player.position.y] - data.surfaceIndex = player.surface.index - } - ) - } -) - - -script.on_event( - defines.events.on_player_died, - (e: OnPlayerDiedEvent) => { - playerUpdateThrottle( - e, - (player, data) => { - data.ticksToRespawn = player.ticks_to_respawn ?? null - playerOnlineInfo(player, data) - if (e.cause != undefined) { - data.diedCause = { - unitNumber: e.cause.unit_number ?? null, - protoId: Converters.prototypeId(e.cause.type, e.cause.name), - } - } - } - ) - } -) - - -script.on_event(defines.events.on_player_banned, handleBannedEvent) -script.on_event(defines.events.on_player_unbanned, handleBannedEvent) - -function handleBannedEvent(event: OnPlayerBannedEvent | OnPlayerUnbannedEvent) { - playerUpdateThrottle( - event, +script.on_event(defines.events.on_player_joined_game, (e: OnPlayerJoinedGameEvent) => { + PlayerUpdates.playerUpdateThrottle( + e, (player, data) => { - data.bannedReason = event.reason ?? null - playerOnlineInfo(player, data) + data.isAdmin = player.admin + data.characterUnitNumber = player.character?.unit_number ?? null + data.chatColour = Converters.mapColour(player.chat_color) + data.colour = Converters.mapColour(player.color) + data.forceIndex = player.force.index as ForceIndex + data.name = player.name + data.isShowOnMap = player.show_on_map + data.isSpectator = player.spectator + data.surfaceIndex = player.surface.index + data.tag = player.tag + Converters.playerOnlineInfo(player, data) } ) -} +}) -script.on_event( - defines.events.on_player_kicked, - (event: OnPlayerKickedEvent) => { - log(`on_player_kicked ${event.tick} ${event.name}`) - playerUpdateImmediate( - event, - (player, data) => { - data.kickedReason = event.reason ?? null - playerOnlineInfo(player, data) +script.on_event(defines.events.on_player_changed_position, (e: OnPlayerChangedPositionEvent) => { + PlayerUpdates.playerUpdateThrottle( + e, + (player, data) => { + data.position = [player.position.x, player.position.y] + } + ) +}) + + +script.on_event(defines.events.on_player_changed_surface, (e: OnPlayerChangedSurfaceEvent) => { + PlayerUpdates.playerUpdateThrottle( + e, + (player, data) => { + data.position = [player.position.x, player.position.y] + data.surfaceIndex = player.surface.index + } + ) +}) + + +script.on_event(defines.events.on_player_died, (e: OnPlayerDiedEvent) => { + PlayerUpdates.playerUpdateThrottle( + e, + (player, data) => { + data.ticksToRespawn = player.ticks_to_respawn ?? null + Converters.playerOnlineInfo(player, data) + if (e.cause != undefined) { + data.diedCause = { + unitNumber: e.cause.unit_number ?? null, + protoId: Converters.prototypeId(e.cause.type, e.cause.name), } - ) - } -) + } + } + ) +}) + + +script.on_event(defines.events.on_player_banned, (event: OnPlayerBannedEvent) => { + PlayerUpdates.handleBannedEvent(event) +}) +script.on_event(defines.events.on_player_unbanned, (event: OnPlayerBannedEvent) => { + PlayerUpdates.handleBannedEvent(event) +}) + + +script.on_event(defines.events.on_player_kicked, (event: OnPlayerKickedEvent) => { + log(`on_player_kicked ${event.tick} ${event.name}`) + PlayerUpdates.playerUpdateImmediate( + event, + (player, data) => { + data.kickedReason = event.reason ?? null + Converters.playerOnlineInfo(player, data) + } + ) +}) + + +script.on_event(defines.events.on_pre_player_left_game, (event: OnPrePlayerLeftGameEvent) => { + log(`on_pre_player_left_game ${event.tick} ${event.name}`) + + const playerUpdateKey: PlayerUpdateKey = { + index: event.player_index, + } + + const playerUpdate: KafkatorioPacketData.PlayerUpdate = { + type: KafkatorioPacketData.Type.PlayerUpdate, + key: playerUpdateKey, + disconnectReason: disconnectReasons.get(event.reason) + } + + packetEmitter.emitKeyedPacket(playerUpdate) + + // playerUpdateImmediate( + // event, + // (player, data) => { + // data.disconnectReason = disconnectReasons.get(event.reason) + // playerOnlineInfo(player, data) + // } + // ) +}) + +script.on_event(defines.events.on_player_removed, (event: OnPlayerRemovedEvent) => { + log(`on_player_removed ${event.tick} ${event.name}`) + PlayerUpdates.playerUpdateImmediate( + event, + (player, data) => { + data.isRemoved = true + Converters.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, - (event: OnPrePlayerLeftGameEvent) => { - log(`on_pre_player_left_game ${event.tick} ${event.name}`) - - const playerUpdateKey: PlayerUpdateKey = { - index: event.player_index , - } - - const playerUpdate: KafkatorioPacketData.PlayerUpdate = { - type: KafkatorioPacketData.Type.PlayerUpdate, - key: playerUpdateKey, - disconnectReason: disconnectReasons.get(event.reason) - } - - packetEmitter.emitKeyedPacket(playerUpdate) - - // playerUpdateImmediate( - // event, - // (player, data) => { - // data.disconnectReason = disconnectReasons.get(event.reason) - // playerOnlineInfo(player, data) - // } - // ) - } -) - -script.on_event( - defines.events.on_player_removed, - (event: OnPlayerRemovedEvent) => { - log(`on_player_removed ${event.tick} ${event.name}`) - playerUpdateImmediate( - event, - (player, data) => { - data.isRemoved = true - playerOnlineInfo(player, data) - } - ) - } -) diff --git a/modules/events-mod/src/main/typescript/main/events/prototypeUpdates.ts b/modules/events-mod/src/main/typescript/main/events/prototypeUpdates.ts index b424383..6d17469 100644 --- a/modules/events-mod/src/main/typescript/main/events/prototypeUpdates.ts +++ b/modules/events-mod/src/main/typescript/main/events/prototypeUpdates.ts @@ -1,33 +1,48 @@ import PacketEmitter from "../PacketEmitter"; -import {FactorioPrototype, KafkatorioPacketData} from "../../generated/kafkatorio-schema"; +import { + EntityItemGroup, + FactorioPrototype, + KafkatorioPacketData +} from "../../generated/kafkatorio-schema"; import {Converters} from "./converters"; -import PrototypesUpdate = KafkatorioPacketData.PrototypesUpdate; + + +type PrototypesByType = LuaTable export function emitPrototypes() { - const data: PrototypesUpdate = { - prototypes: prototypeUpdates(), - type: KafkatorioPacketData.Type.PrototypesUpdate, + const mapTileProtos: PrototypesByType = getMapTilePrototypes() + emit(mapTileProtos) + + + game.item_group_prototypes + game.item_subgroup_prototypes + + + const entityProtos: PrototypesByType = getEntityPrototypes() + emit(entityProtos) +} + + +function emit(protosByType: PrototypesByType) { + for (const [, protos] of pairs(protosByType)) { + PacketEmitter.emitInstantPacket({ + type: KafkatorioPacketData.Type.PrototypesUpdate, + prototypes: protos, + }) + } +} + + +function getMapTilePrototypes(): PrototypesByType { + const tiles = new LuaTable() + if (!tiles.has("tile")) { + tiles.set("tile", []) } - PacketEmitter.emitInstantPacket(data) -} - - -function prototypeUpdates(): FactorioPrototype[] { - let prototypes: FactorioPrototype[] = [] - - prototypes.push(...getMapTilePrototypes()) - - return prototypes -} - - -function getMapTilePrototypes(): FactorioPrototype.MapTile[] { - let tiles: FactorioPrototype.MapTile[] = [] for (const [, tile] of game.tile_prototypes) { - tiles.push({ + tiles.get("tile").push({ type: FactorioPrototype.Type.MapTile, protoId: Converters.prototypeId("tile", tile.name), @@ -42,19 +57,59 @@ function getMapTilePrototypes(): FactorioPrototype.MapTile[] { } -// function getEntityPrototypes(): FactorioPrototype.MapTile[] { -// let tiles: FactorioPrototype.MapTile[] = [] -// for (const [, tile] of game.tile_prototypes) { -// tiles.push({ -// type: FactorioPrototype.Type.MapTile, -// -// name: tile.name, -// order: tile.order, -// layer: tile.layer, -// collisionMasks: convertCollisionMaskToNames(tile.collision_mask), -// mapColour: Converters.mapColour(tile.map_color), -// canBeMined: tile.mineable_properties.minable, -// }) -// } -// return tiles -// } +function getEntityPrototypes(): PrototypesByType { + const protos = new LuaTable() + + for (const [, entity] of game.entity_prototypes) { + const key: string = `${entity.group.name}/${entity.subgroup.name}` + + if (!protos.has(key)) { + protos.set(key, []) + } + + const entityProto: FactorioPrototype.Entity = { + type: FactorioPrototype.Type.Entity, + protoId: Converters.prototypeId(entity.type, entity.name), + + group: convertItemGroup(entity.group), + subgroup: convertItemSubgroup(entity.subgroup), + + isBuilding: entity.is_building, + isEntityWithOwner: entity.is_entity_with_owner, + isMilitaryTarget: entity.is_military_target, + maxHealth: entity.max_health, + } + + if (entity.map_color != undefined) { + entityProto.mapColour = Converters.mapColour(entity.map_color) + } + if (entity.friendly_map_color != undefined) { + entityProto.mapColourFriend = Converters.mapColour(entity.friendly_map_color) + } + if (entity.enemy_map_color != undefined) { + entityProto.mapColourEnemy = Converters.mapColour(entity.enemy_map_color) + } + entityProto.miningProperties = Converters.miningProperties(entity.mineable_properties) + + protos.get(key).push(entityProto) + } + return protos +} + + +function convertItemGroup(itemGroup: LuaGroup): EntityItemGroup { + return { + name: itemGroup.name, + type: itemGroup.type, + parentName: null, + } +} + + +function convertItemSubgroup(itemGroup: LuaGroup): EntityItemGroup { + return { + name: itemGroup.name, + type: itemGroup.type, + parentName: itemGroup.group?.name, + } +} diff --git a/modules/events-mod/src/main/typescript/main/events/registerEventListeners.ts b/modules/events-mod/src/main/typescript/main/events/registerEventListeners.ts index 095c3a2..54ee97e 100644 --- a/modules/events-mod/src/main/typescript/main/events/registerEventListeners.ts +++ b/modules/events-mod/src/main/typescript/main/events/registerEventListeners.ts @@ -3,7 +3,7 @@ import {isEventType} from "./eventTypeCheck"; import {Converters} from "./converters"; import {handleSurfaceUpdate} from "./surfaceUpdates"; import EventCacheService from "../cache/EventDataCache"; -import MapChunkUpdate from "./mapChunkUpdates"; +import MapChunkUpdate from "./handlers/MapChunkUpdateHandler"; script.on_event( diff --git a/modules/events-mod/src/main/typescript/main/events/resourceEntityUpdates.ts b/modules/events-mod/src/main/typescript/main/events/resourceEntityUpdates.ts deleted file mode 100644 index 5955137..0000000 --- a/modules/events-mod/src/main/typescript/main/events/resourceEntityUpdates.ts +++ /dev/null @@ -1,99 +0,0 @@ -// import {isEventType} from "./eventTypeCheck"; -// import {Converters} from "./converters"; -// import EventUpdatesManager, {EventUpdates} from "../cache/EventDataCache"; -// import { -// KafkatorioPacketData, -// MapChunkPosition, -// PrototypeKey, -// } from "../../generated/kafkatorio-schema"; -// import CacheKey = EventUpdates.PacketKey; -// import Type = KafkatorioPacketData.Type; -// -// -// export class ResourceEntityUpdatesHandler { -// -// -// handleChunkGeneratedEvent( -// event: OnChunkGeneratedEvent, -// expirationDurationTicks?: uint, -// ) { -// const resourceEntities = this.getAreaResourceEntities(event.surface, event.area) -// -// mapTilesUpdateDebounce( -// event.surface, -// Converters.convertMapTablePosition(event.position), -// tiles, -// event, -// undefined, -// expirationDurationTicks, -// ) -// } -// -// -// private resourceEntityUpdatesThrottle( -// surface: LuaSurface | undefined, -// chunkPosition: MapChunkPosition, -// tiles: TileRead[], -// event: MapTileUpdateEvent, -// updater?: MapChunkUpdater, -// expirationDurationTicks?: uint, -// ) { -// -// if (surface == undefined) { -// return -// } -// -// const eventName = Converters.eventNameString(event.name) -// -// const key: KafkatorioPacketData.ResourceEntitiesUpdate["key"] = { -// surfaceIndex: surface.index as SurfaceIndex, -// chunkPosition: chunkPosition, -// } -// -// EventUpdatesManager.throttle( -// key, -// Type.MapChunkUpdate, -// data => { -// -// // tile dictionary update -// if (data.tileDictionary == undefined) { -// data.tileDictionary = { -// tilesXY: {}, -// protos: {}, -// } -// } -// -// let protosCount: uint = table_size(data.tileDictionary.protos) -// for (const tile of tiles) { -// const tileName = tile.name as PrototypeIdMapTile -// const protoKey = protosCount++ as PrototypeKey -// data.tileDictionary.protos[tileName] ??= protoKey -// -// const xString = `${tile.position.x}` -// const yString = `${tile.position.y}` -// -// data.tileDictionary.tilesXY[xString] ??= {} -// data.tileDictionary.tilesXY[xString][yString] = protoKey -// } -// -// // events count update -// data.events ??= {} -// data.events[eventName] ??= [] -// data.events[eventName].push(event.tick) -// -// // apply mutator -// if (updater != undefined) { -// updater(data) -// } -// }, -// expirationDurationTicks, -// ) -// } -// -// } -// -// -// -// const ResourceEntityUpdates = new ResourceEntityUpdatesHandler() -// -// export default ResourceEntityUpdates diff --git a/modules/events-server/src/main/kotlin/dev/adamko/kafkatorio/server/processor/topology/colourMapChunks.kt b/modules/events-server/src/main/kotlin/dev/adamko/kafkatorio/server/processor/topology/colourMapChunks.kt index b4a7528..c7f02cd 100644 --- a/modules/events-server/src/main/kotlin/dev/adamko/kafkatorio/server/processor/topology/colourMapChunks.kt +++ b/modules/events-server/src/main/kotlin/dev/adamko/kafkatorio/server/processor/topology/colourMapChunks.kt @@ -211,16 +211,15 @@ fun KTable>.streamMapChunkColou val pid = "$pid.output-chunk.${chunkSize.name}" toStream("$pid.stream") - .filter("$pid.filter-tiles-not-empty") { _, v -> - !v?.map.isNullOrEmpty() + .filter("$pid.filter-tiles-not-empty") { _, chunkTiles -> + !chunkTiles?.map.isNullOrEmpty() } - .mapValues("$pid.map-not-null") { _, v -> - requireNotNull(v) + .mapValues("$pid.map-not-null") { _, chunkTiles -> + requireNotNull(chunkTiles) } - .peek("$pid.print-group-result") { _, v -> - println("Grouping map tiles result: ${v.chunkId} / ${v.map.size}") - } - .to( + .peek("$pid.print-group-result") { _, chunkTiles -> + println("Grouping map tiles result: ${chunkTiles.chunkId} / size:${chunkTiles.map.size}") + }.to( outputTopic, producedAs( "$pid.grouped-map-chunks",