From b1fb0fca7e5c6c945e34c1e7f57f9cd4b2d0f06b Mon Sep 17 00:00:00 2001 From: tobspr Date: Sat, 15 Aug 2020 18:14:00 +0200 Subject: [PATCH] Fix wires blueprint pasting bug, do not show wire info on unconnected wires --- src/js/core/rectangle.js | 17 ++++++++ src/js/core/stale_area_detector.js | 50 +++++++++++++++++++++++ src/js/game/hud/parts/debug_changes.js | 2 +- src/js/game/hud/parts/wire_info.js | 2 - src/js/game/systems/wire.js | 55 ++++++++++++++++++-------- 5 files changed, 107 insertions(+), 19 deletions(-) create mode 100644 src/js/core/stale_area_detector.js diff --git a/src/js/core/rectangle.js b/src/js/core/rectangle.js index 6b4315aa..84fe05e5 100644 --- a/src/js/core/rectangle.js +++ b/src/js/core/rectangle.js @@ -376,6 +376,23 @@ export class Rectangle { ); } + /** + * Good for printing stuff + */ + toString() { + return ( + "[x:" + + round2Digits(this.x) + + "| y:" + + round2Digits(this.y) + + "| w:" + + round2Digits(this.w) + + "| h:" + + round2Digits(this.h) + + "]" + ); + } + /** * Returns a new recangle in tile space which includes all tiles which are visible in this rect * @param {boolean=} includeHalfTiles diff --git a/src/js/core/stale_area_detector.js b/src/js/core/stale_area_detector.js new file mode 100644 index 00000000..f8e77f0c --- /dev/null +++ b/src/js/core/stale_area_detector.js @@ -0,0 +1,50 @@ +import { createLogger } from "./logging"; +import { Rectangle } from "./rectangle"; +import { globalConfig } from "./config"; + +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(); + } + } + + /** + * Updates the stale area + */ + update() { + if (this.staleArea) { + logger.log(this.name, "is recomputing", this.staleArea.toString()); + if (G_IS_DEV && globalConfig.debug.renderChanges) { + this.root.hud.parts.changesDebugger.renderChange(this.name, this.staleArea, "#fd145b"); + } + this.recomputeMethod(this.staleArea); + this.staleArea = null; + } + } +} diff --git a/src/js/game/hud/parts/debug_changes.js b/src/js/game/hud/parts/debug_changes.js index 1502afa2..88de84fe 100644 --- a/src/js/game/hud/parts/debug_changes.js +++ b/src/js/game/hud/parts/debug_changes.js @@ -57,7 +57,7 @@ export class HUDChangesDebugger extends BaseHUDPart { for (let i = 0; i < this.changes.length; ++i) { const change = this.changes[i]; parameters.context.fillStyle = change.fillColor; - parameters.context.globalAlpha = 0.5; + parameters.context.globalAlpha = 0.2; parameters.context.fillRect( change.area.x * globalConfig.tileSize, change.area.y * globalConfig.tileSize, diff --git a/src/js/game/hud/parts/wire_info.js b/src/js/game/hud/parts/wire_info.js index ebc448ac..6f57fe17 100644 --- a/src/js/game/hud/parts/wire_info.js +++ b/src/js/game/hud/parts/wire_info.js @@ -53,8 +53,6 @@ export class HUDWireInfo extends BaseHUDPart { if (networks.length === 0) { // No network at all - parameters.context.fillStyle = "#333"; - this.spriteEmpty.draw(parameters.context, mousePos.x + 10, mousePos.y - 10, 40, 40); return; } diff --git a/src/js/game/systems/wire.js b/src/js/game/systems/wire.js index 40852cca..17192093 100644 --- a/src/js/game/systems/wire.js +++ b/src/js/game/systems/wire.js @@ -2,6 +2,9 @@ import { globalConfig } from "../../core/config"; import { gMetaBuildingRegistry } from "../../core/global_registries"; import { Loader } from "../../core/loader"; import { createLogger } from "../../core/logging"; +import { Rectangle } from "../../core/rectangle"; +import { StaleAreaDetector } from "../../core/stale_area_detector"; +import { fastArrayDeleteValueIfContained } from "../../core/utils"; import { arrayAllDirections, enumDirection, @@ -14,13 +17,11 @@ import { arrayWireRotationVariantToType, MetaWireBuilding } from "../buildings/w import { getCodeFromBuildingData } from "../building_codes"; import { enumWireType, WireComponent } from "../components/wire"; import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { WireTunnelComponent } from "../components/wire_tunnel"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; import { MapChunkView } from "../map_chunk_view"; import { defaultBuildingVariant } from "../meta_building"; -import { WireTunnelComponent } from "../components/wire_tunnel"; -import { fastArrayDeleteValueIfContained } from "../../core/utils"; -import { BooleanItem } from "../items/boolean_item"; const logger = createLogger("wires"); @@ -110,8 +111,8 @@ export class WireSystem extends GameSystemWithFilter { }, }; - this.root.signals.entityDestroyed.add(this.updateSurroundingWirePlacement, this); - this.root.signals.entityAdded.add(this.updateSurroundingWirePlacement, this); + this.root.signals.entityDestroyed.add(this.queuePlacementUpdate, this); + this.root.signals.entityAdded.add(this.queuePlacementUpdate, this); this.root.signals.entityDestroyed.add(this.queueRecomputeIfWire, this); this.root.signals.entityChanged.add(this.queueRecomputeIfWire, this); @@ -119,6 +120,12 @@ export class WireSystem extends GameSystemWithFilter { this.needsRecompute = true; + this.staleArea = new StaleAreaDetector({ + root: this.root, + name: "wires", + recomputeMethod: this.updateSurroundingWirePlacement.bind(this), + }); + /** * @type {Array} */ @@ -134,7 +141,7 @@ export class WireSystem extends GameSystemWithFilter { return; } - if (entity.components.Wire || entity.components.WiredPins || entity.components.WireTunnel) { + if (this.isEntityRelevantForWires(entity)) { this.needsRecompute = true; this.networks = []; } @@ -485,6 +492,8 @@ export class WireSystem extends GameSystemWithFilter { * Updates the wires network */ update() { + this.staleArea.update(); + if (this.needsRecompute) { this.recomputeWiresNetwork(); } @@ -668,32 +677,46 @@ export class WireSystem extends GameSystemWithFilter { } /** - * Updates the wire placement after an entity has been added / deleted + * Returns whether this entity is relevant for the wires network * @param {Entity} entity */ - updateSurroundingWirePlacement(entity) { + isEntityRelevantForWires(entity) { + return entity.components.Wire || entity.components.WiredPins || entity.components.WireTunnel; + } + + /** + * + * @param {Entity} entity + */ + queuePlacementUpdate(entity) { if (!this.root.gameInitialized) { return; } + if (!this.isEntityRelevantForWires(entity)) { + return; + } + const staticComp = entity.components.StaticMapEntity; if (!staticComp) { return; } - const metaWire = gMetaBuildingRegistry.findByClass(MetaWireBuilding); - - // Compute affected area + // Invalidate affected area const originalRect = staticComp.getTileSpaceBounds(); const affectedArea = originalRect.expandedInAllDirections(1); + this.staleArea.invalidate(affectedArea); + } + + /** + * Updates the wire placement after an entity has been added / deleted + * @param {Rectangle} affectedArea + */ + updateSurroundingWirePlacement(affectedArea) { + const metaWire = gMetaBuildingRegistry.findByClass(MetaWireBuilding); for (let x = affectedArea.x; x < affectedArea.right(); ++x) { for (let y = affectedArea.y; y < affectedArea.bottom(); ++y) { - if (originalRect.containsPoint(x, y)) { - // Make sure we don't update the original entity - continue; - } - const targetEntities = this.root.map.getLayersContentsMultipleXY(x, y); for (let i = 0; i < targetEntities.length; ++i) { const targetEntity = targetEntities[i];