Further improve belt placement performance

This commit is contained in:
tobspr 2020-06-24 20:36:15 +02:00
parent 12927ec0ff
commit 7b15a256b5
1 changed files with 30 additions and 22 deletions

View File

@ -63,10 +63,10 @@ export class BeltSystem extends GameSystemWithFilter {
this.root.signals.entityAdded.add(this.updateSurroundingBeltPlacement, this); this.root.signals.entityAdded.add(this.updateSurroundingBeltPlacement, this);
this.root.signals.entityDestroyed.add(this.updateSurroundingBeltPlacement, this); this.root.signals.entityDestroyed.add(this.updateSurroundingBeltPlacement, this);
this.root.signals.postLoadHook.add(this.computeBeltCache, this);
this.cacheNeedsUpdate = true; /** @type {Rectangle} */
/** @type {Rectangle[]} */ this.areaToRecompute = null;
this.smallUpdateAreas = [];
} }
/** /**
@ -92,6 +92,10 @@ export class BeltSystem extends GameSystemWithFilter {
// Compute affected area // Compute affected area
const originalRect = staticComp.getTileSpaceBounds(); const originalRect = staticComp.getTileSpaceBounds();
const affectedArea = originalRect.expandedInAllDirections(1); const affectedArea = originalRect.expandedInAllDirections(1);
// Store if anything got changed, if so we need to queue a recompute
let anythingChanged = false;
for (let x = affectedArea.x; x < affectedArea.right(); ++x) { for (let x = affectedArea.x; x < affectedArea.right(); ++x) {
for (let y = affectedArea.y; y < affectedArea.bottom(); ++y) { for (let y = affectedArea.y; y < affectedArea.bottom(); ++y) {
if (!originalRect.containsPoint(x, y)) { if (!originalRect.containsPoint(x, y)) {
@ -111,17 +115,20 @@ export class BeltSystem extends GameSystemWithFilter {
); );
targetStaticComp.rotation = rotation; targetStaticComp.rotation = rotation;
metaBelt.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant); metaBelt.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant);
this.cacheNeedsUpdate = true; anythingChanged = true;
} }
} }
} }
} }
} }
// Optimize for the common case of adding or removing buildings one at a time. if (anythingChanged) {
// Clicking and dragging can fire up to 4 create/destroy signals. if (this.areaToRecompute) {
if (this.cacheNeedsUpdate) { this.areaToRecompute = this.areaToRecompute.getUnion(affectedArea);
this.smallUpdateAreas.push(affectedArea.expandedInAllDirections(1)); } else {
this.areaToRecompute = affectedArea.clone();
}
logger.log("Queuing recompute:", this.areaToRecompute);
} }
} }
@ -167,33 +174,34 @@ export class BeltSystem extends GameSystemWithFilter {
return null; return null;
} }
/**
* Recomputes the belt cache
*/
computeBeltCache() { computeBeltCache() {
logger.log("Updating belt cache"); if (this.areaToRecompute) {
logger.log("Updating belt cache by updating area:", this.areaToRecompute);
if (this.smallUpdateAreas.length <= 4) { for (let x = this.areaToRecompute.x; x < this.areaToRecompute.right(); ++x) {
for (let i = 0; i < this.smallUpdateAreas.length; ++i) { for (let y = this.areaToRecompute.y; y < this.areaToRecompute.bottom(); ++y) {
const area = this.smallUpdateAreas[i]; const tile = this.root.map.getTileContentXY(x, y);
for (let x = area.x; x < area.right(); ++x) { if (tile && tile.components.Belt) {
for (let y = area.y; y < area.bottom(); ++y) { tile.components.Belt.followUpCache = this.findFollowUpEntity(tile);
const tile = this.root.map.getTileContentXY(x, y);
if (tile && tile.components.Belt) {
tile.components.Belt.followUpCache = this.findFollowUpEntity(tile);
}
} }
} }
} }
// Reset stale areas afterwards
this.areaToRecompute = null;
} else { } else {
logger.log("Doing full belt recompute");
for (let i = 0; i < this.allEntities.length; ++i) { for (let i = 0; i < this.allEntities.length; ++i) {
const entity = this.allEntities[i]; const entity = this.allEntities[i];
entity.components.Belt.followUpCache = this.findFollowUpEntity(entity); entity.components.Belt.followUpCache = this.findFollowUpEntity(entity);
} }
} }
this.smallUpdateAreas = [];
} }
update() { update() {
if (this.cacheNeedsUpdate) { if (this.areaToRecompute) {
this.cacheNeedsUpdate = false;
this.computeBeltCache(); this.computeBeltCache();
} }