| 1455 | } |
| 1456 | |
| 1457 | pair<List<RectI>, Set<Vec2I>> DungeonGenerator::buildDungeon(Dungeon::PartConstPtr anchor, Vec2I basePos, Dungeon::DungeonGeneratorWriter* writer, bool forcePlacement) { |
| 1458 | writer->reset(); |
| 1459 | |
| 1460 | Deque<std::pair<Dungeon::Part const*, Vec2I>> openSet; |
| 1461 | StringMap<int> placementCounter; |
| 1462 | Set<Vec2I> modifiedTiles; |
| 1463 | Set<Vec2I> preserveTiles; |
| 1464 | int piecesPlaced = 0; |
| 1465 | |
| 1466 | Logger::debug("Placing dungeon entrance at {}", basePos); |
| 1467 | |
| 1468 | auto placePart = [&](Dungeon::Part const* part, Vec2I const& placePos) { |
| 1469 | Set<Vec2I> clearTileEntityPositions; |
| 1470 | part->forEachTile([&](Vec2I tilePos, Dungeon::Tile const& tile) -> bool { |
| 1471 | if (tile.modifiesPlaces()) |
| 1472 | clearTileEntityPositions.insert(writer->wrapPosition(placePos + tilePos)); |
| 1473 | return false; |
| 1474 | }); |
| 1475 | auto partBounds = RectI::withSize(placePos, Vec2I(part->size())); |
| 1476 | writer->clearTileEntities(partBounds, clearTileEntityPositions, part->clearAnchoredObjects()); |
| 1477 | |
| 1478 | if (part->markDungeonId()) |
| 1479 | writer->setMarkDungeonId(m_dungeonId); |
| 1480 | else |
| 1481 | writer->setMarkDungeonId(); |
| 1482 | |
| 1483 | part->place(placePos, preserveTiles, writer); |
| 1484 | writer->finishPart(); |
| 1485 | |
| 1486 | part->forEachTile([&](Vec2I tilePos, Dungeon::Tile const& tile) -> bool { |
| 1487 | if (tile.usesPlaces()) |
| 1488 | preserveTiles.insert(placePos + tilePos); |
| 1489 | if (tile.modifiesPlaces()) |
| 1490 | modifiedTiles.insert(placePos + tilePos); |
| 1491 | return false; |
| 1492 | }); |
| 1493 | |
| 1494 | openSet.append({part, placePos}); |
| 1495 | |
| 1496 | placementCounter[part->name()]++; |
| 1497 | piecesPlaced++; |
| 1498 | |
| 1499 | Logger::debug("placed {}", part->name()); |
| 1500 | }; |
| 1501 | |
| 1502 | placePart(anchor.get(), basePos); |
| 1503 | |
| 1504 | Vec2I origin = basePos + Vec2I(anchor->size()) / 2; |
| 1505 | |
| 1506 | Set<Vec2I> closedConnectors; |
| 1507 | while (openSet.size()) { |
| 1508 | Dungeon::Part const* parentPart = openSet.first().first; |
| 1509 | Vec2I parentPos = openSet.first().second; |
| 1510 | openSet.takeFirst(); |
| 1511 | Logger::debug("Trying to add part {} at {} connectors: {}", parentPart->name(), parentPos, parentPart->connections().size()); |
| 1512 | for (size_t i = 0; i < parentPart->connections().size(); i++) { |
| 1513 | auto connector = parentPart->connections()[i]; |
| 1514 | Vec2I connectorPos = parentPos + connector->offset(); |
no test coverage detected