aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorparamat <paramat@users.noreply.github.com>2017-06-11 06:02:20 +0100
committerparamat <mat.gregory@virginmedia.com>2017-06-19 02:20:04 +0100
commitea4d407082dd120bb6b3b1e9c869e88f26b001b1 (patch)
treea1ca192ae4ef304e30e7638fd553b71b691baa0a
parent8f2e60a9619f3db2dea752626e778f753c0714bc (diff)
downloadminetest-ea4d407082dd120bb6b3b1e9c869e88f26b001b1.tar.gz
minetest-ea4d407082dd120bb6b3b1e9c869e88f26b001b1.tar.bz2
minetest-ea4d407082dd120bb6b3b1e9c869e88f26b001b1.zip
Mgv7 spawn search: Cope with extreme custom terrain and biome 'dust'
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'.
-rw-r--r--src/mapgen_v7.cpp38
1 files changed, 24 insertions, 14 deletions
diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp
index 2048da1fe..ad242ae49 100644
--- a/src/mapgen_v7.cpp
+++ b/src/mapgen_v7.cpp
@@ -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;
}