Skip to content

Commit 4adbd69

Browse files
committed
FindSpawnPos: Let mapgens decide what spawn altitude is suitable
To avoid spawn search failing in new specialised mapgens Increase spawn search range to 4000 nodes Add getSpawnLevelAtPoint() functions to EmergeManager, class Mapgen and all mapgens Remove getGroundLevelAtPoint() functions from all mapgens except mgv6 (possibly to be re-added later in the correct form to return actual ground level) Make mgvalleys flag names consistent with other mapgens Remove now unused 'vertical spawn range' setting
1 parent 38e7122 commit 4adbd69

19 files changed

+123
-78
lines changed

src/defaultsettings.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,6 @@ void set_default_settings(Settings *settings)
247247
settings->setDefault("default_privs", "interact, shout");
248248
settings->setDefault("player_transfer_distance", "0");
249249
settings->setDefault("enable_pvp", "true");
250-
settings->setDefault("vertical_spawn_range", "16");
251250
settings->setDefault("disallow_empty_password", "false");
252251
settings->setDefault("disable_anticheat", "false");
253252
settings->setDefault("enable_rollback_recording", "false");

src/emerge.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,18 @@ v3s16 EmergeManager::getContainingChunk(v3s16 blockpos, s16 chunksize)
334334
}
335335

336336

337+
int EmergeManager::getSpawnLevelAtPoint(v2s16 p)
338+
{
339+
if (m_mapgens.size() == 0 || !m_mapgens[0]) {
340+
errorstream << "EmergeManager: getSpawnLevelAtPoint() called"
341+
" before mapgen init" << std::endl;
342+
return 0;
343+
}
344+
345+
return m_mapgens[0]->getSpawnLevelAtPoint(p);
346+
}
347+
348+
337349
int EmergeManager::getGroundLevelAtPoint(v2s16 p)
338350
{
339351
if (m_mapgens.size() == 0 || !m_mapgens[0]) {

src/emerge.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ class EmergeManager {
136136

137137
// Mapgen helpers methods
138138
Biome *getBiomeAtPoint(v3s16 p);
139+
int getSpawnLevelAtPoint(v2s16 p);
139140
int getGroundLevelAtPoint(v2s16 p);
140141
bool isBlockUnderground(v3s16 blockpos);
141142

src/mapgen.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ class Mapgen {
181181
virtual void makeChunk(BlockMakeData *data) {}
182182
virtual int getGroundLevelAtPoint(v2s16 p) { return 0; }
183183

184+
// getSpawnLevelAtPoint() is a function within each mapgen that returns a
185+
// suitable y co-ordinate for player spawn ('suitable' usually meaning
186+
// within 16 nodes of water_level). If a suitable spawn level cannot be
187+
// found at the specified (X, Z) 'MAX_MAP_GENERATION_LIMIT' is returned to
188+
// signify this and to cause Server::findSpawnPos() to try another (X, Z).
189+
virtual int getSpawnLevelAtPoint(v2s16 p) { return 0; }
190+
184191
private:
185192
DISABLE_CLASS_COPY(Mapgen);
186193
};

src/mapgen_flat.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,18 +192,25 @@ void MapgenFlatParams::writeParams(Settings *settings) const
192192
/////////////////////////////////////////////////////////////////
193193

194194

195-
int MapgenFlat::getGroundLevelAtPoint(v2s16 p)
195+
int MapgenFlat::getSpawnLevelAtPoint(v2s16 p)
196196
{
197+
s16 level_at_point = ground_level;
197198
float n_terrain = NoisePerlin2D(&noise_terrain->np, p.X, p.Y, seed);
199+
198200
if ((spflags & MGFLAT_LAKES) && n_terrain < lake_threshold) {
199-
s16 depress = (lake_threshold - n_terrain) * lake_steepness;
200-
return ground_level - depress;
201+
level_at_point = ground_level -
202+
(lake_threshold - n_terrain) * lake_steepness;
201203
} else if ((spflags & MGFLAT_HILLS) && n_terrain > hill_threshold) {
202-
s16 rise = (n_terrain - hill_threshold) * hill_steepness;
203-
return ground_level + rise;
204-
} else {
205-
return ground_level;
204+
level_at_point = ground_level +
205+
(n_terrain - hill_threshold) * hill_steepness;
206206
}
207+
208+
if (ground_level < water_level) // Ocean world, allow spawn in water
209+
return MYMAX(level_at_point, water_level);
210+
else if (level_at_point > water_level)
211+
return level_at_point; // Spawn on land
212+
else
213+
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
207214
}
208215

209216

src/mapgen_flat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class MapgenFlat : public Mapgen {
102102
~MapgenFlat();
103103

104104
virtual void makeChunk(BlockMakeData *data);
105-
int getGroundLevelAtPoint(v2s16 p);
105+
int getSpawnLevelAtPoint(v2s16 p);
106106
void calculateNoise();
107107
s16 generateTerrain();
108108
MgStoneType generateBiomes(float *heat_map, float *humidity_map);

src/mapgen_fractal.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -209,17 +209,28 @@ void MapgenFractalParams::writeParams(Settings *settings) const
209209
/////////////////////////////////////////////////////////////////
210210

211211

212-
int MapgenFractal::getGroundLevelAtPoint(v2s16 p)
212+
int MapgenFractal::getSpawnLevelAtPoint(v2s16 p)
213213
{
214-
s16 search_start = 128;
215-
s16 search_end = -128;
216-
217-
for (s16 y = search_start; y >= search_end; y--) {
218-
if (getFractalAtPoint(p.X, y, p.Y))
219-
return y;
214+
bool solid_below = false; // Dry solid node is present below to spawn on
215+
u8 air_count = 0; // Consecutive air nodes above the dry solid node
216+
s16 seabed_level = NoisePerlin2D(&noise_seabed->np, p.X, p.Y, seed);
217+
// Seabed can rise above water_level or might be raised to create dry land
218+
s16 search_start = MYMAX(seabed_level, water_level + 1);
219+
if (seabed_level > water_level)
220+
solid_below = true;
221+
222+
for (s16 y = search_start; y <= search_start + 128; y++) {
223+
if (getFractalAtPoint(p.X, y, p.Y)) { // Fractal node
224+
solid_below = true;
225+
air_count = 0;
226+
} else if (solid_below) { // Air above solid node
227+
air_count++;
228+
if (air_count == 2)
229+
return y - 2;
230+
}
220231
}
221232

222-
return -MAX_MAP_GENERATION_LIMIT;
233+
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
223234
}
224235

225236

src/mapgen_fractal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class MapgenFractal : public Mapgen {
114114
~MapgenFractal();
115115

116116
virtual void makeChunk(BlockMakeData *data);
117-
int getGroundLevelAtPoint(v2s16 p);
117+
int getSpawnLevelAtPoint(v2s16 p);
118118
void calculateNoise();
119119
bool getFractalAtPoint(s16 x, s16 y, s16 z);
120120
s16 generateTerrain();

src/mapgen_singlenode.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ void MapgenSinglenode::makeChunk(BlockMakeData *data)
9999
}
100100

101101

102-
int MapgenSinglenode::getGroundLevelAtPoint(v2s16 p)
102+
int MapgenSinglenode::getSpawnLevelAtPoint(v2s16 p)
103103
{
104104
return 0;
105105
}

src/mapgen_singlenode.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class MapgenSinglenode : public Mapgen {
4141
~MapgenSinglenode();
4242

4343
void makeChunk(BlockMakeData *data);
44-
int getGroundLevelAtPoint(v2s16 p);
44+
int getSpawnLevelAtPoint(v2s16 p);
4545
};
4646

4747
struct MapgenFactorySinglenode : public MapgenFactory {

0 commit comments

Comments
 (0)