import { Component } from "../game/component"; import { Entity } from "../game/entity"; import { globalConfig } from "./config"; import { createLogger } from "./logging"; import { Rectangle } from "./rectangle"; const logger = createLogger("stale_areas"); export class StaleAreaDetector { /** * * @param {object} param0 * @param {import("../game/root").GameRoot} param0.root * @param {string} param0.name The name for reference * @param {(Rectangle) => void} param0.recomputeMethod Method which recomputes the given area */ constructor({ root, name, recomputeMethod }) { this.root = root; this.name = name; this.recomputeMethod = recomputeMethod; /** @type {Rectangle} */ this.staleArea = null; } /** * Invalidates the given area * @param {Rectangle} area */ invalidate(area) { // logger.log(this.name, "invalidated", area.toString()); if (this.staleArea) { this.staleArea = this.staleArea.getUnion(area); } else { this.staleArea = area.clone(); } } /** * Makes this detector recompute the area of an entity whenever * it changes in any way * @param {Array} components * @param {number} tilesAround How many tiles arround to expand the area */ recomputeOnComponentsChanged(components, tilesAround) { const componentIds = components.map(component => component.getId()); /** * Internal checker method * @param {Entity} entity */ const checker = entity => { if (!this.root.gameInitialized) { return; } // Check for all components for (let i = 0; i < componentIds.length; ++i) { if (entity.components[componentIds[i]]) { // Entity is relevant, compute affected area const area = entity.components.StaticMapEntity.getTileSpaceBounds().expandedInAllDirections( tilesAround ); this.invalidate(area); return; } } }; this.root.signals.entityAdded.add(checker); this.root.signals.entityChanged.add(checker); this.root.signals.entityComponentRemoved.add(checker); this.root.signals.entityGotNewComponent.add(checker); this.root.signals.entityDestroyed.add(checker); } /** * Updates the stale area */ update() { if (this.staleArea) { if (G_IS_DEV && globalConfig.debug.renderChanges) { logger.log(this.name, "is recomputing", this.staleArea.toString()); this.root.hud.parts.changesDebugger.renderChange(this.name, this.staleArea, "#fd145b"); } this.recomputeMethod(this.staleArea); this.staleArea = null; } } }