From af485dd7cba63869d6553d59a2f628e5c1d2bd4e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 18 Aug 2024 01:30:59 +0300 Subject: [PATCH] add sea_layers --- res/generators/default.lua | 9 ++-- src/logic/scripting/scripting.cpp | 43 ++++++++++++++++- src/world/generator/GeneratorDef.hpp | 2 + src/world/generator/WorldGenerator.cpp | 64 +++++++++++++++----------- 4 files changed, 86 insertions(+), 32 deletions(-) diff --git a/res/generators/default.lua b/res/generators/default.lua index 22f7e9a0..d77fb9f1 100644 --- a/res/generators/default.lua +++ b/res/generators/default.lua @@ -1,5 +1,9 @@ sea_level = 64 +sea_layers = { + {block="base:water", height=-1}, +} + layers = { {block="base:grass_block", height=1, below_sea_level=false}, {block="base:dirt", height=5, below_sea_level=false}, @@ -20,7 +24,7 @@ local function _generate_heightmap(x, y, w, h, seed, s) map:noise({x, y}, 0.8*s, 4, 0.04) map:cellnoise({x, y}, 0.1*s, 3, 0.7, umap, vmap) map:mul(0.5) - map:add(0.3) + map:add(0.5) local rivermap = Heightmap(w, h) rivermap.noiseSeed = seed @@ -50,6 +54,3 @@ function generate_heightmap(x, y, w, h, seed) map:crop(0, 0, w, h) return map end - -local map = generate_heightmap(0, 0, 1024, 1024, 0) -map:dump("heightmap.png") diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 572c2ce2..334e7923 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -688,17 +688,23 @@ void scripting::load_entity_component( class LuaGeneratorScript : public GeneratorScript { scriptenv env; std::vector layers; + std::vector seaLayers; uint lastLayersHeight; + uint lastSeaLayersHeight; uint seaLevel; public: LuaGeneratorScript( scriptenv env, - std::vector layers, + std::vector layers, + std::vector seaLayers, uint lastLayersHeight, + uint lastSeaLayersHeight, uint seaLevel) : env(std::move(env)), layers(std::move(layers)), + seaLayers(std::move(seaLayers)), lastLayersHeight(lastLayersHeight), + lastSeaLayersHeight(lastSeaLayersHeight), seaLevel(seaLevel) {} @@ -725,15 +731,26 @@ public: for (auto& layer : layers) { layer.rt.id = content->blocks.require(layer.block).rt.id; } + for (auto& layer : seaLayers) { + layer.rt.id = content->blocks.require(layer.block).rt.id; + } } const std::vector& getLayers() const override { return layers; } + const std::vector& getSeaLayers() const override { + return seaLayers; + } + uint getLastLayersHeight() const override { return lastLayersHeight; } + + uint getLastSeaLayersHeight() const override { + return lastSeaLayersHeight; + } uint getSeaLevel() const override { return seaLevel; @@ -784,9 +801,12 @@ std::unique_ptr scripting::load_generator( } uint lastLayersHeight = 0; + uint lastSeaLayersHeight = 0; bool hasResizeableLayer = false; + bool hasResizeableSeaLayer = false; std::vector layers; + std::vector seaLayers; if (lua::getfield(L, "layers")) { int len = lua::objlen(L, -1); for (int i = 1; i <= len; i++) { @@ -803,9 +823,28 @@ std::unique_ptr scripting::load_generator( } lua::pop(L); } + if (lua::getfield(L, "sea_layers")) { + int len = lua::objlen(L, -1); + for (int i = 1; i <= len; i++) { + lua::rawgeti(L, i); + try { + seaLayers.push_back( + load_layer(L, -1, lastSeaLayersHeight, hasResizeableSeaLayer)); + } catch (const std::runtime_error& err) { + lua::pop(L, 2); + throw std::runtime_error( + "sea layer #"+std::to_string(i)+": "+err.what()); + } + lua::pop(L); + } + lua::pop(L); + } lua::pop(L); return std::make_unique( - std::move(env), std::move(layers), lastLayersHeight, seaLevel); + std::move(env), + std::move(layers), std::move(seaLayers), + lastLayersHeight, lastSeaLayersHeight, + seaLevel); } void scripting::load_world_script( diff --git a/src/world/generator/GeneratorDef.hpp b/src/world/generator/GeneratorDef.hpp index afb5eec3..72c8c470 100644 --- a/src/world/generator/GeneratorDef.hpp +++ b/src/world/generator/GeneratorDef.hpp @@ -26,9 +26,11 @@ public: const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed) = 0; virtual const std::vector& getLayers() const = 0; + virtual const std::vector& getSeaLayers() const = 0; /// @brief Total height of all layers after resizeable one virtual uint getLastLayersHeight() const = 0; + virtual uint getLastSeaLayersHeight() const = 0; virtual uint getSeaLevel() const = 0; diff --git a/src/world/generator/WorldGenerator.cpp b/src/world/generator/WorldGenerator.cpp index fa25d49d..53dc559a 100644 --- a/src/world/generator/WorldGenerator.cpp +++ b/src/world/generator/WorldGenerator.cpp @@ -1,6 +1,7 @@ #include "WorldGenerator.hpp" #include +#include #include "content/Content.hpp" #include "voxels/Block.hpp" @@ -14,6 +15,37 @@ WorldGenerator::WorldGenerator( ) : def(def), content(content) { } +static inline void generate_pole( + const std::vector& layers, + int height, int bottom, int seaLevel, int lastLayersHeight, + voxel* voxels, + int x, int z +) { + uint y = height; + uint layerExtension = 0; + for (const auto& layer : layers) { + // skip layer if can't be generated under sea level + if (y < seaLevel && !layer.below_sea_level) { + layerExtension = std::max(0, layer.height); + continue; + } + + int layerHeight = layer.height; + if (layerHeight == -1) { + // resizeable layer + layerHeight = y - lastLayersHeight - bottom + 1; + } else { + layerHeight += layerExtension; + } + layerHeight = std::min(static_cast(layerHeight), y); + + for (uint i = 0; i < layerHeight; i++, y--) { + voxels[vox_index(x, y, z)].id = layer.rt.id; + } + layerExtension = 0; + } +} + #include "util/timeutil.hpp" void WorldGenerator::generate( voxel* voxels, int chunkX, int chunkZ, uint64_t seed @@ -24,42 +56,22 @@ void WorldGenerator::generate( ); auto values = heightmap->getValues(); const auto& layers = def.script->getLayers(); + const auto& seaLayers = def.script->getSeaLayers(); + uint lastLayersHeight = def.script->getLastLayersHeight(); + uint lastSeaLayersHeight = def.script->getLastSeaLayersHeight(); + uint seaLevel = def.script->getSeaLevel(); - auto baseWater = content->blocks.require("base:water").rt.id; std::memset(voxels, 0, sizeof(voxel) * CHUNK_VOL); for (uint z = 0; z < CHUNK_D; z++) { for (uint x = 0; x < CHUNK_W; x++) { - // generate water int height = values[z * CHUNK_W + x] * CHUNK_H; height = std::max(0, height); - for (uint y = height+1; y <= seaLevel; y++) { - voxels[vox_index(x, y, z)].id = baseWater; - } - uint y = height; - uint layerExtension = 0; - for (const auto& layer : layers) { - // skip layer if can't be generated under sea level - if (y < seaLevel && !layer.below_sea_level) { - layerExtension = std::max(0, layer.height); - continue; - } - - uint layerHeight = layer.height; - if (layerHeight == -1) { - // resizeable layer - layerHeight = y - lastLayersHeight + 1; - } else { - layerHeight += layerExtension; - } - for (uint i = 0; i < layerHeight; i++, y--) { - voxels[vox_index(x, y, z)].id = layer.rt.id; - } - layerExtension = 0; - } + generate_pole(seaLayers, seaLevel, height, seaLevel, lastSeaLayersHeight, voxels, x, z); + generate_pole(layers, height, 0, seaLevel, lastLayersHeight, voxels, x, z); } } }