]> git.lizzy.rs Git - minetest.git/commitdiff
Mgv7 spawn search: Cope with extreme custom terrain and biome 'dust'
authorparamat <paramat@users.noreply.github.com>
Sun, 11 Jun 2017 05:02:20 +0000 (06:02 +0100)
committerparamat <mat.gregory@virginmedia.com>
Mon, 19 Jun 2017 01:20:04 +0000 (02:20 +0100)
Previously, maximum spawn level was set to 'water_level + 16'. This would result
in spawn search failing if terrain had been customised to be much higher than
'water_level' at all points.

Also raise spawn level by 1 node to avoid spawning half-buried in a biome 'dust'
node such as 'default:snowblock'.

src/mapgen_v7.cpp

index 2048da1fe251b0ee52b008c110d9f4cd1910f49d..ad242ae49bfc893c8d6d9470f4e85718abfc7596 100644 (file)
@@ -202,10 +202,7 @@ void MapgenV7Params::writeParams(Settings *settings) const
 
 int MapgenV7::getSpawnLevelAtPoint(v2s16 p)
 {
-       // Base terrain calculation
-       s16 y = baseTerrainLevelAtPoint(p.X, p.Y);
-
-       // If enabled, check if inside a river
+       // If rivers are enabled, first check if in a river
        if (spflags & MGV7_RIDGES) {
                float width = 0.2;
                float uwatern = NoisePerlin2D(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2;
@@ -213,28 +210,41 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p)
                        return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
        }
 
-       // If mountains are disabled, terrain level is base terrain level
-       // Avoids spawn on non-existant mountain terrain
+       // Terrain noise 'offset' is the average level of that terrain.
+       // At least 50% of terrain will be below the higher of base and alt terrain
+       // 'offset's.
+       // Raising the maximum spawn level above 'water_level + 16' is necessary
+       // for when terrain 'offset's are set much higher than water_level.
+       s16 max_spawn_y = MYMAX(MYMAX(noise_terrain_alt->np.offset,
+                       noise_terrain_base->np.offset),
+                       water_level + 16);
+       // Base terrain calculation
+       s16 y = baseTerrainLevelAtPoint(p.X, p.Y);
+
+       // If mountains are disabled, terrain level is base terrain level.
+       // Avoids mid-air spawn where mountain terrain would have been.
        if (!(spflags & MGV7_MOUNTAINS)) {
-               if (y <= water_level || y > water_level + 16)
+               if (y <= water_level || y > max_spawn_y)
                        return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
                else
-                       return y;
+                       // + 1 to not be half-buried in a potential node-deep biome 'dust'
+                       return y + 1;
        }
 
-       // Mountain terrain calculation
-       int iters = 128;
-       while (iters--) {
+       // Search upwards for first node without mountain terrain
+       int iters = 256;
+       while (iters > 0 && y <= max_spawn_y) {
                if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) {  // If air above
-                       if (y <= water_level || y > water_level + 16)
+                       if (y <= water_level || y > max_spawn_y)
                                return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
                        else
-                               return y;
+                               return y + 1;
                }
                y++;
+               iters--;
        }
 
-       // Unsuitable spawn point, no mountain surface found
+       // Unsuitable spawn point
        return MAX_MAP_GENERATION_LIMIT;
 }