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

summaryrefslogtreecommitdiff
path: root/source/game/StarCelestialDatabase.hpp
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/StarCelestialDatabase.hpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/game/StarCelestialDatabase.hpp')
-rw-r--r--source/game/StarCelestialDatabase.hpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/source/game/StarCelestialDatabase.hpp b/source/game/StarCelestialDatabase.hpp
new file mode 100644
index 0000000..ac5b42b
--- /dev/null
+++ b/source/game/StarCelestialDatabase.hpp
@@ -0,0 +1,228 @@
+#ifndef STAR_CELESTIAL_DATABASE_HPP
+#define STAR_CELESTIAL_DATABASE_HPP
+
+#include "StarRect.hpp"
+#include "StarTtlCache.hpp"
+#include "StarWeightedPool.hpp"
+#include "StarThread.hpp"
+#include "StarBTreeDatabase.hpp"
+#include "StarCelestialTypes.hpp"
+#include "StarPerlin.hpp"
+
+namespace Star {
+
+STAR_CLASS(CelestialDatabase);
+STAR_CLASS(CelestialMasterDatabase);
+STAR_CLASS(CelestialSlaveDatabase);
+
+class CelestialDatabase {
+public:
+ virtual ~CelestialDatabase();
+
+ // The x/y region of usable worlds.
+ RectI xyRange() const;
+
+ // The maximum number of bodies that can orbit a single system center /
+ // planetary body. Orbital numbers are up to this number of levels
+ // *inclusive*, so planetary orbit numbers would be 1-N, and planetary orbit
+ // "0", in this system, would refer to the center of the planetary system
+ // itself, e.g. a star. In the same way, satellites around a planetary
+ // object are numbered 1-N, and 0 refers to the planetary object itself.
+ int planetOrbitalLevels() const;
+ int satelliteOrbitalLevels() const;
+
+ // The following methods are allowed to return no information even in the
+ // case of valid coordinates, due to delayed loading.
+
+ virtual Maybe<CelestialParameters> parameters(CelestialCoordinate const& coordinate) = 0;
+ virtual Maybe<String> name(CelestialCoordinate const& coordinate) = 0;
+
+ virtual Maybe<bool> hasChildren(CelestialCoordinate const& coordinate) = 0;
+ virtual List<CelestialCoordinate> children(CelestialCoordinate const& coordinate) = 0;
+ virtual List<int> childOrbits(CelestialCoordinate const& coordinate) = 0;
+
+ // Return all valid system coordinates in the given x/y range. All systems
+ // are guaranteed to have unique x/y coordinates, and are meant to be viewed
+ // from the top in 2d. The z-coordinate is there simpy as a validation
+ // parameter.
+ virtual List<CelestialCoordinate> scanSystems(RectI const& region, Maybe<StringSet> const& includedTypes = {}) = 0;
+ virtual List<pair<Vec2I, Vec2I>> scanConstellationLines(RectI const& region) = 0;
+
+ // Returns false if part or all of the specified region is not loaded. This
+ // is only relevant for calls to scanSystems and scanConstellationLines, and
+ // does not imply that each individual system in the given region is fully
+ // loaded with all planets moons etc, only that scanSystem and
+ // scanConstellationLines are not waiting on missing data.
+ virtual bool scanRegionFullyLoaded(RectI const& region) = 0;
+
+protected:
+ Vec2I chunkIndexFor(CelestialCoordinate const& coordinate) const;
+ Vec2I chunkIndexFor(Vec2I const& systemXY) const;
+
+ // Returns the chunk indexes for the given region.
+ List<Vec2I> chunkIndexesFor(RectI const& region) const;
+
+ // Returns the region of the given chunk.
+ RectI chunkRegion(Vec2I const& chunkIndex) const;
+
+ // m_baseInformation should only be modified in the constructor, as it is not
+ // thread protected.
+ CelestialBaseInformation m_baseInformation;
+};
+
+class CelestialMasterDatabase : public CelestialDatabase {
+public:
+ CelestialMasterDatabase(Maybe<String> databaseFile = {});
+
+ CelestialBaseInformation baseInformation() const;
+ CelestialResponse respondToRequest(CelestialRequest const& requests);
+
+ // Unload data that has not been used in the configured TTL time, and
+ // periodically commit to the underlying database if it is in use.
+ void cleanupAndCommit();
+
+ // Does this coordinate point to a valid existing object?
+ bool coordinateValid(CelestialCoordinate const& coordinate);
+
+ // Find a planetary or satellite object randomly throughout the entire
+ // celestial space that satisfies the given parameters. May fail to find
+ // anything, though with the defaults this is vanishingly unlikely.
+ Maybe<CelestialCoordinate> findRandomWorld(unsigned tries = 10, unsigned trySpatialRange = 50,
+ function<bool(CelestialCoordinate)> filter = {}, Maybe<uint64_t> seed = {});
+
+ // CelestialMasterDatabase always returns actual data, as it does just in
+ // time generation.
+
+ Maybe<CelestialParameters> parameters(CelestialCoordinate const& coordinate) override;
+ Maybe<String> name(CelestialCoordinate const& coordinate) override;
+
+ Maybe<bool> hasChildren(CelestialCoordinate const& coordinate) override;
+ List<CelestialCoordinate> children(CelestialCoordinate const& coordinate) override;
+ List<int> childOrbits(CelestialCoordinate const& coordinate) override;
+
+ List<CelestialCoordinate> scanSystems(RectI const& region, Maybe<StringSet> const& includedTypes = {}) override;
+ List<pair<Vec2I, Vec2I>> scanConstellationLines(RectI const& region) override;
+
+ bool scanRegionFullyLoaded(RectI const& region) override;
+
+ // overwrite the celestial parameters for the world at the given celestial coordinate
+ void updateParameters(CelestialCoordinate const& coordinate, CelestialParameters const& parameters);
+
+protected:
+ struct SatelliteType {
+ String typeName;
+ Json baseParameters;
+ JsonArray variationParameters;
+ JsonObject orbitParameters;
+ };
+
+ struct PlanetaryType {
+ String typeName;
+ float satelliteProbability;
+ size_t maxSatelliteCount;
+ Json baseParameters;
+ JsonArray variationParameters;
+ JsonObject orbitParameters;
+ };
+
+ struct SystemType {
+ String typeName;
+ bool constellationCapable;
+ Json baseParameters;
+ JsonArray variationParameters;
+ List<CelestialOrbitRegion> orbitRegions;
+ };
+
+ struct GenerationInformation {
+ float systemProbability;
+ float constellationProbability;
+ Vec2U constellationLineCountRange;
+ unsigned constellationMaxTries;
+ float maximumConstellationLineLength;
+ float minimumConstellationLineLength;
+ float minimumConstellationMagnitude;
+ float minimumConstellationLineCloseness;
+
+ Map<String, SystemType> systemTypes;
+
+ PerlinD systemTypePerlin;
+ Json systemTypeBins;
+
+ StringMap<PlanetaryType> planetaryTypes;
+ StringMap<SatelliteType> satelliteTypes;
+
+ StringList planetarySuffixes;
+ StringList satelliteSuffixes;
+
+ WeightedPool<String> systemPrefixNames;
+ WeightedPool<String> systemNames;
+ WeightedPool<String> systemSuffixNames;
+ };
+
+ static Maybe<CelestialOrbitRegion> orbitRegion(
+ List<CelestialOrbitRegion> const& orbitRegions, int planetaryOrbitNumber);
+
+ CelestialChunk const& getChunk(Vec2I const& chunkLocation);
+
+ CelestialChunk produceChunk(Vec2I const& chunkLocation) const;
+ Maybe<pair<CelestialParameters, HashMap<int, CelestialPlanet>>> produceSystem(
+ RandomSource& random, Vec3I const& location) const;
+ List<CelestialConstellation> produceConstellations(
+ RandomSource& random, List<Vec2I> const& constellationCandidates) const;
+
+ GenerationInformation m_generationInformation;
+
+ mutable RecursiveMutex m_mutex;
+
+ HashTtlCache<Vec2I, CelestialChunk> m_chunkCache;
+ BTreeSha256Database m_database;
+
+ float m_commitInterval;
+ Timer m_commitTimer;
+};
+
+class CelestialSlaveDatabase : public CelestialDatabase {
+public:
+ CelestialSlaveDatabase(CelestialBaseInformation baseInformation);
+
+ // Signal that the given region should be requested from the master database.
+ void signalRegion(RectI const& region);
+
+ // Signal that the given system should be fully requested from the master
+ // database.
+ void signalSystem(CelestialCoordinate const& system);
+
+ // There is an internal activity time for chunk requests to live to prevent
+ // repeatedly requesting the same set of chunks.
+ List<CelestialRequest> pullRequests();
+ void pushResponses(List<CelestialResponse> responses);
+
+ // Unload data that has not been used in the configured TTL time.
+ void cleanup();
+
+ Maybe<CelestialParameters> parameters(CelestialCoordinate const& coordinate) override;
+ Maybe<String> name(CelestialCoordinate const& coordinate) override;
+
+ Maybe<bool> hasChildren(CelestialCoordinate const& coordinate) override;
+ List<CelestialCoordinate> children(CelestialCoordinate const& coordinate) override;
+ List<int> childOrbits(CelestialCoordinate const& coordinate) override;
+
+ List<CelestialCoordinate> scanSystems(RectI const& region, Maybe<StringSet> const& includedTypes = {}) override;
+ List<pair<Vec2I, Vec2I>> scanConstellationLines(RectI const& region) override;
+
+ bool scanRegionFullyLoaded(RectI const& region) override;
+
+ void invalidateCacheFor(CelestialCoordinate const& coordinate);
+
+private:
+ float m_requestTimeout;
+
+ mutable RecursiveMutex m_mutex;
+ HashTtlCache<Vec2I, CelestialChunk> m_chunkCache;
+ HashMap<Vec2I, Timer> m_pendingChunkRequests;
+ HashMap<Vec3I, Timer> m_pendingSystemRequests;
+};
+
+}
+
+#endif