#pragma once #include #include #include #include #include #include "typedefs.hpp" #include "maths/Heightmap.hpp" #include "StructurePlacement.hpp" class Content; class VoxelFragment; struct GeneratorDef; struct VoxelStructureMeta { std::string name; }; struct BlocksLayer { /// @brief Layer block std::string block; /// @brief Layer height. -1 is resizeable layer int height; /// @brief Layer can present under the sea level (default: true) else will /// extend the next layer bool belowSeaLevel; struct { /// @brief Layer block index blockid_t id; } rt; }; /// @brief Set of blocks layers with additional info struct BlocksLayers { std::vector layers; /// @brief Total height of all layers after the resizeable one uint lastLayersHeight; }; struct BiomeParameter { /// @brief Central parameter value for the biome float value; /// @brief Parameter score multiplier /// (the higher the weight, the greater the chance of biome choosing) float weight; }; struct WeightedEntry { std::string name; float weight; struct { size_t id; } rt; bool operator>(const WeightedEntry& other) const { return weight > other.weight; } }; struct BiomeElementList { static inline float MIN_CHANCE = 1e-6f; /// @brief Entries sorted by weight descending. std::vector entries; /// @brief Sum of weight values float weightsSum = 0.0f; /// @brief Value generation chance float chance; BiomeElementList() {} BiomeElementList(std::vector entries, float chance) : entries(entries), chance(chance) { for (const auto& entry : entries) { weightsSum += entry.weight; } } /// @brief Choose value based on weight /// @param rand some random value in range [0, 1) /// @return *.index of chosen value inline size_t choose(float rand, size_t def=0) const { if (entries.empty() || rand > chance || chance < MIN_CHANCE) { return def; } rand = rand / chance; rand *= weightsSum; for (const auto& entry : entries) { rand -= entry.weight; if (rand <= 0.0f) { return entry.rt.id; } } return entries[entries.size()-1].rt.id; } }; struct Biome { /// @brief Biome name std::string name; std::vector parameters; /// @brief Plant is a single-block structure randomly generating in world BiomeElementList plants; BiomeElementList structures; BlocksLayers groundLayers; BlocksLayers seaLayers; }; /// @brief Generator behaviour and settings interface class GeneratorScript { public: virtual ~GeneratorScript() = default; /// @brief Generates a heightmap with values in range 0..1 /// @param offset position of the heightmap in the world /// @param size size of the heightmap /// @param seed world seed /// @return generated heightmap of given size (can't be nullptr) virtual std::shared_ptr generateHeightmap( const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed) = 0; virtual std::vector> generateParameterMaps( const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed) = 0; virtual std::vector placeStructures( const GeneratorDef& def, const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed, const std::shared_ptr& heightmap) = 0; /// @brief Get generator biomes virtual const std::vector& getBiomes() const = 0; /// @return Number of biome parameters, that biome choosing depending on virtual uint getBiomeParameters() const = 0; /// @return Sea level (top of seaLayers) virtual uint getSeaLevel() const = 0; /// @brief Build the runtime cache /// @param content built content virtual void prepare(const GeneratorDef& def, const Content* content) = 0; }; struct GeneratingVoxelStructure { VoxelStructureMeta meta; std::array, 4> fragments; GeneratingVoxelStructure( VoxelStructureMeta meta, std::unique_ptr structure ); }; /// @brief Generator information struct GeneratorDef { /// @brief Generator full name - packid:name std::string name; std::unique_ptr script; std::unordered_map structuresIndices; std::vector> structures; GeneratorDef(std::string name); GeneratorDef(const GeneratorDef&) = delete; };