store belts as buildings and fix issue that belts could not be selected

This commit is contained in:
2026-04-24 21:09:28 +02:00
parent fff5d43352
commit 55997ef851
4 changed files with 102 additions and 133 deletions

View File

@@ -241,24 +241,6 @@ EntityId BuildingSystem::place(BuildingType type, QPoint anchor,
int BuildingSystem::demolish(EntityId id)
{
// Belt / splitter?
const std::map<EntityId, BeltEntry>::iterator beltIt = m_beltEntities.find(id);
if (beltIt != m_beltEntities.end())
{
const QPoint tile = beltIt->second.tile;
const BuildingType btype = beltIt->second.type;
m_belts.removeTile(tile);
m_tileOccupancy.erase({tile.x(), tile.y()});
m_beltEntities.erase(beltIt);
const BuildingDef* def = findBuildingDef(btype);
if (def)
{
return def->cost * m_config.world.refundPercentage / 100;
}
return 0;
}
// Construction queue?
for (std::deque<ConstructionSite>::iterator it = m_constructionQueue.begin();
it != m_constructionQueue.end();
@@ -287,6 +269,10 @@ int BuildingSystem::demolish(EntityId id)
{
if (it->id == id)
{
if (it->type == BuildingType::Belt || it->type == BuildingType::Splitter)
{
m_belts.removeTile(it->anchor);
}
const BuildingDef* def = findBuildingDef(it->type);
for (const QPoint& cell : it->bodyCells)
{
@@ -381,71 +367,65 @@ void BuildingSystem::tickConstruction(Tick currentTick)
return;
}
// Promote construction site — belts/splitters go into BeltSystem, others become Buildings.
// Promote construction site to an operational Building.
const BuildingDef* def = findBuildingDef(front.type);
const ParsedSurfaceMask mask = parseSurfaceMask(
def ? def->surfaceMask : std::vector<std::string>{},
front.rotation);
Building building;
building.id = front.id;
building.anchor = front.anchor;
building.footprint = front.footprint;
building.rotation = front.rotation;
building.type = front.type;
building.hp = 100.0f;
building.maxHp = 100.0f;
building.recipeId = front.recipeId;
for (const QPoint& cell : mask.bodyCells)
{
building.bodyCells.push_back(front.anchor + cell);
}
for (const Port& port : mask.outputPorts)
{
Port absPort;
absPort.tile = front.anchor + port.tile;
absPort.direction = port.direction;
building.outputPorts.push_back(absPort);
}
building.inputPorts = computeInputPorts(building);
if (!building.recipeId.empty())
{
if (building.type == BuildingType::Shipyard)
{
initShipyardBuffers(building);
}
else
{
const RecipeDef* recipe = findRecipe(building.recipeId, building.type);
if (recipe)
{
initBuffers(building, *recipe);
}
}
}
// Register with BeltSystem before the move (mask stays valid).
if (front.type == BuildingType::Belt)
{
m_belts.placeBelt(front.anchor, front.rotation);
m_beltEntities[front.id] = BeltEntry{front.anchor, BuildingType::Belt, front.rotation, front.rotation};
}
else if (front.type == BuildingType::Splitter)
{
const BuildingDef* def = findBuildingDef(front.type);
assert(def != nullptr);
const ParsedSurfaceMask mask = parseSurfaceMask(def->surfaceMask, front.rotation);
assert(mask.outputPorts.size() >= 2);
const Rotation outA = mask.outputPorts[0].direction;
const Rotation outB = mask.outputPorts[1].direction;
m_belts.placeSplitter(front.anchor, outA, outB);
m_beltEntities[front.id] = BeltEntry{front.anchor, BuildingType::Splitter, outA, outB};
m_belts.placeSplitter(front.anchor,
mask.outputPorts[0].direction,
mask.outputPorts[1].direction);
}
else
{
const BuildingDef* def = findBuildingDef(front.type);
const ParsedSurfaceMask mask = parseSurfaceMask(
def ? def->surfaceMask : std::vector<std::string>{},
front.rotation);
Building building;
building.id = front.id;
building.anchor = front.anchor;
building.footprint = front.footprint;
building.rotation = front.rotation;
building.type = front.type;
building.hp = 100.0f;
building.maxHp = 100.0f;
building.recipeId = front.recipeId;
for (const QPoint& cell : mask.bodyCells)
{
building.bodyCells.push_back(front.anchor + cell);
}
for (const Port& port : mask.outputPorts)
{
Port absPort;
absPort.tile = front.anchor + port.tile;
absPort.direction = port.direction;
building.outputPorts.push_back(absPort);
}
building.inputPorts = computeInputPorts(building);
if (!building.recipeId.empty())
{
if (building.type == BuildingType::Shipyard)
{
initShipyardBuffers(building);
}
else
{
const RecipeDef* recipe = findRecipe(building.recipeId, building.type);
if (recipe)
{
initBuffers(building, *recipe);
}
}
}
m_buildings.push_back(std::move(building));
}
m_buildings.push_back(std::move(building));
m_constructionQueue.pop_front();
@@ -774,15 +754,30 @@ std::vector<ConstructionSite> BuildingSystem::allSites() const
std::vector<BuildingSystem::BeltTileInfo> BuildingSystem::allBeltTiles() const
{
std::vector<BeltTileInfo> result;
result.reserve(m_beltEntities.size());
for (const std::map<EntityId, BeltEntry>::value_type& kv : m_beltEntities)
for (const Building& b : m_buildings)
{
if (b.type != BuildingType::Belt && b.type != BuildingType::Splitter)
{
continue;
}
BeltTileInfo info;
info.id = kv.first;
info.tile = kv.second.tile;
info.type = kv.second.type;
info.directionA = kv.second.directionA;
info.directionB = kv.second.directionB;
info.id = b.id;
info.tile = b.bodyCells.empty() ? b.anchor : b.bodyCells[0];
info.type = b.type;
if (!b.outputPorts.empty())
{
info.directionA = b.outputPorts[0].direction;
info.directionB = b.outputPorts[0].direction;
}
else
{
info.directionA = b.rotation;
info.directionB = b.rotation;
}
if (b.type == BuildingType::Splitter && b.outputPorts.size() >= 2)
{
info.directionB = b.outputPorts[1].direction;
}
result.push_back(info);
}
return result;
@@ -907,6 +902,10 @@ bool BuildingSystem::removeBuilding(EntityId id)
{
if (it->id == id)
{
if (it->type == BuildingType::Belt || it->type == BuildingType::Splitter)
{
m_belts.removeTile(it->anchor);
}
for (const QPoint& cell : it->bodyCells)
{
m_tileOccupancy.erase({cell.x(), cell.y()});