Skip to content

Commit ea4d407

Browse files
committedJun 19, 2017
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'.
1 parent 8f2e60a commit ea4d407

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed
 

‎src/mapgen_v7.cpp

+24-14
Original file line numberDiff line numberDiff line change
@@ -202,39 +202,49 @@ void MapgenV7Params::writeParams(Settings *settings) const
202202

203203
int MapgenV7::getSpawnLevelAtPoint(v2s16 p)
204204
{
205-
// Base terrain calculation
206-
s16 y = baseTerrainLevelAtPoint(p.X, p.Y);
207-
208-
// If enabled, check if inside a river
205+
// If rivers are enabled, first check if in a river
209206
if (spflags & MGV7_RIDGES) {
210207
float width = 0.2;
211208
float uwatern = NoisePerlin2D(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2;
212209
if (fabs(uwatern) <= width)
213210
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
214211
}
215212

216-
// If mountains are disabled, terrain level is base terrain level
217-
// Avoids spawn on non-existant mountain terrain
213+
// Terrain noise 'offset' is the average level of that terrain.
214+
// At least 50% of terrain will be below the higher of base and alt terrain
215+
// 'offset's.
216+
// Raising the maximum spawn level above 'water_level + 16' is necessary
217+
// for when terrain 'offset's are set much higher than water_level.
218+
s16 max_spawn_y = MYMAX(MYMAX(noise_terrain_alt->np.offset,
219+
noise_terrain_base->np.offset),
220+
water_level + 16);
221+
// Base terrain calculation
222+
s16 y = baseTerrainLevelAtPoint(p.X, p.Y);
223+
224+
// If mountains are disabled, terrain level is base terrain level.
225+
// Avoids mid-air spawn where mountain terrain would have been.
218226
if (!(spflags & MGV7_MOUNTAINS)) {
219-
if (y <= water_level || y > water_level + 16)
227+
if (y <= water_level || y > max_spawn_y)
220228
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
221229
else
222-
return y;
230+
// + 1 to not be half-buried in a potential node-deep biome 'dust'
231+
return y + 1;
223232
}
224233

225-
// Mountain terrain calculation
226-
int iters = 128;
227-
while (iters--) {
234+
// Search upwards for first node without mountain terrain
235+
int iters = 256;
236+
while (iters > 0 && y <= max_spawn_y) {
228237
if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) { // If air above
229-
if (y <= water_level || y > water_level + 16)
238+
if (y <= water_level || y > max_spawn_y)
230239
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
231240
else
232-
return y;
241+
return y + 1;
233242
}
234243
y++;
244+
iters--;
235245
}
236246

237-
// Unsuitable spawn point, no mountain surface found
247+
// Unsuitable spawn point
238248
return MAX_MAP_GENERATION_LIMIT;
239249
}
240250

0 commit comments

Comments
 (0)
Please sign in to comment.