From 8299e4b67eff48e0f6e101afea2fae8f0e65c421 Mon Sep 17 00:00:00 2001 From: paramat Date: Wed, 14 Jun 2017 02:00:51 +0100 Subject: [PATCH] Biomes/decorations/ores: Make relative to 'water_level' setting Add 'biome_zero_level' argument to 'generateBiomes()', 'deco_zero_level' argument to 'placeAllDecos()' and 'ore_zero_level' to 'placeAllOres()' to allow mapgens to vertically shift the registered biomes, decorations and ores per-mapchunk. Will also allow many realm possibilities in future mapgens. --- doc/lua_api.txt | 14 ++++++++++---- src/mapgen.cpp | 7 +++++-- src/mapgen.h | 2 +- src/mapgen_carpathian.cpp | 10 ++++++---- src/mapgen_flat.cpp | 8 +++++--- src/mapgen_fractal.cpp | 8 +++++--- src/mapgen_v5.cpp | 8 +++++--- src/mapgen_v6.cpp | 6 ++++-- src/mapgen_v7.cpp | 8 +++++--- src/mapgen_valleys.cpp | 8 +++++--- src/mg_decoration.cpp | 19 ++++++++++++++----- src/mg_decoration.h | 6 ++++-- src/mg_ore.cpp | 23 +++++++++++++++++------ src/mg_ore.h | 6 ++++-- 14 files changed, 90 insertions(+), 43 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 3fc815272..e675cc703 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4420,6 +4420,9 @@ Definition tables -- ^ In this example, there is a 3x3x3 cluster where 8 out of the 27 nodes are coal ore y_min = -31000, y_max = 64, + -- ^ Lower and upper limits for ore. + -- ^ Limits are relative to y = water_level - 1 for core mapgen, or + -- ^ relative to y = 0 for minetest.generate_ores(). flags = "", -- ^ Attributes for this ore generation noise_threshold = 0.5, @@ -4429,7 +4432,7 @@ Definition tables -- ^ Needed for sheet ore_type. Omit from scatter ore_type for a uniform ore distribution random_factor = 1.0, -- ^ Multiplier of the randomness contribution to the noise value at any - -- given point to decide if ore should be placed. Set to 0 for solid veins. + -- ^ given point to decide if ore should be placed. Set to 0 for solid veins. -- ^ This parameter is only valid for ore_type == "vein". biomes = {"desert", "rainforest"} -- ^ List of biomes in which this decoration occurs. Occurs in all biomes if this is omitted, @@ -4467,6 +4470,7 @@ The Biome API is still in an experimental phase and subject to change. y_min = 1, y_max = 31000, -- ^ Lower and upper limits for biome. + -- ^ Limits are relative to y = water_level - 1. -- ^ Because biome is not recalculated for every node in a node column -- ^ some biome materials can exceed their limits, especially stone. -- ^ For each node column in a mapchunk, biome is only recalculated at column @@ -4509,9 +4513,11 @@ The Biome API is still in an experimental phase and subject to change. -- ^ Can be a list of (or a single) biome names, IDs, or definitions. y_min = -31000 y_max = 31000 - -- ^ Minimum and maximum `y` positions these decorations can be generated at. - -- ^ This parameter refers to the `y` position of the decoration base, so - -- the actual maximum height would be `height_max + size.Y`. + -- ^ Lower and upper limits for decoration. + -- ^ Limits are relative to y = water_level - 1 for core mapgen, or + -- ^ relative to y = 0 for minetest.generate_decorations(). + -- ^ This parameter refers to the `y` position of the decoration base, so + -- the actual maximum height would be `height_max + size.Y`. spawn_by = "default:water", -- ^ Node (or list of nodes) that the decoration only spawns next to. -- ^ Checks two horizontal planes of neighbouring nodes (including diagonal neighbours), diff --git a/src/mapgen.cpp b/src/mapgen.cpp index b095d34c8..7a03a4606 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -621,7 +621,7 @@ MapgenBasic::~MapgenBasic() } -MgStoneType MapgenBasic::generateBiomes() +MgStoneType MapgenBasic::generateBiomes(s16 biome_zero_level) { // can't generate biomes without a biome generator! assert(biomegen); @@ -673,7 +673,10 @@ MgStoneType MapgenBasic::generateBiomes() (air_above || !biome); if (is_stone_surface || is_water_surface) { - biome = biomegen->getBiomeAtIndex(index, y); + // Limit to +-MAX MAP GENERATION LIMIT to work with biome y_min / y_max. + s32 relative_y = rangelim(y - biome_zero_level, + -MAX_MAP_GENERATION_LIMIT, MAX_MAP_GENERATION_LIMIT); + biome = biomegen->getBiomeAtIndex(index, relative_y); if (biomemap[index] == BIOME_NONE && is_stone_surface) biomemap[index] = biome->index; diff --git a/src/mapgen.h b/src/mapgen.h index 7acceddaf..7f4b76c3e 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -251,7 +251,7 @@ public: virtual void generateCaves(s16 max_stone_y, s16 large_cave_depth); virtual bool generateCaverns(s16 max_stone_y); virtual void generateDungeons(s16 max_stone_y, MgStoneType stone_type); - virtual MgStoneType generateBiomes(); + virtual MgStoneType generateBiomes(s16 biome_zero_level = 0); virtual void dustTopNodes(); protected: diff --git a/src/mapgen_carpathian.cpp b/src/mapgen_carpathian.cpp index c33239087..598795830 100644 --- a/src/mapgen_carpathian.cpp +++ b/src/mapgen_carpathian.cpp @@ -242,7 +242,7 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data) // Init biome generator, place biome-specific nodes, and build biomemap biomegen->calcBiomeNoise(node_min); - MgStoneType stone_type = generateBiomes(); + MgStoneType stone_type = generateBiomes(water_level - 1); // Generate caverns, tunnels and classic caves if (flags & MG_CAVES) { @@ -266,10 +266,12 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data) // Generate the registered decorations if (flags & MG_DECORATIONS) - m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); + m_emerge->decomgr->placeAllDecos(this, blockseed, + node_min, node_max, water_level - 1); // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + m_emerge->oremgr->placeAllOres(this, blockseed, + node_min, node_max, water_level - 1); // Sprinkle some dust on top after everything else was generated dustTopNodes(); @@ -448,4 +450,4 @@ int MapgenCarpathian::generateTerrain() } return stone_surface_max_y; -} \ No newline at end of file +} diff --git a/src/mapgen_flat.cpp b/src/mapgen_flat.cpp index 95fb35412..56dca1f06 100644 --- a/src/mapgen_flat.cpp +++ b/src/mapgen_flat.cpp @@ -189,7 +189,7 @@ void MapgenFlat::makeChunk(BlockMakeData *data) // Init biome generator, place biome-specific nodes, and build biomemap biomegen->calcBiomeNoise(node_min); - MgStoneType stone_type = generateBiomes(); + MgStoneType stone_type = generateBiomes(water_level - 1); if (flags & MG_CAVES) generateCaves(stone_surface_max_y, large_cave_depth); @@ -199,10 +199,12 @@ void MapgenFlat::makeChunk(BlockMakeData *data) // Generate the registered decorations if (flags & MG_DECORATIONS) - m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); + m_emerge->decomgr->placeAllDecos(this, blockseed, + node_min, node_max, water_level - 1); // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + m_emerge->oremgr->placeAllOres(this, blockseed, + node_min, node_max, water_level - 1); // Sprinkle some dust on top after everything else was generated dustTopNodes(); diff --git a/src/mapgen_fractal.cpp b/src/mapgen_fractal.cpp index 4fe0d8369..13da2f180 100644 --- a/src/mapgen_fractal.cpp +++ b/src/mapgen_fractal.cpp @@ -199,7 +199,7 @@ void MapgenFractal::makeChunk(BlockMakeData *data) // Init biome generator, place biome-specific nodes, and build biomemap biomegen->calcBiomeNoise(node_min); - MgStoneType stone_type = generateBiomes(); + MgStoneType stone_type = generateBiomes(water_level - 1); if (flags & MG_CAVES) generateCaves(stone_surface_max_y, large_cave_depth); @@ -209,10 +209,12 @@ void MapgenFractal::makeChunk(BlockMakeData *data) // Generate the registered decorations if (flags & MG_DECORATIONS) - m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); + m_emerge->decomgr->placeAllDecos(this, blockseed, + node_min, node_max, water_level - 1); // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + m_emerge->oremgr->placeAllOres(this, blockseed, + node_min, node_max, water_level - 1); // Sprinkle some dust on top after everything else was generated dustTopNodes(); diff --git a/src/mapgen_v5.cpp b/src/mapgen_v5.cpp index ffa1f538c..ad1e9d0a5 100644 --- a/src/mapgen_v5.cpp +++ b/src/mapgen_v5.cpp @@ -200,7 +200,7 @@ void MapgenV5::makeChunk(BlockMakeData *data) // Init biome generator, place biome-specific nodes, and build biomemap biomegen->calcBiomeNoise(node_min); - MgStoneType stone_type = generateBiomes(); + MgStoneType stone_type = generateBiomes(water_level - 1); // Generate caverns, tunnels and classic caves if (flags & MG_CAVES) { @@ -224,10 +224,12 @@ void MapgenV5::makeChunk(BlockMakeData *data) // Generate the registered decorations if (flags & MG_DECORATIONS) - m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); + m_emerge->decomgr->placeAllDecos(this, blockseed, + node_min, node_max, water_level - 1); // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + m_emerge->oremgr->placeAllOres(this, blockseed, + node_min, node_max, water_level - 1); // Sprinkle some dust on top after everything else was generated dustTopNodes(); diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index ebbd932d4..e8e0c583d 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -619,10 +619,12 @@ void MapgenV6::makeChunk(BlockMakeData *data) // Generate the registered decorations if (flags & MG_DECORATIONS) - m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); + m_emerge->decomgr->placeAllDecos(this, blockseed, + node_min, node_max, water_level - 1); // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + m_emerge->oremgr->placeAllOres(this, blockseed, + node_min, node_max, water_level - 1); // Calculate lighting if (flags & MG_LIGHT) diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 17f2df835..4b263bdb3 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -298,7 +298,7 @@ void MapgenV7::makeChunk(BlockMakeData *data) // Init biome generator, place biome-specific nodes, and build biomemap biomegen->calcBiomeNoise(node_min); - MgStoneType stone_type = generateBiomes(); + MgStoneType stone_type = generateBiomes(water_level - 1); // Generate caverns, tunnels and classic caves if (flags & MG_CAVES) { @@ -322,10 +322,12 @@ void MapgenV7::makeChunk(BlockMakeData *data) // Generate the registered decorations if (flags & MG_DECORATIONS) - m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); + m_emerge->decomgr->placeAllDecos(this, blockseed, + node_min, node_max, water_level - 1); // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + m_emerge->oremgr->placeAllOres(this, blockseed, + node_min, node_max, water_level - 1); // Sprinkle some dust on top after everything else was generated dustTopNodes(); diff --git a/src/mapgen_valleys.cpp b/src/mapgen_valleys.cpp index 71c0b001f..8c54dbcd9 100644 --- a/src/mapgen_valleys.cpp +++ b/src/mapgen_valleys.cpp @@ -236,7 +236,7 @@ void MapgenValleys::makeChunk(BlockMakeData *data) updateHeightmap(node_min, node_max); // Place biome-specific nodes and build biomemap - MgStoneType stone_type = generateBiomes(); + MgStoneType stone_type = generateBiomes(water_level - 1); // Cave creation. if (flags & MG_CAVES) @@ -248,10 +248,12 @@ void MapgenValleys::makeChunk(BlockMakeData *data) // Generate the registered decorations if (flags & MG_DECORATIONS) - m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); + m_emerge->decomgr->placeAllDecos(this, blockseed, + node_min, node_max, water_level - 1); // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + m_emerge->oremgr->placeAllOres(this, blockseed, + node_min, node_max, water_level - 1); // Sprinkle some dust on top after everything else was generated dustTopNodes(); diff --git a/src/mg_decoration.cpp b/src/mg_decoration.cpp index b13ddbadb..4af7a7897 100644 --- a/src/mg_decoration.cpp +++ b/src/mg_decoration.cpp @@ -48,7 +48,7 @@ DecorationManager::DecorationManager(IGameDef *gamedef) : size_t DecorationManager::placeAllDecos(Mapgen *mg, u32 blockseed, - v3s16 nmin, v3s16 nmax) + v3s16 nmin, v3s16 nmax, s16 deco_zero_level) { size_t nplaced = 0; @@ -57,7 +57,7 @@ size_t DecorationManager::placeAllDecos(Mapgen *mg, u32 blockseed, if (!deco) continue; - nplaced += deco->placeDeco(mg, blockseed, nmin, nmax); + nplaced += deco->placeDeco(mg, blockseed, nmin, nmax, deco_zero_level); blockseed++; } @@ -123,8 +123,18 @@ bool Decoration::canPlaceDecoration(MMVManip *vm, v3s16 p) } -size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) +size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, + v3s16 nmin, v3s16 nmax, s16 deco_zero_level) { + // Decoration y_min / y_max is displaced by deco_zero_level or remains + // unchanged. Any decoration with a limit at +-MAX_MAP_GENERATION_LIMIT is + // considered to have that limit at +-infinity, so we do not alter that limit. + s32 y_min_disp = (y_min <= -MAX_MAP_GENERATION_LIMIT) ? + -MAX_MAP_GENERATION_LIMIT : y_min + deco_zero_level; + + s32 y_max_disp = (y_max >= MAX_MAP_GENERATION_LIMIT) ? + MAX_MAP_GENERATION_LIMIT : y_max + deco_zero_level; + PcgRandom ps(blockseed + 53); int carea_size = nmax.X - nmin.X + 1; @@ -179,8 +189,7 @@ size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) else y = mg->findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y); - if (y < nmin.Y || y > nmax.Y || - y < y_min || y > y_max) + if (y < y_min_disp || y > y_max_disp || y < nmin.Y || y > nmax.Y) continue; if (y + getHeight() > mg->vm->m_area.MaxEdge.Y) { diff --git a/src/mg_decoration.h b/src/mg_decoration.h index 968c78612..a7fdb97fe 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -70,7 +70,8 @@ public: virtual void resolveNodeNames(); bool canPlaceDecoration(MMVManip *vm, v3s16 p); - size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); + size_t placeDeco(Mapgen *mg, u32 blockseed, + v3s16 nmin, v3s16 nmax, s16 deco_zero_level); //size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); virtual size_t generate(MMVManip *vm, PcgRandom *pr, v3s16 p) = 0; @@ -145,7 +146,8 @@ public: } } - size_t placeAllDecos(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); + size_t placeAllDecos(Mapgen *mg, u32 blockseed, + v3s16 nmin, v3s16 nmax, s16 deco_zero_level = 0); }; #endif diff --git a/src/mg_ore.cpp b/src/mg_ore.cpp index 73af2e2e6..36100f762 100644 --- a/src/mg_ore.cpp +++ b/src/mg_ore.cpp @@ -43,7 +43,8 @@ OreManager::OreManager(IGameDef *gamedef) : } -size_t OreManager::placeAllOres(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) +size_t OreManager::placeAllOres(Mapgen *mg, u32 blockseed, + v3s16 nmin, v3s16 nmax, s16 ore_zero_level) { size_t nplaced = 0; @@ -52,7 +53,7 @@ size_t OreManager::placeAllOres(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nma if (!ore) continue; - nplaced += ore->placeOre(mg, blockseed, nmin, nmax); + nplaced += ore->placeOre(mg, blockseed, nmin, nmax, ore_zero_level); blockseed++; } @@ -85,13 +86,23 @@ void Ore::resolveNodeNames() } -size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) +size_t Ore::placeOre(Mapgen *mg, u32 blockseed, + v3s16 nmin, v3s16 nmax, s16 ore_zero_level) { - if (!(nmin.Y <= y_max && nmax.Y >= y_min)) + // Ore y_min / y_max is displaced by ore_zero_level or remains unchanged. + // Any ore with a limit at +-MAX_MAP_GENERATION_LIMIT is considered to have + // that limit at +-infinity, so we do not alter that limit. + s32 y_min_disp = (y_min <= -MAX_MAP_GENERATION_LIMIT) ? + -MAX_MAP_GENERATION_LIMIT : y_min + ore_zero_level; + + s32 y_max_disp = (y_max >= MAX_MAP_GENERATION_LIMIT) ? + MAX_MAP_GENERATION_LIMIT : y_max + ore_zero_level; + + if (nmin.Y > y_max_disp || nmax.Y < y_min_disp) return 0; - int actual_ymin = MYMAX(nmin.Y, y_min); - int actual_ymax = MYMIN(nmax.Y, y_max); + int actual_ymin = MYMAX(nmin.Y, y_min_disp); + int actual_ymax = MYMIN(nmax.Y, y_max_disp); if (clust_size >= actual_ymax - actual_ymin + 1) return 0; diff --git a/src/mg_ore.h b/src/mg_ore.h index 5aeb3631c..692cd848e 100644 --- a/src/mg_ore.h +++ b/src/mg_ore.h @@ -70,7 +70,8 @@ public: virtual void resolveNodeNames(); - size_t placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); + size_t placeOre(Mapgen *mg, u32 blockseed, + v3s16 nmin, v3s16 nmax, s16 ore_zero_level); virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3s16 nmax, u8 *biomemap) = 0; }; @@ -163,7 +164,8 @@ public: void clear(); - size_t placeAllOres(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); + size_t placeAllOres(Mapgen *mg, u32 blockseed, + v3s16 nmin, v3s16 nmax, s16 ore_zero_level = 0); }; #endif