say where the factory's data lives, now that it has moved
The FactoryState migration finished some time ago -- every system that touches the factory takes the state as an argument and holds none of it, and the const surface has become free functions over the struct -- but the comments still described the state of affairs two refactors back. FactoryState.h claimed BuildingSystem holds a reference and that passing the state into the tick methods was the remaining step, gated on ~180 const call sites that no longer exist. It now says what is true, and names what genuinely has not moved: the id counter and the block stock, factory data still living on Simulation behind callbacks. architecture.md described neither FactoryState nor FactoryQueries at all, so the Buildings section told a reader that buildings are a plain vector and nothing about who owns it or how it is read. It gains that section, including why ConstructionSystem completes a building itself. BuildingSystem.h had collected ten comment blocks whose declarations had moved out from under them -- the whole Queries section was four comments and no functions, and the deconstruction-queue tick comment sat above tickBeltPull, documenting the wrong function. Those are gone; tickBeltPull gets a comment describing what it actually does, and the Queries banner now points at where the queries went. No code changed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ne3mejABZoLWKLh8fgpM3x
This commit is contained in:
@@ -242,6 +242,44 @@ struct Building {
|
||||
- Belts and splitters are separate types owned by the belt subsystem, not general `Building` instances.
|
||||
- No ECS for buildings. A miner is never also an assembler; there is no composition benefit to decomposing buildings into components.
|
||||
|
||||
### Factory State and Queries
|
||||
|
||||
The buildings, the construction and deconstruction queues, and the tile-ownership grid
|
||||
live in one struct — `FactoryState` — owned by `Simulation` (and by `ArenaSimulation` in
|
||||
the balancing tool), never by a system. It is data with no behaviour of its own, the
|
||||
buildings-side counterpart to `EntityAdmin`.
|
||||
|
||||
```cpp
|
||||
struct FactoryState {
|
||||
std::vector<Building> buildings;
|
||||
std::deque<ConstructionSite> constructionQueue;
|
||||
std::deque<DeconstructionEntry> deconstructionQueue;
|
||||
BuildingGrid grid; // who owns which tile
|
||||
int asteroidWidth_tiles = 0; // left placement bound
|
||||
};
|
||||
```
|
||||
|
||||
Every system that touches the factory — `BuildingSystem`, `ConstructionSystem`,
|
||||
`DeconstructionSystem` — takes it as an argument and holds none of it, the same shape the
|
||||
`lib/ecs/system` classes have, where the world arrives per tick. This is why
|
||||
`ConstructionSystem` can complete a building itself instead of handing the finished site
|
||||
back to `BuildingSystem`: with the state in the argument there is no owner to route
|
||||
through.
|
||||
|
||||
**Reading the factory needs no system.** The queries are free functions over the state:
|
||||
`FactoryQueries.h` for what is where (`findBuilding`, `getInputPorts`, `collectBeltTiles`),
|
||||
`PlacementRules.h` for whether a placement is legal, `ProductionRules.h` for what a
|
||||
building could run and what its status light shows. A caller therefore depends on the data
|
||||
it reads rather than on whichever system happens to tick it — which is what let the UI, the
|
||||
balancing tool and the tests stop reaching through `BuildingSystem` for const answers.
|
||||
|
||||
What has not moved yet: the building-id counter and the global building block stock are
|
||||
factory data that still live on `Simulation`, reached through callbacks
|
||||
(`m_allocateBuildingId`, `m_addBuildingBlocks`) held by `BuildingSystem` and
|
||||
`DeconstructionSystem`. `m_spawnShip` and `m_isItemUnlocked` are genuine cross-domain
|
||||
reaches — into the entity model and the unlock state — and are not candidates for this
|
||||
struct.
|
||||
|
||||
## Debris
|
||||
|
||||
Debris — the salvageable object dropped by destroyed ships and defence stations — is the
|
||||
|
||||
@@ -57,12 +57,6 @@ public:
|
||||
std::optional<BuildingId> place(FactoryState& state, BuildingType type, QPoint anchor, Rotation rotation,
|
||||
Tick currentTick);
|
||||
|
||||
// Returns true if the placement satisfies REQ-BLD-PLACE-VALID terrain and
|
||||
// world-bounds rules: every ship-dock (S) cell sits in space (x >= 0), every
|
||||
// other body (A) cell sits on the asteroid (x < 0 and x >= the left edge),
|
||||
// and every cell has 0 <= y < world.height_tiles. There is no right-side
|
||||
// bound — space extends rightward. Tile occupancy is NOT checked here.
|
||||
|
||||
// Sets the current buildable asteroid width in tiles. Grows the left
|
||||
// placement bound as the player unlocks asteroid expansions (REQ-EXP-UNLOCK).
|
||||
// Defaults to world.regions.asteroid_width_tiles at construction.
|
||||
@@ -83,8 +77,6 @@ public:
|
||||
// progress and credits no refund. No-op if the id is not queued.
|
||||
void cancelDeconstruction(FactoryState& state, BuildingId id);
|
||||
|
||||
// True if the building is currently in the deconstruction queue.
|
||||
|
||||
// Set the recipe (or schematic id for shipyard) on a building or queued
|
||||
// construction site. Clears both buffers on an operational building.
|
||||
void setRecipe(FactoryState& state, BuildingId id, const std::string& recipeId);
|
||||
@@ -105,9 +97,9 @@ public:
|
||||
const std::vector<ItemType>& filterB);
|
||||
|
||||
// -- Tick hooks (called from Simulation::tick in the documented order) ---
|
||||
// Advances the deconstruction queue (REQ-BLD-DECON-QUEUE): one building at a
|
||||
// time, in parallel with tickConstruction. Removes the front building and
|
||||
// credits its refund when its timer elapses.
|
||||
// Advances every building's virtual input belts, delivers what arrives into the
|
||||
// input buffers (into the global block stock for the HQ), and takes what the
|
||||
// adjacent real belts offer (REQ-MAT-INPUT-INTAKE, REQ-HQ-BELT-INPUT).
|
||||
void tickBeltPull(FactoryState& state);
|
||||
void tickProduction(FactoryState& state, Tick currentTick);
|
||||
void tickShipyardProduction(FactoryState& state, Tick currentTick);
|
||||
@@ -117,18 +109,10 @@ public:
|
||||
void tickOutputBelts(FactoryState& state);
|
||||
|
||||
// -- Queries -------------------------------------------------------------
|
||||
|
||||
|
||||
// REQ-UI-DEBUG-OVERLAY "Max Factory Production": count of completed
|
||||
// (operational) Miner/Smelter/Assembler/ReprocessingPlant/Shipyard buildings.
|
||||
|
||||
// REQ-UI-DEBUG-OVERLAY "Current Factory Production": subset of the above
|
||||
// that currently has an active production cycle.
|
||||
|
||||
// Production state for the UI status light (REQ-UI-STATUS-LIGHT). Returns
|
||||
// nullopt for building types that show no light (belts, splitters, tunnels,
|
||||
// HQ, defence stations). The Salvage Bay is a two-state special case:
|
||||
// Producing while its output buffer holds scrap, Starved when empty.
|
||||
// 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
|
||||
@@ -148,19 +132,10 @@ public:
|
||||
// currently on the tile are discarded by BeltSystem::removeTile).
|
||||
void rotateInPlace(FactoryState& state, BuildingId id, Rotation newRotation);
|
||||
|
||||
|
||||
// Input-capable adjacent tiles for a building or construction site
|
||||
// (REQ-BLD-BELT-DRAG, REQ-MAT-INPUT-PORTS): each returned Port.tile is the
|
||||
// outside adjacent tile and Port.direction is the belt facing that points into
|
||||
// the target. Output-port edges are excluded. Empty for an unknown id.
|
||||
|
||||
// Register / unregister tile occupancy for ECS station entities.
|
||||
void registerTileOccupancy(FactoryState& state, const std::vector<QPoint>& cells, BuildingId ownerPlaceholder);
|
||||
void unregisterTileOccupancy(FactoryState& state, const std::vector<QPoint>& cells);
|
||||
|
||||
// Place one "scrap" item into a SalvageBay's output buffer.
|
||||
// Returns false if bay not found, wrong type, or output buffer is full.
|
||||
|
||||
// Bypass the construction queue and create a fully-operational Building
|
||||
// immediately. Used for pre-placed structures (HQ, defence stations).
|
||||
// surfaceMask comes from the relevant config struct.
|
||||
@@ -181,13 +156,6 @@ public:
|
||||
void appendChecksum(const FactoryState& state, Hasher& hasher) const;
|
||||
|
||||
private:
|
||||
// Starts the front deconstruction-queue entry's timer if not yet started
|
||||
// (mirrors how tickConstruction starts a queued construction site).
|
||||
|
||||
// Registers a belt/splitter/tunnel building's tile with the belt subsystem
|
||||
// (on construction completion, or when un-queuing a deconstruction). No-op for
|
||||
// non-belt-subsystem types. Splitter filters are (re)applied after placement.
|
||||
|
||||
// Selects a recipe for an auto-recipe building that has none, from a material being
|
||||
// offered to it at one of its input ports (REQ-BLD-AUTO-RECIPE). No-op for every
|
||||
// other building, for one that already holds a recipe, and for a material none of
|
||||
@@ -213,28 +181,19 @@ private:
|
||||
const Port& outputPort,
|
||||
const Item& item);
|
||||
|
||||
// Candidate recipes an idle building would try this tick: an auto-recipe
|
||||
// building (Smelter, Reprocessing Plant) offers every recipe of its type with
|
||||
// inputs; other buildings offer only their selected recipe. Shared by
|
||||
// tickProduction and the status classifier (REQ-MAT-CYCLE, REQ-UI-STATUS-LIGHT).
|
||||
// True if every input of `recipe` is present in `b`'s input buffers in the
|
||||
// required per-cycle amount (REQ-MAT-CYCLE input check).
|
||||
// Combined base + module materials a shipyard needs per ship (REQ-BLD-SHIPYARD).
|
||||
// True if the building currently has all inputs/materials to start a cycle
|
||||
// (ignoring output-buffer space); drives the Starved/Blocked distinction of
|
||||
// the status light (REQ-UI-STATUS-LIGHT).
|
||||
|
||||
// What one cycle of this recipe produces: the items of its one output group
|
||||
// (REQ-MAT-OUTPUT-GROUP). Where the recipe has several, one is picked by weight from
|
||||
// those currently eligible (REQ-LOCK-OUTPUT-POOL) and the result is empty if none is;
|
||||
// where it has one, that group is returned with no draw and no eligibility test.
|
||||
std::vector<Item> rollOutputGroup(const RecipeDef& recipe);
|
||||
|
||||
// No world data among these: the factory arrives per call (FactoryState.h). What is
|
||||
// left are the immutable config, the transport layer, the shared RNG, and four
|
||||
// callbacks into what this system cannot reach on its own -- the id counter and the
|
||||
// block stock, which live on Simulation, and the entity and unlock sides.
|
||||
const GameConfig& m_config;
|
||||
|
||||
|
||||
BeltSystem& m_belts;
|
||||
std::function<BuildingId()> m_allocateBuildingId;
|
||||
std::function<BuildingId()> m_allocateBuildingId;
|
||||
std::function<void(int)> m_addBuildingBlocks;
|
||||
std::function<void(const std::string&, QVector2D,
|
||||
const std::optional<ShipLayoutConfig>&)> m_spawnShip;
|
||||
|
||||
@@ -33,10 +33,15 @@ struct DeconstructionEntry
|
||||
// arrives as a tick argument instead of being owned by the system.
|
||||
//
|
||||
// Owned by Simulation (and by ArenaSimulation in the balancing tool), not by the
|
||||
// systems that operate on it. BuildingSystem holds a reference. The remaining step
|
||||
// is to pass this into the tick methods instead, so the systems become stateless
|
||||
// over it — that one is gated on the query surface, which today reaches the data
|
||||
// through BuildingSystem's ~180 const call sites.
|
||||
// systems that operate on it. Every system that touches the factory —
|
||||
// BuildingSystem, ConstructionSystem, DeconstructionSystem — takes it as an argument
|
||||
// and holds none of it, so each is stateless over the world it works on. Reading it
|
||||
// needs no system at all: the queries are free functions over this struct
|
||||
// (FactoryQueries.h, PlacementRules.h, ProductionRules.h).
|
||||
//
|
||||
// What is not here yet is the data those systems still reach back into Simulation
|
||||
// for through callbacks: the building-id counter and the global building block stock,
|
||||
// both of which are factory data living outside the factory's state.
|
||||
struct FactoryState
|
||||
{
|
||||
std::vector<Building> buildings;
|
||||
|
||||
Reference in New Issue
Block a user