Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/StarMicroDungeon.cpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
commit6352e8e3196f78388b6c771073f9e03eaa612673 (patch)
treee23772f79a7fbc41bc9108951e9e136857484bf4 /source/game/StarMicroDungeon.cpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/game/StarMicroDungeon.cpp')
-rw-r--r--source/game/StarMicroDungeon.cpp80
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 {};
+}
+
+}