emit entity prototypes
- mod: refactor event handlers to separate files - lib: update models for prototypes
This commit is contained in:
parent
4510ec4a6e
commit
80eb001bbf
27 changed files with 1570 additions and 1437 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<string>(
|
||||
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,
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<defines.entity_status, EntityStatus> = {
|
||||
//@formatter:off
|
||||
[ defines.entity_status.cant_divide_segments ]: EntityStatus.CANT_DIVIDE_SEGMENTS,
|
||||
|
|
|
|||
|
|
@ -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<MapChunkPosition, OldTileAndPosition> = new LuaTable<MapChunkPosition, OldTileAndPosition>()
|
||||
|
||||
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<KafkatorioPacketData.MapChunkEntityUpdate>(
|
||||
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<KafkatorioPacketData.MapChunkEntityUpdate>(
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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<string>(
|
||||
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
|
||||
|
|
@ -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<MapChunkPosition, OldTileAndPosition> = new LuaTable<MapChunkPosition, OldTileAndPosition>()
|
||||
|
||||
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<KafkatorioPacketData.MapChunkEntityUpdate>(
|
||||
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<KafkatorioPacketData.MapChunkEntityUpdate>(
|
||||
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
|
||||
|
|
@ -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<KafkatorioPacketData.MapChunkTileUpdate> = {
|
||||
surfaceIndex: surface.index,
|
||||
chunkPosition: [position.x, position.y],
|
||||
}
|
||||
|
||||
EventUpdatesManager.debounce<KafkatorioPacketData.MapChunkTileUpdate>(
|
||||
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<KafkatorioPacketData.MapChunkTileUpdate>(
|
||||
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<MapChunkPosition, TileRead[]> {
|
||||
|
||||
const mapChunkPositionToTiles = new Map<MapChunkPosition, TileRead[]>()
|
||||
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
|
||||
|
|
@ -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<KafkatorioPacketData.PlayerUpdate>(
|
||||
{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
|
||||
|
|
@ -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<KafkatorioPacketData.MapChunkTileUpdate> = {
|
||||
surfaceIndex: surface.index,
|
||||
chunkPosition: [position.x, position.y],
|
||||
}
|
||||
|
||||
EventUpdatesManager.debounce<KafkatorioPacketData.MapChunkTileUpdate>(
|
||||
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<KafkatorioPacketData.MapChunkTileUpdate>(
|
||||
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<MapChunkPosition, TileRead[]> {
|
||||
|
||||
const mapChunkPositionToTiles = new Map<MapChunkPosition, TileRead[]>()
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -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<KafkatorioPacketData.PlayerUpdate>(
|
||||
{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<defines.disconnect_reason, keyof typeof defines.disconnect_reason>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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<T extends FactorioPrototype> = LuaTable<string, T[]>
|
||||
|
||||
|
||||
export function emitPrototypes() {
|
||||
|
||||
const data: PrototypesUpdate = {
|
||||
prototypes: prototypeUpdates(),
|
||||
type: KafkatorioPacketData.Type.PrototypesUpdate,
|
||||
const mapTileProtos: PrototypesByType<FactorioPrototype.MapTile> = getMapTilePrototypes()
|
||||
emit(mapTileProtos)
|
||||
|
||||
|
||||
game.item_group_prototypes
|
||||
game.item_subgroup_prototypes
|
||||
|
||||
|
||||
const entityProtos: PrototypesByType<FactorioPrototype.Entity> = getEntityPrototypes()
|
||||
emit(entityProtos)
|
||||
}
|
||||
|
||||
|
||||
function emit<T extends FactorioPrototype>(protosByType: PrototypesByType<T>) {
|
||||
for (const [, protos] of pairs(protosByType)) {
|
||||
PacketEmitter.emitInstantPacket({
|
||||
type: KafkatorioPacketData.Type.PrototypesUpdate,
|
||||
prototypes: protos,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getMapTilePrototypes(): PrototypesByType<FactorioPrototype.MapTile> {
|
||||
const tiles = new LuaTable<string, FactorioPrototype.MapTile[]>()
|
||||
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<FactorioPrototype.Entity> {
|
||||
const protos = new LuaTable<string, FactorioPrototype.Entity[]>()
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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<KafkatorioPacketData.ResourceEntitiesUpdate>(
|
||||
// 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue