| 20 | } |
| 21 | |
| 22 | Maybe<pair<List<RectI>, Set<Vec2I>>> MicroDungeonFactory::generate(RectI const& bounds, |
| 23 | String const& dungeonName, |
| 24 | Vec2I const& position, |
| 25 | uint64_t seed, |
| 26 | float threatLevel, |
| 27 | DungeonGeneratorWorldFacadePtr facade, |
| 28 | bool forcePlacement) { |
| 29 | Dungeon::DungeonGeneratorWriter writer(facade, {}, {}); |
| 30 | |
| 31 | if (m_generating) |
| 32 | throw DungeonException("Not reentrant."); |
| 33 | |
| 34 | m_generating = true; |
| 35 | auto generatingGuard = finally([this]() { m_generating = false; }); |
| 36 | |
| 37 | DungeonGenerator dungeonGenerator(dungeonName, seed, threatLevel, BiomeMicroDungeonId); |
| 38 | |
| 39 | try { |
| 40 | // don't bother scanning around because its used in a bruteforce manner for now. |
| 41 | // try to stay a bit stable generation wise, maybe trash the cache after a sector is done ? |
| 42 | |
| 43 | auto anchorPart = dungeonGenerator.pickAnchor(); |
| 44 | if (!anchorPart) { |
| 45 | Logger::debug("No valid anchor piece found for microdungeon at {}, skipping", position); |
| 46 | return {}; |
| 47 | } |
| 48 | |
| 49 | if (forcePlacement) { |
| 50 | return dungeonGenerator.buildDungeon(anchorPart, position - anchorPart->anchorPoint(), &writer, forcePlacement); |
| 51 | } else { |
| 52 | for (int dy : m_placementshifts) { |
| 53 | auto pos = position - anchorPart->anchorPoint() + Vec2I{0, dy}; |
| 54 | if (!bounds.contains(pos) || !bounds.contains(pos + Vec2I{anchorPart->size()} - Vec2I{1, 1})) |
| 55 | continue; |
| 56 | |
| 57 | bool collision = false; |
| 58 | anchorPart->forEachTile([&](Vec2I tilePos, Dungeon::Tile const& tile) -> bool { |
| 59 | if (tile.usesPlaces()) { |
| 60 | if (facade->getDungeonIdAt(pos + tilePos) != NoDungeonId) { |
| 61 | collision = true; |
| 62 | return true; |
| 63 | } |
| 64 | } |
| 65 | return false; |
| 66 | }); |
| 67 | |
| 68 | if (!collision && anchorPart->canPlace(pos, &writer)) { |
| 69 | return dungeonGenerator.buildDungeon(anchorPart, pos, &writer, forcePlacement); |
| 70 | } |
| 71 | } |
| 72 | } |
| 73 | } catch (std::exception const& e) { |
| 74 | throw DungeonException(strf("Error generating microdungeon named '{}'", dungeonGenerator.definition()->name()), e); |
| 75 | } |
| 76 | |
| 77 | return {}; |
| 78 | } |
| 79 |
no test coverage detected