Compare commits
2 Commits
d713257fb5
...
71d0dad3f2
| Author | SHA1 | Date | |
|---|---|---|---|
| 71d0dad3f2 | |||
| fda88fe75c |
@@ -38,3 +38,17 @@ std::string buildingTypeId(BuildingType type)
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool isAutoRecipeBuildingType(BuildingType type)
|
||||
{
|
||||
return type == BuildingType::Smelter
|
||||
|| type == BuildingType::ReprocessingPlant;
|
||||
}
|
||||
|
||||
bool isBeltSubsystemType(BuildingType type)
|
||||
{
|
||||
return type == BuildingType::Belt
|
||||
|| type == BuildingType::Splitter
|
||||
|| type == BuildingType::TunnelEntry
|
||||
|| type == BuildingType::TunnelExit;
|
||||
}
|
||||
|
||||
@@ -29,3 +29,13 @@ std::optional<BuildingType> parseBuildingType(const std::string& id);
|
||||
|
||||
// Canonical id string for a BuildingType. The inverse of parseBuildingType.
|
||||
std::string buildingTypeId(BuildingType type);
|
||||
|
||||
// Smelter and Reprocessing Plant have no player-selected recipe
|
||||
// (REQ-BLD-SMELTER, REQ-BLD-REPROCESSING). They auto-process whatever inputs
|
||||
// they receive, matching against every recipe of their building type.
|
||||
bool isAutoRecipeBuildingType(BuildingType type);
|
||||
|
||||
// Belts, splitters, and tunnel ends keep their runtime data in the belt subsystem
|
||||
// rather than in the Building instance, so placing/removing them must register or
|
||||
// unregister a tile with BeltSystem.
|
||||
bool isBeltSubsystemType(BuildingType type);
|
||||
|
||||
@@ -9,6 +9,7 @@ SET(HDRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ItemType.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Item.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Port.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PortGeometry.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/SchematicChoiceOption.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/DisplayName.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BeltDragPath.h
|
||||
|
||||
45
src/lib/core/PortGeometry.h
Normal file
45
src/lib/core/PortGeometry.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <QPoint>
|
||||
|
||||
#include "Rotation.h"
|
||||
|
||||
// Geometry of a building's input/output ports. A Port names the tile *outside* the
|
||||
// building together with the direction items flow across it; these helpers give the
|
||||
// building body tile on the other side of that edge, which is where the virtual
|
||||
// input/output belt lives.
|
||||
//
|
||||
// Shared by the simulation (which moves items across the edge) and the renderer
|
||||
// (which draws the virtual belt), so the two cannot disagree about which tile a
|
||||
// port belongs to.
|
||||
|
||||
// The building body tile that owns an output port, given the port's outside tile
|
||||
// (port.tile) and its facing direction. The virtual output belt occupies this tile
|
||||
// and flows toward port.tile (REQ-MAT-OUTPUT-EMERGE).
|
||||
inline QPoint outputBodyTile(QPoint portTile, Rotation direction)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case Rotation::East: return portTile + QPoint(-1, 0);
|
||||
case Rotation::West: return portTile + QPoint( 1, 0);
|
||||
case Rotation::North: return portTile + QPoint( 0, 1);
|
||||
case Rotation::South: return portTile + QPoint( 0, -1);
|
||||
}
|
||||
return portTile;
|
||||
}
|
||||
|
||||
// The building body tile an input port feeds into, given the port's outside belt
|
||||
// tile (port.tile) and its inward flow direction. The virtual input belt occupies
|
||||
// this tile and flows from the outer edge (progress 0.0) to the centre (0.5)
|
||||
// (REQ-MAT-INPUT-INTAKE).
|
||||
inline QPoint inputBodyTile(QPoint portTile, Rotation inwardDirection)
|
||||
{
|
||||
switch (inwardDirection)
|
||||
{
|
||||
case Rotation::East: return portTile + QPoint( 1, 0);
|
||||
case Rotation::West: return portTile + QPoint(-1, 0);
|
||||
case Rotation::North: return portTile + QPoint( 0, -1);
|
||||
case Rotation::South: return portTile + QPoint( 0, 1);
|
||||
}
|
||||
return portTile;
|
||||
}
|
||||
52
src/lib/sim/BuildingGrid.cpp
Normal file
52
src/lib/sim/BuildingGrid.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "BuildingGrid.h"
|
||||
|
||||
#include "StateChecksum.h"
|
||||
|
||||
void BuildingGrid::occupy(QPoint cell, BuildingId id)
|
||||
{
|
||||
m_owners[{cell.x(), cell.y()}] = id;
|
||||
}
|
||||
|
||||
void BuildingGrid::occupy(const std::vector<QPoint>& cells, BuildingId id)
|
||||
{
|
||||
for (const QPoint& cell : cells)
|
||||
{
|
||||
occupy(cell, id);
|
||||
}
|
||||
}
|
||||
|
||||
void BuildingGrid::release(const std::vector<QPoint>& cells)
|
||||
{
|
||||
for (const QPoint& cell : cells)
|
||||
{
|
||||
m_owners.erase({cell.x(), cell.y()});
|
||||
}
|
||||
}
|
||||
|
||||
bool BuildingGrid::isOccupied(QPoint tile) const
|
||||
{
|
||||
return m_owners.count({tile.x(), tile.y()}) > 0;
|
||||
}
|
||||
|
||||
std::optional<BuildingId> BuildingGrid::findOwner(QPoint tile) const
|
||||
{
|
||||
const std::map<std::pair<int, int>, BuildingId>::const_iterator it =
|
||||
m_owners.find({tile.x(), tile.y()});
|
||||
if (it == m_owners.end())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void BuildingGrid::appendChecksum(Hasher& hasher) const
|
||||
{
|
||||
// std::map iterates in sorted key order.
|
||||
hasher.append(m_owners.size());
|
||||
for (const std::pair<const std::pair<int, int>, BuildingId>& entry : m_owners)
|
||||
{
|
||||
hasher.append(entry.first.first);
|
||||
hasher.append(entry.first.second);
|
||||
hasher.append(entry.second);
|
||||
}
|
||||
}
|
||||
46
src/lib/sim/BuildingGrid.h
Normal file
46
src/lib/sim/BuildingGrid.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <QPoint>
|
||||
|
||||
#include "BuildingId.h"
|
||||
|
||||
class Hasher;
|
||||
|
||||
// The authority on which building owns which world tile.
|
||||
//
|
||||
// Every building and construction site claims its body cells here when it is placed
|
||||
// and releases them when it is removed, so the map is the single place that knows
|
||||
// whether a tile is free. It is a plain index owned by BuildingSystem, not a system:
|
||||
// it has no per-tick behaviour and nothing outside BuildingSystem touches it.
|
||||
//
|
||||
// Keys are deliberately std::pair<int, int> rather than QPoint: the checksum folds the
|
||||
// entries in map iteration order (docs/replay_design.md), so the comparator is part of
|
||||
// the determinism contract and is not changed casually.
|
||||
class BuildingGrid
|
||||
{
|
||||
public:
|
||||
// Records absolute body cells as owned by id. Re-occupying a cell overwrites its
|
||||
// previous owner, matching the placement paths that reserve cells for a site and
|
||||
// then hand them to the building it becomes.
|
||||
void occupy(QPoint cell, BuildingId id);
|
||||
void occupy(const std::vector<QPoint>& cells, BuildingId id);
|
||||
|
||||
// Releases absolute body cells. Cells that are not occupied are ignored.
|
||||
void release(const std::vector<QPoint>& cells);
|
||||
|
||||
bool isOccupied(QPoint tile) const;
|
||||
|
||||
// The building owning the tile, or nullopt when the tile is free.
|
||||
std::optional<BuildingId> findOwner(QPoint tile) const;
|
||||
|
||||
// Folds the occupancy into the hasher in deterministic order.
|
||||
void appendChecksum(Hasher& hasher) const;
|
||||
|
||||
private:
|
||||
std::map<std::pair<int, int>, BuildingId> m_owners;
|
||||
};
|
||||
@@ -6,63 +6,13 @@
|
||||
#include <random>
|
||||
#include <set>
|
||||
|
||||
#include "PortGeometry.h"
|
||||
#include "StateChecksum.h"
|
||||
#include "SurfaceMask.h"
|
||||
#include "tracing.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
// Smelter and Reprocessing Plant have no player-selected recipe
|
||||
// (REQ-BLD-SMELTER, REQ-BLD-REPROCESSING). They auto-process whatever inputs
|
||||
// they receive, matching against every recipe of their building type.
|
||||
bool isAutoRecipeBuildingType(BuildingType type)
|
||||
{
|
||||
return type == BuildingType::Smelter
|
||||
|| type == BuildingType::ReprocessingPlant;
|
||||
}
|
||||
|
||||
// Belts, splitters, and tunnel ends keep their runtime data in the belt subsystem
|
||||
// rather than in the Building instance, so placing/removing them must register or
|
||||
// unregister a tile with BeltSystem.
|
||||
bool isBeltSubsystemType(BuildingType type)
|
||||
{
|
||||
return type == BuildingType::Belt
|
||||
|| type == BuildingType::Splitter
|
||||
|| type == BuildingType::TunnelEntry
|
||||
|| type == BuildingType::TunnelExit;
|
||||
}
|
||||
|
||||
// The building body tile that owns an output port, given the port's outside tile
|
||||
// (port.tile) and its facing direction. The virtual output belt occupies this tile
|
||||
// and flows toward port.tile (REQ-MAT-OUTPUT-EMERGE).
|
||||
QPoint outputBodyTile(QPoint portTile, Rotation direction)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case Rotation::East: return portTile + QPoint(-1, 0);
|
||||
case Rotation::West: return portTile + QPoint( 1, 0);
|
||||
case Rotation::North: return portTile + QPoint( 0, 1);
|
||||
case Rotation::South: return portTile + QPoint( 0, -1);
|
||||
}
|
||||
return portTile;
|
||||
}
|
||||
|
||||
// The building body tile an input port feeds into, given the port's outside belt
|
||||
// tile (port.tile) and its inward flow direction. The virtual input belt occupies
|
||||
// this tile and flows from the outer edge (progress 0.0) to the centre (0.5)
|
||||
// (REQ-MAT-INPUT-INTAKE).
|
||||
QPoint inputBodyTile(QPoint portTile, Rotation inwardDirection)
|
||||
{
|
||||
switch (inwardDirection)
|
||||
{
|
||||
case Rotation::East: return portTile + QPoint( 1, 0);
|
||||
case Rotation::West: return portTile + QPoint(-1, 0);
|
||||
case Rotation::North: return portTile + QPoint( 0, -1);
|
||||
case Rotation::South: return portTile + QPoint( 0, 1);
|
||||
}
|
||||
return portTile;
|
||||
}
|
||||
|
||||
// An input belt accepts a new item at progress 0.0 only when it holds fewer than
|
||||
// three items and the entry slot is clear (nothing within a quarter tile of 0.0),
|
||||
// matching the belt packing used elsewhere (REQ-GW-BELT-CAPACITY).
|
||||
@@ -358,7 +308,7 @@ std::optional<BuildingId> BuildingSystem::place(BuildingType type, QPoint anchor
|
||||
for (const QPoint& cell : mask.bodyCells)
|
||||
{
|
||||
const QPoint absCell = anchor + cell;
|
||||
m_tileOccupancy[{absCell.x(), absCell.y()}] = id;
|
||||
m_grid.occupy(absCell, id);
|
||||
}
|
||||
|
||||
// Build construction site.
|
||||
@@ -462,10 +412,7 @@ int BuildingSystem::deconstruct(BuildingId id, Tick currentTick)
|
||||
if (it->id == id)
|
||||
{
|
||||
const BuildingDef* def = m_config.buildings.findBuildingDef(it->type);
|
||||
for (const QPoint& cell : it->bodyCells)
|
||||
{
|
||||
m_tileOccupancy.erase({cell.x(), cell.y()});
|
||||
}
|
||||
m_grid.release(it->bodyCells);
|
||||
m_constructionQueue.erase(it);
|
||||
if (def)
|
||||
{
|
||||
@@ -849,10 +796,7 @@ void BuildingSystem::tickDeconstruction(Tick currentTick)
|
||||
if (it->id != front.id) { continue; }
|
||||
|
||||
const BuildingDef* def = m_config.buildings.findBuildingDef(it->type);
|
||||
for (const QPoint& cell : it->bodyCells)
|
||||
{
|
||||
m_tileOccupancy.erase({cell.x(), cell.y()});
|
||||
}
|
||||
m_grid.release(it->bodyCells);
|
||||
m_buildings.erase(it);
|
||||
if (def)
|
||||
{
|
||||
@@ -988,14 +932,13 @@ bool BuildingSystem::tryDirectCoupleDeposit(BuildingId producerId,
|
||||
const Port& outputPort,
|
||||
const Item& item)
|
||||
{
|
||||
const std::map<std::pair<int, int>, BuildingId>::const_iterator occIt =
|
||||
m_tileOccupancy.find({outputPort.tile.x(), outputPort.tile.y()});
|
||||
if (occIt == m_tileOccupancy.end() || occIt->second == producerId)
|
||||
const std::optional<BuildingId> ownerId = m_grid.findOwner(outputPort.tile);
|
||||
if (!ownerId.has_value() || *ownerId == producerId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Building* consumer = findBuildingMutable(occIt->second);
|
||||
Building* consumer = findBuildingMutable(*ownerId);
|
||||
if (!consumer)
|
||||
{
|
||||
return false; // an unbuilt construction site, or not an operational building
|
||||
@@ -1577,7 +1520,7 @@ std::vector<BuildingSystem::BeltTileInfo> BuildingSystem::getAllBeltTiles() cons
|
||||
|
||||
bool BuildingSystem::isTileOccupied(QPoint tile) const
|
||||
{
|
||||
return m_tileOccupancy.count({tile.x(), tile.y()}) > 0;
|
||||
return m_grid.isOccupied(tile);
|
||||
}
|
||||
|
||||
std::optional<BuildingId> BuildingSystem::findRotateInPlaceTarget(
|
||||
@@ -1598,15 +1541,14 @@ std::optional<BuildingId> BuildingSystem::findRotateInPlaceTarget(
|
||||
|
||||
// All body cells must be occupied by the same entity.
|
||||
const QPoint firstAbs = anchor + mask.bodyCells[0];
|
||||
const auto firstIt = m_tileOccupancy.find({firstAbs.x(), firstAbs.y()});
|
||||
if (firstIt == m_tileOccupancy.end()) { return std::nullopt; }
|
||||
const BuildingId candidateId = firstIt->second;
|
||||
const std::optional<BuildingId> firstOwner = m_grid.findOwner(firstAbs);
|
||||
if (!firstOwner.has_value()) { return std::nullopt; }
|
||||
const BuildingId candidateId = *firstOwner;
|
||||
|
||||
for (const QPoint& rel : mask.bodyCells)
|
||||
{
|
||||
const QPoint abs = anchor + rel;
|
||||
const auto it = m_tileOccupancy.find({abs.x(), abs.y()});
|
||||
if (it == m_tileOccupancy.end() || it->second != candidateId)
|
||||
const std::optional<BuildingId> owner = m_grid.findOwner(anchor + rel);
|
||||
if (!owner.has_value() || *owner != candidateId)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -1766,7 +1708,7 @@ BuildingId BuildingSystem::placeImmediate(BuildingType type,
|
||||
{
|
||||
const QPoint absCell = anchor + cell;
|
||||
building.bodyCells.push_back(absCell);
|
||||
m_tileOccupancy[{absCell.x(), absCell.y()}] = id;
|
||||
m_grid.occupy(absCell, id);
|
||||
}
|
||||
for (const Port& port : mask.outputPorts)
|
||||
{
|
||||
@@ -1801,10 +1743,7 @@ bool BuildingSystem::removeBuilding(BuildingId id)
|
||||
{
|
||||
m_belts.removeTile(it->anchor);
|
||||
}
|
||||
for (const QPoint& cell : it->bodyCells)
|
||||
{
|
||||
m_tileOccupancy.erase({cell.x(), cell.y()});
|
||||
}
|
||||
m_grid.release(it->bodyCells);
|
||||
m_buildings.erase(it);
|
||||
return true;
|
||||
}
|
||||
@@ -1823,18 +1762,12 @@ void BuildingSystem::forEachBuilding(std::function<void(Building&)> fn)
|
||||
void BuildingSystem::registerTileOccupancy(const std::vector<QPoint>& cells,
|
||||
BuildingId ownerPlaceholder)
|
||||
{
|
||||
for (const QPoint& cell : cells)
|
||||
{
|
||||
m_tileOccupancy[{cell.x(), cell.y()}] = ownerPlaceholder;
|
||||
}
|
||||
m_grid.occupy(cells, ownerPlaceholder);
|
||||
}
|
||||
|
||||
void BuildingSystem::unregisterTileOccupancy(const std::vector<QPoint>& cells)
|
||||
{
|
||||
for (const QPoint& cell : cells)
|
||||
{
|
||||
m_tileOccupancy.erase({cell.x(), cell.y()});
|
||||
}
|
||||
m_grid.release(cells);
|
||||
}
|
||||
|
||||
namespace
|
||||
@@ -1943,12 +1876,5 @@ void BuildingSystem::appendChecksum(Hasher& hasher) const
|
||||
for (const ItemType& type : e.splitterFilterB) { hasher.append(type.id); }
|
||||
}
|
||||
|
||||
// std::map iterates in sorted key order.
|
||||
hasher.append(m_tileOccupancy.size());
|
||||
for (const std::pair<const std::pair<int, int>, BuildingId>& entry : m_tileOccupancy)
|
||||
{
|
||||
hasher.append(entry.first.first);
|
||||
hasher.append(entry.first.second);
|
||||
hasher.append(entry.second);
|
||||
}
|
||||
m_grid.appendChecksum(hasher);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "BeltSystem.h"
|
||||
#include "Building.h"
|
||||
#include "BuildingGrid.h"
|
||||
#include "BuildingType.h"
|
||||
#include "BuildingId.h"
|
||||
#include "GameConfig.h"
|
||||
@@ -309,6 +310,7 @@ private:
|
||||
};
|
||||
std::deque<DeconstructionEntry> m_deconstructionQueue;
|
||||
|
||||
// Maps every occupied body-cell coordinate to the entity that owns it.
|
||||
std::map<std::pair<int, int>, BuildingId> m_tileOccupancy;
|
||||
// The authority on which building owns which tile; every placement and removal
|
||||
// path claims and releases its body cells here.
|
||||
BuildingGrid m_grid;
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@ SET(HDRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BeltSystem.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Building.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingConfig.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingGrid.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingSystem.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/EntityHitTest.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ShipLayout.h
|
||||
@@ -36,6 +37,7 @@ SET(SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BeltSlot.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BeltSystem.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingConfig.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingGrid.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingSystem.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/EntityHitTest.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ShipStatsCalculator.cpp
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "HealthComponent.h"
|
||||
#include "HqProxyComponent.h"
|
||||
#include "ItemIconCache.h"
|
||||
#include "PortGeometry.h"
|
||||
#include "PositionComponent.h"
|
||||
#include "RepairBehavior.h"
|
||||
#include "SalvageScrapBehavior.h"
|
||||
@@ -166,18 +167,6 @@ Rotation rotateCounterClockwise(Rotation r)
|
||||
return Rotation::East;
|
||||
}
|
||||
|
||||
QPoint portBodyTile(QPoint portTile, Rotation direction)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case Rotation::East: return portTile + QPoint(-1, 0);
|
||||
case Rotation::West: return portTile + QPoint( 1, 0);
|
||||
case Rotation::North: return portTile + QPoint( 0, 1);
|
||||
case Rotation::South: return portTile + QPoint( 0, -1);
|
||||
}
|
||||
return portTile;
|
||||
}
|
||||
|
||||
// Fill color for a building's status light per its production state
|
||||
// (REQ-UI-STATUS-LIGHT).
|
||||
QColor statusLightFill(ProductionStatus status, const StatusLightVisuals& sl)
|
||||
@@ -1341,7 +1330,7 @@ void GameWorldView::drawBuildings(QPainter& painter)
|
||||
|
||||
for (const Port& port : b.outputPorts)
|
||||
{
|
||||
drawPortGlyph(painter, portBodyTile(port.tile, port.direction),
|
||||
drawPortGlyph(painter, outputBodyTile(port.tile, port.direction),
|
||||
port.direction, bv.outline, /*centered*/ false);
|
||||
}
|
||||
|
||||
@@ -1441,7 +1430,7 @@ void GameWorldView::drawBuildings(QPainter& painter)
|
||||
for (const Port& port : siteMask.outputPorts)
|
||||
{
|
||||
const QPoint absBody = s.anchor
|
||||
+ portBodyTile(port.tile, port.direction);
|
||||
+ outputBodyTile(port.tile, port.direction);
|
||||
drawPortGlyph(painter, absBody, port.direction, bv.outline,
|
||||
/*centered*/ false);
|
||||
}
|
||||
@@ -2215,7 +2204,7 @@ void GameWorldView::drawBuildingGhost(QPainter& painter, BuildingType type,
|
||||
|
||||
for (const Port& port : parsed.outputPorts)
|
||||
{
|
||||
drawPortGlyph(painter, anchorTile + portBodyTile(port.tile, port.direction),
|
||||
drawPortGlyph(painter, anchorTile + outputBodyTile(port.tile, port.direction),
|
||||
port.direction, lineColor, /*centered*/ false);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,20 +84,6 @@ bool hasRecipeSelection(BuildingType type)
|
||||
|| type == BuildingType::Shipyard;
|
||||
}
|
||||
|
||||
// Auto-recipe buildings have no selected recipe; their production is driven by
|
||||
// whatever inputs they receive.
|
||||
bool isAutoRecipeBuilding(BuildingType type)
|
||||
{
|
||||
return type == BuildingType::Smelter
|
||||
|| type == BuildingType::ReprocessingPlant;
|
||||
}
|
||||
|
||||
bool isBeltLike(BuildingType type)
|
||||
{
|
||||
return type == BuildingType::Belt || type == BuildingType::Splitter
|
||||
|| type == BuildingType::TunnelEntry || type == BuildingType::TunnelExit;
|
||||
}
|
||||
|
||||
QString rotationLabel(Rotation r)
|
||||
{
|
||||
switch (r)
|
||||
@@ -313,7 +299,7 @@ void SelectedBuildingPanel::buildSingle(BuildingId id)
|
||||
|
||||
// Belt "Clear" removes items from a live belt tile; a construction site has
|
||||
// none and is not registered with BeltSystem yet, so hide it for sites.
|
||||
if (isBeltLike(type) && !m_singleIsSite)
|
||||
if (isBeltSubsystemType(type) && !m_singleIsSite)
|
||||
{
|
||||
m_clearBeltBtn->show();
|
||||
}
|
||||
@@ -394,7 +380,7 @@ void SelectedBuildingPanel::refreshBuffers(const Building* b)
|
||||
// Auto-recipe buildings (Smelter, Reprocessing Plant) have no selected
|
||||
// recipe; while a cycle runs, resolve the recipe actually in production so
|
||||
// the cycle time and progress can be shown (REQ-UI-PRODUCTION-PROGRESS).
|
||||
if (!recipe && isAutoRecipeBuilding(b->type) && b->production.has_value())
|
||||
if (!recipe && isAutoRecipeBuildingType(b->type) && b->production.has_value())
|
||||
{
|
||||
recipe = m_config->recipes.findRecipeDef(b->production->recipeId, b->type);
|
||||
}
|
||||
@@ -488,7 +474,7 @@ void SelectedBuildingPanel::refreshBuffers(const Building* b)
|
||||
}
|
||||
|
||||
if (isProductionBuilding(b->type)
|
||||
&& (recipe || shipDef || isAutoRecipeBuilding(b->type)))
|
||||
&& (recipe || shipDef || isAutoRecipeBuildingType(b->type)))
|
||||
{
|
||||
if (recipe || shipDef)
|
||||
{
|
||||
@@ -683,7 +669,7 @@ void SelectedBuildingPanel::buildMulti(const std::vector<BuildingId>& ids)
|
||||
{
|
||||
text += buildingTypeName(entry.first) + " x "
|
||||
+ QString::number(entry.second) + "\n";
|
||||
if (isBeltLike(entry.first))
|
||||
if (isBeltSubsystemType(entry.first))
|
||||
{
|
||||
hasBelt = true;
|
||||
}
|
||||
@@ -832,7 +818,7 @@ void SelectedBuildingPanel::onClearBelt()
|
||||
for (BuildingId id : m_selectedBuildingIds)
|
||||
{
|
||||
const Building* b = m_sim->getBuildings().findBuilding(id);
|
||||
if (b && isBeltLike(b->type))
|
||||
if (b && isBeltSubsystemType(b->type))
|
||||
{
|
||||
for (const QPoint& cell : b->bodyCells)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user