diff --git a/src/balancing/ArenaSimulation.cpp b/src/balancing/ArenaSimulation.cpp index b30bd7a..d31ffba 100644 --- a/src/balancing/ArenaSimulation.cpp +++ b/src/balancing/ArenaSimulation.cpp @@ -494,11 +494,6 @@ const FactoryState& ArenaSimulation::getFactoryState() const return m_factoryState; } -const BuildingSystem& ArenaSimulation::getBuildings() const -{ - return *m_buildingSystem; -} - const ShipSystem& ArenaSimulation::getShips() const { return *m_shipSystem; diff --git a/src/balancing/ArenaSimulation.h b/src/balancing/ArenaSimulation.h index fa23cf8..b6ef73c 100644 --- a/src/balancing/ArenaSimulation.h +++ b/src/balancing/ArenaSimulation.h @@ -85,7 +85,6 @@ public: Tick getCurrentTick() const; const ArenaConfig& getArenaConfig() const; - const BuildingSystem& getBuildings() const; const FactoryState& getFactoryState() const; const ShipSystem& getShips() const; const DebrisSystem& getDebrisSystem() const; diff --git a/src/lib/sim/BuildingSystem.cpp b/src/lib/sim/BuildingSystem.cpp index 63635eb..571e719 100644 --- a/src/lib/sim/BuildingSystem.cpp +++ b/src/lib/sim/BuildingSystem.cpp @@ -774,59 +774,6 @@ void BuildingSystem::tickOutputBelts(FactoryState& state) } } -void BuildingSystem::forEachEmergingItem(const FactoryState& state, - const std::function& visit) const -{ - for (const Building& building : state.buildings) - { - for (std::size_t p = 0; p < building.outputPorts.size(); ++p) - { - const Port& port = building.outputPorts[p]; - const QPoint bodyTile = outputBodyTile(port.tile, port.direction); - const std::vector& lane = building.emergingItems[p]; - - // Render least-progressed first (bottom) → most-progressed last (top), - // matching belt item ordering (REQ-GW-TILE-SIZE). - for (int i = static_cast(lane.size()) - 1; i >= 0; --i) - { - visit(lane[i].item.type, - beltSlotWorldPos(bodyTile, port.direction, lane[i].progress)); - } - } - } -} - -void BuildingSystem::forEachIncomingItem(const FactoryState& state, - const std::function& visit) const -{ - for (const Building& building : state.buildings) - { - for (std::size_t p = 0; p < building.inputPorts.size(); ++p) - { - const Port& port = building.inputPorts[p]; - const QPoint bodyTile = inputBodyTile(port.tile, port.direction); - const std::vector& lane = building.incomingItems[p]; - - // Render least-progressed first (bottom) → most-progressed last (top), - // matching belt item ordering (REQ-GW-TILE-SIZE). - for (int i = static_cast(lane.size()) - 1; i >= 0; --i) - { - visit(lane[i].item.type, - beltSlotWorldPos(bodyTile, port.direction, lane[i].progress)); - } - } - } -} - -// --------------------------------------------------------------------------- -// Queries -// --------------------------------------------------------------------------- - - - - - - void BuildingSystem::rotateInPlace(FactoryState& state, BuildingId id, Rotation newRotation) { // Construction site path — just update rotation; no ports to recompute. diff --git a/src/lib/sim/BuildingSystem.h b/src/lib/sim/BuildingSystem.h index adc32ac..4e851ae 100644 --- a/src/lib/sim/BuildingSystem.h +++ b/src/lib/sim/BuildingSystem.h @@ -108,24 +108,10 @@ public: // (REQ-MAT-OUTPUT-EMERGE). void tickOutputBelts(FactoryState& state); - // -- Queries ------------------------------------------------------------- - // Reading the factory needs no system: those queries are free functions over the - // state (FactoryQueries.h), the placement rules (PlacementRules.h) and the - // production rules (ProductionRules.h). Only the two visitors below are still - // here, and only because their callers reach them through this system. - - // Visits every item currently emerging from a building output port on its - // virtual output belt (REQ-MAT-OUTPUT-EMERGE), passing the item type and its - // world-space centre (in tile units). Least-progressed first (drawn bottom) so - // callers can paint in visit order (REQ-GW-TILE-SIZE ordering). - void forEachEmergingItem(const FactoryState& state, - const std::function& visit) const; - - // Visits every item currently travelling inward on a building input port's - // virtual input belt (REQ-MAT-INPUT-INTAKE), passing the item type and its - // world-space centre (in tile units). Least-progressed first (drawn bottom). - void forEachIncomingItem(const FactoryState& state, - const std::function& visit) const; + // This system answers no queries: reading the factory needs none, the queries being + // free functions over the state (FactoryQueries.h), the placement rules + // (PlacementRules.h) and the production rules (ProductionRules.h). What is left here + // mutates. // Rotate an existing building or construction site to newRotation in place. // For belt-type operational buildings, re-registers with BeltSystem (items diff --git a/src/lib/sim/FactoryQueries.cpp b/src/lib/sim/FactoryQueries.cpp index 5c63000..ed1e45a 100644 --- a/src/lib/sim/FactoryQueries.cpp +++ b/src/lib/sim/FactoryQueries.cpp @@ -3,6 +3,7 @@ #include #include +#include "BeltSlot.h" #include "PortGeometry.h" #include "ProductionRules.h" #include "SelectionBox.h" @@ -234,6 +235,50 @@ TunnelTileMap collectTunnelTiles(const FactoryState& state) return tunnels; } +void forEachEmergingItem(const FactoryState& state, + const std::function& visit) +{ + for (const Building& building : state.buildings) + { + for (std::size_t p = 0; p < building.outputPorts.size(); ++p) + { + const Port& port = building.outputPorts[p]; + const QPoint bodyTile = outputBodyTile(port.tile, port.direction); + const std::vector& lane = building.emergingItems[p]; + + // Render least-progressed first (bottom) -> most-progressed last (top), + // matching belt item ordering (REQ-GW-TILE-SIZE). + for (int i = static_cast(lane.size()) - 1; i >= 0; --i) + { + visit(lane[i].item.type, + beltSlotWorldPos(bodyTile, port.direction, lane[i].progress)); + } + } + } +} + +void forEachIncomingItem(const FactoryState& state, + const std::function& visit) +{ + for (const Building& building : state.buildings) + { + for (std::size_t p = 0; p < building.inputPorts.size(); ++p) + { + const Port& port = building.inputPorts[p]; + const QPoint bodyTile = inputBodyTile(port.tile, port.direction); + const std::vector& lane = building.incomingItems[p]; + + // Render least-progressed first (bottom) -> most-progressed last (top), + // matching belt item ordering (REQ-GW-TILE-SIZE). + for (int i = static_cast(lane.size()) - 1; i >= 0; --i) + { + visit(lane[i].item.type, + beltSlotWorldPos(bodyTile, port.direction, lane[i].progress)); + } + } + } +} + std::vector collectBeltTiles(const FactoryState& state, const std::vector& ids) { diff --git a/src/lib/sim/FactoryQueries.h b/src/lib/sim/FactoryQueries.h index 4d320d2..935cb09 100644 --- a/src/lib/sim/FactoryQueries.h +++ b/src/lib/sim/FactoryQueries.h @@ -1,8 +1,10 @@ #pragma once +#include #include #include +#include #include #include @@ -83,6 +85,18 @@ std::vector buildingsInBox(const FactoryState& state, // single-cell tile. Shared by the placement preview and the selection highlight. TunnelTileMap collectTunnelTiles(const FactoryState& state); +// Visits every item currently emerging from a building output port on its virtual output +// belt (REQ-MAT-OUTPUT-EMERGE), passing the item type and its world-space centre (in tile +// units). Least-progressed first (drawn bottom) so callers can paint in visit order +// (REQ-GW-TILE-SIZE ordering). +void forEachEmergingItem(const FactoryState& state, + const std::function& visit); + +// Visits every item currently travelling inward on a building input port's virtual input +// belt (REQ-MAT-INPUT-INTAKE), in the same form and the same order. +void forEachIncomingItem(const FactoryState& state, + const std::function& visit); + // The tiles of the belt-subsystem buildings among the given ids, in the order the ids // arrive; anything else in the selection is skipped, as are construction sites, whose // tiles the belt subsystem does not know yet (REQ-BLD-SITE-CONFIG). Shared by the panel's diff --git a/src/lib/sim/Simulation.cpp b/src/lib/sim/Simulation.cpp index d735525..7dab1b3 100644 --- a/src/lib/sim/Simulation.cpp +++ b/src/lib/sim/Simulation.cpp @@ -907,11 +907,6 @@ const FactoryState& Simulation::getFactoryState() const return m_factoryState; } -const BuildingSystem& Simulation::getBuildings() const -{ - return *m_buildingSystem; -} - BeltSystem& Simulation::getBeltsMutable() { return m_beltSystem; diff --git a/src/lib/sim/Simulation.h b/src/lib/sim/Simulation.h index ec7f821..218d379 100644 --- a/src/lib/sim/Simulation.h +++ b/src/lib/sim/Simulation.h @@ -120,7 +120,8 @@ public: // private and reachable only through Simulation::apply (the command // chokepoint) or, in tests, SimulationTestAccess — so production code cannot // mutate the factory outside the recorded command path (docs/replay_design.md). - const BuildingSystem& getBuildings() const; + // BuildingSystem has no const accessor: it answers no queries, so nothing outside + // the command path has a reason to reach it (FactoryQueries.h). // The factory's world data, for the free queries in FactoryQueries.h. const FactoryState& getFactoryState() const; diff --git a/src/ui/WorldRenderer.cpp b/src/ui/WorldRenderer.cpp index 50fec8a..6561e49 100644 --- a/src/ui/WorldRenderer.cpp +++ b/src/ui/WorldRenderer.cpp @@ -541,8 +541,8 @@ void WorldRenderer::drawPortItems(QPainter& painter, const WorldCoordinates& coo painter.save(); painter.setClipRegion(clip); - m_sim.getBuildings().forEachEmergingItem(m_sim.getFactoryState(), drawItem); - m_sim.getBuildings().forEachIncomingItem(m_sim.getFactoryState(), drawItem); + forEachEmergingItem(m_sim.getFactoryState(), drawItem); + forEachIncomingItem(m_sim.getFactoryState(), drawItem); painter.restore(); }