add sea_layers

This commit is contained in:
MihailRis 2024-08-18 01:30:59 +03:00
parent 8fb0f6a1bb
commit af485dd7cb
4 changed files with 86 additions and 32 deletions

View File

@ -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")

View File

@ -688,17 +688,23 @@ void scripting::load_entity_component(
class LuaGeneratorScript : public GeneratorScript {
scriptenv env;
std::vector<BlocksLayer> layers;
std::vector<BlocksLayer> seaLayers;
uint lastLayersHeight;
uint lastSeaLayersHeight;
uint seaLevel;
public:
LuaGeneratorScript(
scriptenv env,
std::vector<BlocksLayer> layers,
std::vector<BlocksLayer> layers,
std::vector<BlocksLayer> 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<BlocksLayer>& getLayers() const override {
return layers;
}
const std::vector<BlocksLayer>& 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<GeneratorScript> scripting::load_generator(
}
uint lastLayersHeight = 0;
uint lastSeaLayersHeight = 0;
bool hasResizeableLayer = false;
bool hasResizeableSeaLayer = false;
std::vector<BlocksLayer> layers;
std::vector<BlocksLayer> 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<GeneratorScript> 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<LuaGeneratorScript>(
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(

View File

@ -26,9 +26,11 @@ public:
const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed) = 0;
virtual const std::vector<BlocksLayer>& getLayers() const = 0;
virtual const std::vector<BlocksLayer>& 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;

View File

@ -1,6 +1,7 @@
#include "WorldGenerator.hpp"
#include <cstring>
#include <iostream>
#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<BlocksLayer>& 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<uint>(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);
}
}
}