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.
|
- 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.
|
- 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
|
||||||
|
|
||||||
Debris — the salvageable object dropped by destroyed ships and defence stations — is the
|
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,
|
std::optional<BuildingId> place(FactoryState& state, BuildingType type, QPoint anchor, Rotation rotation,
|
||||||
Tick currentTick);
|
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
|
// Sets the current buildable asteroid width in tiles. Grows the left
|
||||||
// placement bound as the player unlocks asteroid expansions (REQ-EXP-UNLOCK).
|
// placement bound as the player unlocks asteroid expansions (REQ-EXP-UNLOCK).
|
||||||
// Defaults to world.regions.asteroid_width_tiles at construction.
|
// 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.
|
// progress and credits no refund. No-op if the id is not queued.
|
||||||
void cancelDeconstruction(FactoryState& state, BuildingId id);
|
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
|
// Set the recipe (or schematic id for shipyard) on a building or queued
|
||||||
// construction site. Clears both buffers on an operational building.
|
// construction site. Clears both buffers on an operational building.
|
||||||
void setRecipe(FactoryState& state, BuildingId id, const std::string& recipeId);
|
void setRecipe(FactoryState& state, BuildingId id, const std::string& recipeId);
|
||||||
@@ -105,9 +97,9 @@ public:
|
|||||||
const std::vector<ItemType>& filterB);
|
const std::vector<ItemType>& filterB);
|
||||||
|
|
||||||
// -- Tick hooks (called from Simulation::tick in the documented order) ---
|
// -- Tick hooks (called from Simulation::tick in the documented order) ---
|
||||||
// Advances the deconstruction queue (REQ-BLD-DECON-QUEUE): one building at a
|
// Advances every building's virtual input belts, delivers what arrives into the
|
||||||
// time, in parallel with tickConstruction. Removes the front building and
|
// input buffers (into the global block stock for the HQ), and takes what the
|
||||||
// credits its refund when its timer elapses.
|
// adjacent real belts offer (REQ-MAT-INPUT-INTAKE, REQ-HQ-BELT-INPUT).
|
||||||
void tickBeltPull(FactoryState& state);
|
void tickBeltPull(FactoryState& state);
|
||||||
void tickProduction(FactoryState& state, Tick currentTick);
|
void tickProduction(FactoryState& state, Tick currentTick);
|
||||||
void tickShipyardProduction(FactoryState& state, Tick currentTick);
|
void tickShipyardProduction(FactoryState& state, Tick currentTick);
|
||||||
@@ -117,18 +109,10 @@ public:
|
|||||||
void tickOutputBelts(FactoryState& state);
|
void tickOutputBelts(FactoryState& state);
|
||||||
|
|
||||||
// -- Queries -------------------------------------------------------------
|
// -- Queries -------------------------------------------------------------
|
||||||
|
// Reading the factory needs no system: those queries are free functions over the
|
||||||
|
// state (FactoryQueries.h), the placement rules (PlacementRules.h) and the
|
||||||
// REQ-UI-DEBUG-OVERLAY "Max Factory Production": count of completed
|
// production rules (ProductionRules.h). Only the two visitors below are still
|
||||||
// (operational) Miner/Smelter/Assembler/ReprocessingPlant/Shipyard buildings.
|
// here, and only because their callers reach them through this system.
|
||||||
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// Visits every item currently emerging from a building output port on its
|
// 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
|
// 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).
|
// currently on the tile are discarded by BeltSystem::removeTile).
|
||||||
void rotateInPlace(FactoryState& state, BuildingId id, Rotation newRotation);
|
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.
|
// Register / unregister tile occupancy for ECS station entities.
|
||||||
void registerTileOccupancy(FactoryState& state, const std::vector<QPoint>& cells, BuildingId ownerPlaceholder);
|
void registerTileOccupancy(FactoryState& state, const std::vector<QPoint>& cells, BuildingId ownerPlaceholder);
|
||||||
void unregisterTileOccupancy(FactoryState& state, const std::vector<QPoint>& cells);
|
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
|
// Bypass the construction queue and create a fully-operational Building
|
||||||
// immediately. Used for pre-placed structures (HQ, defence stations).
|
// immediately. Used for pre-placed structures (HQ, defence stations).
|
||||||
// surfaceMask comes from the relevant config struct.
|
// surfaceMask comes from the relevant config struct.
|
||||||
@@ -181,13 +156,6 @@ public:
|
|||||||
void appendChecksum(const FactoryState& state, Hasher& hasher) const;
|
void appendChecksum(const FactoryState& state, Hasher& hasher) const;
|
||||||
|
|
||||||
private:
|
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
|
// 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
|
// 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
|
// other building, for one that already holds a recipe, and for a material none of
|
||||||
@@ -213,26 +181,17 @@ private:
|
|||||||
const Port& outputPort,
|
const Port& outputPort,
|
||||||
const Item& item);
|
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
|
// 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
|
// (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;
|
// 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.
|
// where it has one, that group is returned with no draw and no eligibility test.
|
||||||
std::vector<Item> rollOutputGroup(const RecipeDef& recipe);
|
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;
|
const GameConfig& m_config;
|
||||||
|
|
||||||
|
|
||||||
BeltSystem& m_belts;
|
BeltSystem& m_belts;
|
||||||
std::function<BuildingId()> m_allocateBuildingId;
|
std::function<BuildingId()> m_allocateBuildingId;
|
||||||
std::function<void(int)> m_addBuildingBlocks;
|
std::function<void(int)> m_addBuildingBlocks;
|
||||||
|
|||||||
@@ -33,10 +33,15 @@ struct DeconstructionEntry
|
|||||||
// arrives as a tick argument instead of being owned by the system.
|
// 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
|
// 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
|
// systems that operate on it. Every system that touches the factory —
|
||||||
// is to pass this into the tick methods instead, so the systems become stateless
|
// BuildingSystem, ConstructionSystem, DeconstructionSystem — takes it as an argument
|
||||||
// over it — that one is gated on the query surface, which today reaches the data
|
// and holds none of it, so each is stateless over the world it works on. Reading it
|
||||||
// through BuildingSystem's ~180 const call sites.
|
// 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
|
struct FactoryState
|
||||||
{
|
{
|
||||||
std::vector<Building> buildings;
|
std::vector<Building> buildings;
|
||||||
|
|||||||
Reference in New Issue
Block a user