Files
dota_factory/src/lib/sim/FactoryQueries.h
Malte Langkabel a783e57731 move the two item visitors to the queries they always were
forEachEmergingItem and forEachIncomingItem took a const FactoryState& and
touched no member of BuildingSystem: they read the state and the free geometry
helpers and nothing else. They are queries wearing a system's uniform, and their
one caller -- the renderer -- reached through getBuildings() to call them,
passing the state back in as an argument.

They move to FactoryQueries beside the rest of the read surface, and the renderer
calls them directly. With that, BuildingSystem answers no queries at all: its
const accessor on Simulation and on ArenaSimulation had no other user, so both
are gone. Nothing outside the command path can now reach the system.

No behaviour changes; the bodies move verbatim apart from two arrows in comments
that were non-ASCII.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ne3mejABZoLWKLh8fgpM3x
2026-08-19 17:07:17 +02:00

107 lines
5.2 KiB
C++

#pragma once
#include <functional>
#include <vector>
#include <QPoint>
#include <QPointF>
#include <QRectF>
#include <QVector2D>
#include "Building.h"
#include "BuildingId.h"
#include "BuildingType.h"
#include "BeltSystem.h"
#include "FactoryState.h"
#include "GameConfig.h"
#include "Port.h"
#include "TunnelCompletion.h"
// Queries and operations over the factory's world data that need nothing but that
// data — no config, no belts, no RNG. Free functions rather than BuildingSystem
// methods so that callers depend on the data they read instead of on the system
// that happens to tick it (see FactoryState.h).
//
// Most need nothing but the state. The two at the bottom also take the config,
// because answering them means reading a building definition — but still no belts,
// no RNG and no system.
// The building with the given id, or nullptr when no building has it. Construction
// sites are not buildings yet — use findSite for those.
const Building* findBuilding(const FactoryState& state, BuildingId id);
Building* findBuilding(FactoryState& state, BuildingId id);
// The queued construction site with the given id, or nullptr.
const ConstructionSite* findSite(const FactoryState& state, BuildingId id);
std::vector<Building> getAllBuildings(const FactoryState& state);
std::vector<ConstructionSite> getAllSites(const FactoryState& state);
// REQ-UI-DEBUG-OVERLAY "Max Factory Production": count of completed
// (operational) Miner/Smelter/Assembler/ReprocessingPlant/Shipyard buildings.
int getProductionBuildingCount(const FactoryState& state);
// REQ-UI-DEBUG-OVERLAY "Current Factory Production": subset of the above that
// currently has an active production cycle.
int getActiveProductionBuildingCount(const FactoryState& state);
bool isTileOccupied(const FactoryState& state, QPoint tile);
// True while the building is in the deconstruction queue (REQ-BLD-DECON-QUEUE).
bool isQueuedForDeconstruction(const FactoryState& state, BuildingId id);
// The nearest building of the given type to a world position, or nullptr when
// none exists. Distance is measured to the building's footprint centre.
const Building* findNearestBuilding(const FactoryState& state, QVector2D worldPos,
BuildingType type);
// Hands one scrap to a Salvage Bay's output buffer (REQ-BLD-SALVAGE-BAY). Fails
// if the id is not a Salvage Bay, it is queued for deconstruction
// (REQ-BLD-DECON-QUEUE), or its holding capacity is already taken — emerging
// scrap counts against that capacity (REQ-MAT-OUTPUT-EMERGE).
bool deliverScrapToSalvageBay(FactoryState& state, BuildingId bayId);
// Every belt-facing edge of the building or site with this id (REQ-MAT-INPUT-PORTS,
// REQ-BLD-BELT-DRAG). Empty when the id is unknown. A site has no stored ports, so
// they are derived from its surface mask.
std::vector<Port> getInputPorts(const FactoryState& state, const GameConfig& config,
BuildingId id);
// The two output directions and stored filters of a queued Splitter site
// (REQ-BLD-SITE-CONFIG), or nullopt if the id is not one. Operational splitters are
// configured through BeltSystem by tile instead.
std::optional<BeltSystem::SplitterInfo> getSiteSplitterInfo(const FactoryState& state,
const GameConfig& config,
BuildingId id);
// Ids of all buildings and construction sites the selection box covers — those with
// a body cell the box overlaps, per boxCoversTile (REQ-UI-MULTI-SELECT,
// REQ-BLD-DECONSTRUCT-BOX). `worldBox` is in world coordinates and normalized; it is
// not snapped to tiles.
std::vector<BuildingId> buildingsInBox(const FactoryState& state,
const QRectF& worldBox);
// Every tunnel entry and exit, built or still a construction site, indexed by its
// 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<void(const ItemType&, QPointF)>& 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<void(const ItemType&, QPointF)>& 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
// item list and its clear action, so both speak of exactly the same tiles
// (REQ-UI-BELT-ITEMS, REQ-UI-BELT-CLEAR).
std::vector<QPoint> collectBeltTiles(const FactoryState& state,
const std::vector<BuildingId>& ids);