fix issue where construction sites could be placed outside of game world and add tests
This commit is contained in:
@@ -235,12 +235,18 @@ std::vector<Item> BuildingSystem::rollReprocessingOutput(const RecipeDef& recipe
|
||||
BuildingId BuildingSystem::place(BuildingType type, QPoint anchor,
|
||||
Rotation rotation, Tick currentTick)
|
||||
{
|
||||
const BuildingId id = m_allocateBuildingId();
|
||||
|
||||
const BuildingDef* def = findBuildingDef(type);
|
||||
assert(def != nullptr);
|
||||
const ParsedSurfaceMask mask = parseSurfaceMask(def->surfaceMask, rotation);
|
||||
|
||||
// Reject placements that fall outside the world (REQ-BLD-PLACE-VALID).
|
||||
if (!bodyCellsWithinWorldBounds(mask.bodyCells, anchor))
|
||||
{
|
||||
return kInvalidBuildingId;
|
||||
}
|
||||
|
||||
const BuildingId id = m_allocateBuildingId();
|
||||
|
||||
// Record tile occupancy for body cells.
|
||||
for (const QPoint& cell : mask.bodyCells)
|
||||
{
|
||||
@@ -270,6 +276,70 @@ BuildingId BuildingSystem::place(BuildingType type, QPoint anchor,
|
||||
return id;
|
||||
}
|
||||
|
||||
bool BuildingSystem::bodyCellsWithinWorldBounds(const std::vector<QPoint>& bodyCells,
|
||||
QPoint anchor) const
|
||||
{
|
||||
const int heightTiles = m_config.world.heightTiles;
|
||||
const int leftEdgeX = -m_config.world.regions.asteroidWidth_tiles;
|
||||
for (const QPoint& cell : bodyCells)
|
||||
{
|
||||
const QPoint worldCell = anchor + cell;
|
||||
if (worldCell.y() < 0 || worldCell.y() >= heightTiles)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (worldCell.x() < leftEdgeX)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BuildingSystem::isPlacementValid(BuildingType type, QPoint anchor,
|
||||
Rotation rotation) const
|
||||
{
|
||||
const BuildingDef* def = findBuildingDef(type);
|
||||
if (def == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const ParsedSurfaceMask mask = parseSurfaceMask(def->surfaceMask, rotation);
|
||||
|
||||
if (!bodyCellsWithinWorldBounds(mask.bodyCells, anchor))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Terrain: ship-dock (S) cells must sit in space (x >= 0); all other body
|
||||
// (A) cells must sit on the asteroid (x < 0). (REQ-BLD-PLACE-VALID)
|
||||
for (const QPoint& cell : mask.bodyCells)
|
||||
{
|
||||
const QPoint worldCell = anchor + cell;
|
||||
bool isShipDock = false;
|
||||
for (const QPoint& dock : mask.shipDockCells)
|
||||
{
|
||||
if (dock == cell)
|
||||
{
|
||||
isShipDock = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isShipDock)
|
||||
{
|
||||
if (worldCell.x() < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (worldCell.x() >= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Demolish
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user