Biomes/decorations/ores: Make relative to 'water_level' setting
authorparamat <paramat@users.noreply.github.com>
Wed, 14 Jun 2017 01:00:51 +0000 (02:00 +0100)
committerparamat <mat.gregory@virginmedia.com>
Tue, 11 Jul 2017 00:14:24 +0000 (01:14 +0100)
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.

14 files changed:
doc/lua_api.txt
src/mapgen.cpp
src/mapgen.h
src/mapgen_carpathian.cpp
src/mapgen_flat.cpp
src/mapgen_fractal.cpp
src/mapgen_v5.cpp
src/mapgen_v6.cpp
src/mapgen_v7.cpp
src/mapgen_valleys.cpp
src/mg_decoration.cpp
src/mg_decoration.h
src/mg_ore.cpp
src/mg_ore.h

index 3fc815272adbcf13c3e8b767d5c10e26de41c8fc..e675cc7035ec1dd314fb70ef38a40f084a57f3c9 100644 (file)
@@ -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),
index b095d34c8756ea1d2f004fa604b2b8b62b702125..7a03a4606444d7331b68b157f1fc93b7e2e62fd8 100644 (file)
@@ -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;
index 7acceddaf89681d7a7f47a2d62513456a05e8543..7f4b76c3e0b33e4f1a817025dd3a146ddc090a76 100644 (file)
@@ -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:
index c332390873775ef95393ed97a13bf703fc17b8e5..598795830a517ee0273263ce9b3ae8b0b8aecf97 100644 (file)
@@ -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
+}
index 95fb3541258d13f4474f1e9e50191a22e7636f14..56dca1f06d4608d669f22083f4ed5595aa2657d3 100644 (file)
@@ -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();
index 4fe0d836968d29e910b67b65dd79c2bd86458d0e..13da2f18012e8946978d7e058da3d869cbdeb0ef 100644 (file)
@@ -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();
index ffa1f538c4fa61da4ba2eb91345583e7d9d0432a..ad1e9d0a5fa6a18186547d1b15a13328fc486c36 100644 (file)
@@ -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();
index ebbd932d4de88d39526bbcf7a5b790a85bfe89fd..e8e0c583dfb745fe837d964deaeeeeb52e1bb613 100644 (file)
@@ -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)
index 17f2df835ca703078834e9ee053fe6209ba72883..4b263bdb3b70156fcf3a2c54e9983f36581593a3 100644 (file)
@@ -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();
index 71c0b001f71b0bffa7f14194727020b6c160e74d..8c54dbcd983ea5ea0843b87604e48dd6f30b9de1 100644 (file)
@@ -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();
index b13ddbadb1724ff71c30d8d32b9953c01ec2cd04..4af7a7897f813ef6318aba8b6c57d1d98cbd7669 100644 (file)
@@ -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) {
index 968c78612420585f81f6c92ecb861f4153e55ebf..a7fdb97fe907e92607db9af27a4208c0d4879802 100644 (file)
@@ -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
index 73af2e2e6cdb9ededf1f4da84925237b3fe3b903..36100f762ac80183542bb0544d28205398566139 100644 (file)
@@ -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;
 
index 5aeb3631c925c25299253f2da63f2aa7176be4f7..692cd848e44c9fb9bfb384a0d38df02aeabb490d 100644 (file)
@@ -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