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/StarCelestialDatabase.hpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/game/StarCelestialDatabase.hpp')
-rw-r--r-- | source/game/StarCelestialDatabase.hpp | 228 |
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 |