diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/game/StarMicroDungeon.cpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/game/StarMicroDungeon.cpp')
-rw-r--r-- | source/game/StarMicroDungeon.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/source/game/StarMicroDungeon.cpp b/source/game/StarMicroDungeon.cpp new file mode 100644 index 0000000..646e8b1 --- /dev/null +++ b/source/game/StarMicroDungeon.cpp @@ -0,0 +1,80 @@ +#include "StarMicroDungeon.hpp" +#include "StarRoot.hpp" +#include "StarInterpolation.hpp" +#include "StarLogging.hpp" +#include "StarDungeonGenerator.hpp" + +namespace Star { + +// Placed on server so it can keep a cacheing system which allows for a quick +// scan if a piece fits. + +MicroDungeonFactory::MicroDungeonFactory() { + m_generating = false; + + m_placementshifts.push_back(0); + for (int i = 1; i < 4; ++i) + m_placementshifts.push_back(i); + for (int i = 1; i < 4; ++i) + m_placementshifts.push_back(-i); +} + +Maybe<pair<List<RectI>, Set<Vec2I>>> MicroDungeonFactory::generate(RectI const& bounds, + String const& dungeonName, + Vec2I const& position, + uint64_t seed, + float threatLevel, + DungeonGeneratorWorldFacadePtr facade, + bool forcePlacement) { + Dungeon::DungeonGeneratorWriter writer(facade, {}, {}); + + if (m_generating) + throw DungeonException("Not reentrant."); + + m_generating = true; + auto generatingGuard = finally([this]() { m_generating = false; }); + + DungeonGenerator dungeonGenerator(dungeonName, seed, threatLevel, BiomeMicroDungeonId); + + try { + // don't bother scanning around because its used in a bruteforce manner for now. + // try to stay a bit stable generation wise, maybe trash the cache after a sector is done ? + + auto anchorPart = dungeonGenerator.pickAnchor(); + if (!anchorPart) { + Logger::debug("No valid anchor piece found for microdungeon at %s, skipping", position); + return {}; + } + + if (forcePlacement) { + return dungeonGenerator.buildDungeon(anchorPart, position - anchorPart->anchorPoint(), &writer, forcePlacement); + } else { + for (int dy : m_placementshifts) { + auto pos = position - anchorPart->anchorPoint() + Vec2I{0, dy}; + if (!bounds.contains(pos) || !bounds.contains(pos + Vec2I{anchorPart->size()} - Vec2I{1, 1})) + continue; + + bool collision = false; + anchorPart->forEachTile([&](Vec2I tilePos, Dungeon::Tile const& tile) -> bool { + if (tile.usesPlaces()) { + if (facade->getDungeonIdAt(pos + tilePos) != NoDungeonId) { + collision = true; + return true; + } + } + return false; + }); + + if (!collision && anchorPart->canPlace(pos, &writer)) { + return dungeonGenerator.buildDungeon(anchorPart, pos, &writer, forcePlacement); + } + } + } + } catch (std::exception const& e) { + throw DungeonException(strf("Error generating microdungeon named '%s'", dungeonGenerator.definition()->name()), e); + } + + return {}; +} + +} |