From 8d7de7fde7ce8d6412a36c6c9248fa7d8cf0050c Mon Sep 17 00:00:00 2001 From: phosit Date: Tue, 23 Sep 2025 16:55:45 +0200 Subject: [PATCH] Remove usage of entityObj in BuildManager When destroying a builder it might not be known anymore what it was able to build. Now the entityIDs of the builder is stores. So that it can easily be looked up and removed. --- .../simulation/ai/petra/buildManager.js | 86 +++++++++---------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/binaries/data/mods/public/simulation/ai/petra/buildManager.js b/binaries/data/mods/public/simulation/ai/petra/buildManager.js index 801dec9e01..9e87bcf199 100644 --- a/binaries/data/mods/public/simulation/ai/petra/buildManager.js +++ b/binaries/data/mods/public/simulation/ai/petra/buildManager.js @@ -10,40 +10,38 @@ import { aiWarn } from "simulation/ai/common-api/utils.js"; export function BuildManager() { // List of buildings we have builders for, with number of possible builders. - this.builderCounters = new Map(); + this.builders = new Map(); // List of buildings we can't currently build (because no room, no builder or whatever), // with time we should wait before trying again to build it. this.unbuildables = new Map(); } +function addBuilder(builders, civ, entity) +{ + for (const buildable of entity.buildableEntities(civ)) + { + if (!builders.has(buildable)) + builders.set(buildable, []); + builders.get(buildable).push(entity.id()); + } +} + +function removeBuilder(builders, entityId) +{ + for (const entities of builders.values()) + { + const entityIndex = entities.indexOf(entityId); + if (entityIndex !== -1) + entities.splice(entityIndex, 1); + } +} + /** Initialization at start of game */ BuildManager.prototype.init = function(gameState) { const civ = gameState.getPlayerCiv(); for (const ent of gameState.getOwnUnits().values()) - this.incrementBuilderCounters(civ, ent, 1); -}; - -BuildManager.prototype.incrementBuilderCounters = function(civ, ent, increment) -{ - for (const buildable of ent.buildableEntities(civ)) - { - if (this.builderCounters.has(buildable)) - { - const count = this.builderCounters.get(buildable) + increment; - if (count < 0) - { - aiWarn(" Petra error in incrementBuilderCounters for " + buildable + - " with count < 0"); - continue; - } - this.builderCounters.set(buildable, count); - } - else if (increment > 0) - this.builderCounters.set(buildable, increment); - else - aiWarn(" Petra error in incrementBuilderCounters for " + buildable + " not yet set"); - } + addBuilder(this.builders, civ, ent); }; /** Update the builders counters */ @@ -58,30 +56,25 @@ BuildManager.prototype.checkEvents = function(gameState, events) continue; const ent = gameState.getEntityById(evt.entity); if (ent && ent.isOwn(PlayerID) && ent.hasClass("Unit")) - this.incrementBuilderCounters(civ, ent, 1); + addBuilder(this.builders, civ, ent); } for (const evt of events.Destroy) - { - if (events.Create.some(e => e.entity == evt.entity) || !evt.entityObj) - continue; - const ent = evt.entityObj; - if (ent && ent.isOwn(PlayerID) && ent.hasClass("Unit")) - this.incrementBuilderCounters(civ, ent, -1); - } + removeBuilder(this.builders, evt.entity); for (const evt of events.OwnershipChanged) // capture events { - let increment; if (evt.from == PlayerID) - increment = -1; - else if (evt.to == PlayerID) - increment = 1; - else + { + removeBuilder(this.builders, evt.entity); continue; + } + else if (evt.to != PlayerID) + continue; + const ent = gameState.getEntityById(evt.entity); - if (ent && ent.hasClass("Unit")) - this.incrementBuilderCounters(civ, ent, increment); + if (ent?.hasClass("Unit")) + addBuilder(this.builders, civ, ent); } for (const evt of events.ValueModification) @@ -92,10 +85,10 @@ BuildManager.prototype.checkEvents = function(gameState, events) // Unfortunately there really is not an easy way to determine the changes // at this stage, so we simply have to dump the cache. - this.builderCounters = new Map(); + this.builders = new Map(); for (const ent of gameState.getOwnUnits().values()) - this.incrementBuilderCounters(civ, ent, 1); + addBuilder(this.builders, civ, ent); } }; @@ -106,9 +99,9 @@ BuildManager.prototype.checkEvents = function(gameState, events) BuildManager.prototype.findStructuresByFilter = function(gameState, filter) { const result = []; - for (const [templateName, count] of this.builderCounters) + for (const [templateName, entities] of this.builders) { - if (!count || gameState.isTemplateDisabled(templateName)) + if (!entities.length || gameState.isTemplateDisabled(templateName)) continue; const template = gameState.getTemplate(templateName); if (!template || !template.available(gameState)) @@ -130,8 +123,8 @@ BuildManager.prototype.findStructureWithClass = function(gameState, classes) BuildManager.prototype.hasBuilder = function(template) { - const numBuilders = this.builderCounters.get(template); - return numBuilders && numBuilders > 0; + const numBuilders = this.builders.get(template); + return numBuilders && numBuilders.length > 0; }; BuildManager.prototype.isUnbuildable = function(gameState, template) @@ -182,7 +175,7 @@ BuildManager.prototype.resetMissingRoom = function(gameState) BuildManager.prototype.Serialize = function() { return { - "builderCounters": this.builderCounters, + "builders": this.builders, "unbuildables": this.unbuildables }; }; @@ -192,3 +185,4 @@ BuildManager.prototype.Deserialize = function(data) for (const key in data) this[key] = data[key]; }; +