From 2a506e98918f941e7c8c77d804d249455d18d0bf Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 18 Aug 2024 16:54:58 +0300 Subject: [PATCH] refactor blocks layers --- res/generators/default.lua | 4 +- src/logic/scripting/scripting.cpp | 107 +++++++++++-------------- src/world/generator/GeneratorDef.hpp | 13 +-- src/world/generator/WorldGenerator.cpp | 32 ++++---- 4 files changed, 71 insertions(+), 85 deletions(-) diff --git a/res/generators/default.lua b/res/generators/default.lua index d77fb9f1..05df5ce9 100644 --- a/res/generators/default.lua +++ b/res/generators/default.lua @@ -42,11 +42,11 @@ end function generate_heightmap(x, y, w, h, seed) -- blocks per dot - -- 8 - linear interpolation is visible, but not so much (Minecraft) + -- 8 - linear interpolation is visible, but not so much -- 4 - high quality, but slower -- 2 - you really don't need it -- 1 - please have mercy on your CPU - local bpd = 8 + local bpd = 4 local map = _generate_heightmap( math.floor(x/bpd), math.floor(y/bpd), math.floor(w/bpd)+1, math.floor(h/bpd)+1, seed, bpd) diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 334e7923..d1a94118 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -687,24 +687,18 @@ void scripting::load_entity_component( class LuaGeneratorScript : public GeneratorScript { scriptenv env; - std::vector layers; - std::vector seaLayers; - uint lastLayersHeight; - uint lastSeaLayersHeight; + BlocksLayers groundLayers; + BlocksLayers seaLayers; uint seaLevel; public: LuaGeneratorScript( scriptenv env, - std::vector layers, - std::vector seaLayers, - uint lastLayersHeight, - uint lastSeaLayersHeight, + BlocksLayers groundLayers, + BlocksLayers seaLayers, uint seaLevel) : env(std::move(env)), - layers(std::move(layers)), + groundLayers(std::move(groundLayers)), seaLayers(std::move(seaLayers)), - lastLayersHeight(lastLayersHeight), - lastSeaLayersHeight(lastSeaLayersHeight), seaLevel(seaLevel) {} @@ -728,30 +722,22 @@ public: } void prepare(const Content* content) override { - for (auto& layer : layers) { + for (auto& layer : groundLayers.layers) { layer.rt.id = content->blocks.require(layer.block).rt.id; } - for (auto& layer : seaLayers) { + for (auto& layer : seaLayers.layers) { layer.rt.id = content->blocks.require(layer.block).rt.id; } } - const std::vector& getLayers() const override { - return layers; + const BlocksLayers& getGroundLayers() const override { + return groundLayers; } - const std::vector& getSeaLayers() const override { + const BlocksLayers& getSeaLayers() const override { return seaLayers; } - uint getLastLayersHeight() const override { - return lastLayersHeight; - } - - uint getLastSeaLayersHeight() const override { - return lastSeaLayersHeight; - } - uint getSeaLevel() const override { return seaLevel; } @@ -784,6 +770,32 @@ static BlocksLayer load_layer( return BlocksLayer {name, height, belowSeaLevel, {}}; } +static inline BlocksLayers load_layers( + lua::State* L, const std::string& fieldname +) { + uint lastLayersHeight = 0; + bool hasResizeableLayer = false; + std::vector layers; + + if (lua::getfield(L, fieldname)) { + int len = lua::objlen(L, -1); + for (int i = 1; i <= len; i++) { + lua::rawgeti(L, i); + try { + layers.push_back( + load_layer(L, -1, lastLayersHeight, hasResizeableLayer)); + } catch (const std::runtime_error& err) { + lua::pop(L, 2); + throw std::runtime_error( + fieldname+" #"+std::to_string(i)+": "+err.what()); + } + lua::pop(L); + } + lua::pop(L); + } + return BlocksLayers {std::move(layers), lastLayersHeight}; +} + std::unique_ptr scripting::load_generator( const fs::path& file ) { @@ -800,50 +812,25 @@ std::unique_ptr scripting::load_generator( lua::pop(L); } - uint lastLayersHeight = 0; + uint lastGroundLayersHeight = 0; uint lastSeaLayersHeight = 0; - bool hasResizeableLayer = false; + bool hasResizeableGroundLayer = 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++) { - lua::rawgeti(L, i); - try { - layers.push_back( - load_layer(L, -1, lastLayersHeight, hasResizeableLayer)); - } catch (const std::runtime_error& err) { - lua::pop(L, 2); - throw std::runtime_error( - "layer #"+std::to_string(i)+": "+err.what()); - } - lua::pop(L); - } - 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); - } + BlocksLayers groundLayers; + BlocksLayers seaLayers; + try { + groundLayers = load_layers(L, "layers"); + seaLayers = load_layers(L, "sea_layers"); + } catch (const std::runtime_error& err) { lua::pop(L); + throw std::runtime_error(file.u8string()+": "+err.what()); } lua::pop(L); return std::make_unique( std::move(env), - std::move(layers), std::move(seaLayers), - lastLayersHeight, lastSeaLayersHeight, + std::move(groundLayers), + std::move(seaLayers), seaLevel); } diff --git a/src/world/generator/GeneratorDef.hpp b/src/world/generator/GeneratorDef.hpp index 72c8c470..7852637c 100644 --- a/src/world/generator/GeneratorDef.hpp +++ b/src/world/generator/GeneratorDef.hpp @@ -18,6 +18,11 @@ struct BlocksLayer { } rt; }; +struct BlocksLayers { + std::vector layers; + uint lastLayersHeight; +}; + class GeneratorScript { public: virtual ~GeneratorScript() = default; @@ -25,12 +30,8 @@ public: virtual std::shared_ptr generateHeightmap( 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 const BlocksLayers& getGroundLayers() const = 0; + virtual const BlocksLayers& getSeaLayers() const = 0; virtual uint getSeaLevel() const = 0; diff --git a/src/world/generator/WorldGenerator.cpp b/src/world/generator/WorldGenerator.cpp index 53dc559a..0f0dea6e 100644 --- a/src/world/generator/WorldGenerator.cpp +++ b/src/world/generator/WorldGenerator.cpp @@ -9,31 +9,32 @@ #include "voxels/voxel.hpp" #include "world/generator/GeneratorDef.hpp" -WorldGenerator::WorldGenerator( - const GeneratorDef& def, - const Content* content -) : def(def), content(content) { +WorldGenerator::WorldGenerator(const GeneratorDef& def, const Content* content) + : def(def), content(content) { } static inline void generate_pole( - const std::vector& layers, - int height, int bottom, int seaLevel, int lastLayersHeight, + const BlocksLayers& layers, + int height, + int bottom, + int seaLevel, voxel* voxels, - int x, int z + int x, + int z ) { uint y = height; uint layerExtension = 0; - for (const auto& layer : layers) { + for (const auto& layer : layers.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; + layerHeight = y - layers.lastLayersHeight - bottom + 1; } else { layerHeight += layerExtension; } @@ -52,15 +53,12 @@ void WorldGenerator::generate( ) { timeutil::ScopeLogTimer log(555); auto heightmap = def.script->generateHeightmap( - {chunkX*CHUNK_W, chunkZ*CHUNK_D}, {CHUNK_W, CHUNK_D}, seed + {chunkX * CHUNK_W, chunkZ * CHUNK_D}, {CHUNK_W, CHUNK_D}, seed ); auto values = heightmap->getValues(); - const auto& layers = def.script->getLayers(); + const auto& groundLayers = def.script->getGroundLayers(); const auto& seaLayers = def.script->getSeaLayers(); - uint lastLayersHeight = def.script->getLastLayersHeight(); - uint lastSeaLayersHeight = def.script->getLastSeaLayersHeight(); - uint seaLevel = def.script->getSeaLevel(); std::memset(voxels, 0, sizeof(voxel) * CHUNK_VOL); @@ -70,8 +68,8 @@ void WorldGenerator::generate( int height = values[z * CHUNK_W + x] * CHUNK_H; height = std::max(0, height); - generate_pole(seaLayers, seaLevel, height, seaLevel, lastSeaLayersHeight, voxels, x, z); - generate_pole(layers, height, 0, seaLevel, lastLayersHeight, voxels, x, z); + generate_pole(seaLayers, seaLevel, height, seaLevel, voxels, x, z); + generate_pole(groundLayers, height, 0, seaLevel, voxels, x, z); } } }