]> git.lizzy.rs Git - minetest.git/blob - src/mapgen_valleys.cpp
Security: Fix resolving of some relative paths
[minetest.git] / src / mapgen_valleys.cpp
1 /*
2 Minetest Valleys C
3 Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
4 Copyright (C) 2010-2015 paramat, Matt Gregory
5 Copyright (C) 2016 Duane Robertson <duane@duanerobertson.com>
6
7 Based on Valleys Mapgen by Gael de Sailly
8  (https://forum.minetest.net/viewtopic.php?f=9&t=11430)
9 and mapgen_v7, mapgen_flat by kwolekr and paramat.
10
11 Licensing changed by permission of Gael de Sailly.
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU Lesser General Public License as published by
15 the Free Software Foundation; either version 2.1 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 GNU Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public License along
24 with this program; if not, write to the Free Software Foundation, Inc.,
25 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 */
27
28 #include "mapgen.h"
29 #include "voxel.h"
30 #include "noise.h"
31 #include "mapblock.h"
32 #include "mapnode.h"
33 #include "map.h"
34 #include "content_sao.h"
35 #include "nodedef.h"
36 #include "voxelalgorithms.h"
37 #include "settings.h" // For g_settings
38 #include "emerge.h"
39 #include "dungeongen.h"
40 #include "treegen.h"
41 #include "mg_biome.h"
42 #include "mg_ore.h"
43 #include "mg_decoration.h"
44 #include "mapgen_valleys.h"
45 #include "cavegen.h"
46
47
48 //#undef NDEBUG
49 //#include "assert.h"
50
51 //#include "util/timetaker.h"
52 //#include "profiler.h"
53
54
55 //static Profiler mapgen_prof;
56 //Profiler *mapgen_profiler = &mapgen_prof;
57
58 static FlagDesc flagdesc_mapgen_valleys[] = {
59         {"altitude_chill", MGVALLEYS_ALT_CHILL},
60         {"humid_rivers",   MGVALLEYS_HUMID_RIVERS},
61         {NULL,             0}
62 };
63
64 ///////////////////////////////////////////////////////////////////////////////
65
66
67 MapgenValleys::MapgenValleys(int mapgenid, MapgenValleysParams *params, EmergeManager *emerge)
68         : MapgenBasic(mapgenid, params, emerge)
69 {
70         // NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal
71         this->m_bgen = (BiomeGenOriginal *)biomegen;
72
73         this->map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT,
74                         g_settings->getU16("map_generation_limit"));
75
76         BiomeParamsOriginal *bp = (BiomeParamsOriginal *)params->bparams;
77
78         this->spflags            = params->spflags;
79         this->altitude_chill     = params->altitude_chill;
80         this->large_cave_depth   = params->large_cave_depth;
81         this->lava_features_lim  = rangelim(params->lava_features, 0, 10);
82         this->massive_cave_depth = params->massive_cave_depth;
83         this->river_depth_bed    = params->river_depth + 1.f;
84         this->river_size_factor  = params->river_size / 100.f;
85         this->water_features_lim = rangelim(params->water_features, 0, 10);
86         this->cave_width         = params->cave_width;
87
88         //// 2D Terrain noise
89         noise_filler_depth       = new Noise(&params->np_filler_depth,       seed, csize.X, csize.Z);
90         noise_inter_valley_slope = new Noise(&params->np_inter_valley_slope, seed, csize.X, csize.Z);
91         noise_rivers             = new Noise(&params->np_rivers,             seed, csize.X, csize.Z);
92         noise_terrain_height     = new Noise(&params->np_terrain_height,     seed, csize.X, csize.Z);
93         noise_valley_depth       = new Noise(&params->np_valley_depth,       seed, csize.X, csize.Z);
94         noise_valley_profile     = new Noise(&params->np_valley_profile,     seed, csize.X, csize.Z);
95
96         //// 3D Terrain noise
97         // 1-up 1-down overgeneration
98         noise_inter_valley_fill = new Noise(&params->np_inter_valley_fill, seed, csize.X, csize.Y + 2, csize.Z);
99         // 1-down overgeneraion
100         noise_cave1             = new Noise(&params->np_cave1,             seed, csize.X, csize.Y + 1, csize.Z);
101         noise_cave2             = new Noise(&params->np_cave2,             seed, csize.X, csize.Y + 1, csize.Z);
102         noise_massive_caves     = new Noise(&params->np_massive_caves,     seed, csize.X, csize.Y + 1, csize.Z);
103
104         this->humid_rivers       = (spflags & MGVALLEYS_HUMID_RIVERS);
105         this->use_altitude_chill = (spflags & MGVALLEYS_ALT_CHILL);
106         this->humidity_adjust    = bp->np_humidity.offset - 50.f;
107
108         // a small chance of overflows if the settings are very high
109         this->cave_water_max_height = water_level + MYMAX(0, water_features_lim - 4) * 50;
110         this->lava_max_height       = water_level + MYMAX(0, lava_features_lim - 4) * 50;
111
112         tcave_cache = new float[csize.Y + 2];
113
114         // Resolve content to be used
115         c_lava_source = ndef->getId("mapgen_lava_source");
116 }
117
118
119 MapgenValleys::~MapgenValleys()
120 {
121         delete noise_cave1;
122         delete noise_cave2;
123         delete noise_filler_depth;
124         delete noise_inter_valley_fill;
125         delete noise_inter_valley_slope;
126         delete noise_rivers;
127         delete noise_massive_caves;
128         delete noise_terrain_height;
129         delete noise_valley_depth;
130         delete noise_valley_profile;
131
132         delete[] tcave_cache;
133 }
134
135
136 MapgenValleysParams::MapgenValleysParams()
137 {
138         spflags            = MGVALLEYS_HUMID_RIVERS | MGVALLEYS_ALT_CHILL;
139         altitude_chill     = 90; // The altitude at which temperature drops by 20C.
140         large_cave_depth   = -33;
141         lava_features      = 0;  // How often water will occur in caves.
142         massive_cave_depth = -256;  // highest altitude of massive caves
143         river_depth        = 4;  // How deep to carve river channels.
144         river_size         = 5;  // How wide to make rivers.
145         water_features     = 0;  // How often water will occur in caves.
146         cave_width         = 0.09;
147
148         np_cave1              = NoiseParams(0,     12,   v3f(61,   61,   61),   52534, 3, 0.5,   2.0);
149         np_cave2              = NoiseParams(0,     12,   v3f(67,   67,   67),   10325, 3, 0.5,   2.0);
150         np_filler_depth       = NoiseParams(0.f,   1.2f, v3f(256,  256,  256),  1605,  3, 0.5f,  2.f);
151         np_inter_valley_fill  = NoiseParams(0.f,   1.f,  v3f(256,  512,  256),  1993,  6, 0.8f,  2.f);
152         np_inter_valley_slope = NoiseParams(0.5f,  0.5f, v3f(128,  128,  128),  746,   1, 1.f,   2.f);
153         np_rivers             = NoiseParams(0.f,   1.f,  v3f(256,  256,  256),  -6050, 5, 0.6f,  2.f);
154         np_massive_caves      = NoiseParams(0.f,   1.f,  v3f(768,  256,  768),  59033, 6, 0.63f, 2.f);
155         np_terrain_height     = NoiseParams(-10.f, 50.f, v3f(1024, 1024, 1024), 5202,  6, 0.4f,  2.f);
156         np_valley_depth       = NoiseParams(5.f,   4.f,  v3f(512,  512,  512),  -1914, 1, 1.f,   2.f);
157         np_valley_profile     = NoiseParams(0.6f,  0.5f, v3f(512,  512,  512),  777,   1, 1.f,   2.f);
158 }
159
160
161 void MapgenValleysParams::readParams(const Settings *settings)
162 {
163         settings->getFlagStrNoEx("mgvalleys_spflags",        spflags, flagdesc_mapgen_valleys);
164         settings->getU16NoEx("mgvalleys_altitude_chill",     altitude_chill);
165         settings->getS16NoEx("mgvalleys_large_cave_depth",   large_cave_depth);
166         settings->getU16NoEx("mgvalleys_lava_features",      lava_features);
167         settings->getS16NoEx("mgvalleys_massive_cave_depth", massive_cave_depth);
168         settings->getU16NoEx("mgvalleys_river_depth",        river_depth);
169         settings->getU16NoEx("mgvalleys_river_size",         river_size);
170         settings->getU16NoEx("mgvalleys_water_features",     water_features);
171         settings->getFloatNoEx("mgvalleys_cave_width",       cave_width);
172
173         settings->getNoiseParams("mgvalleys_np_cave1",              np_cave1);
174         settings->getNoiseParams("mgvalleys_np_cave2",              np_cave2);
175         settings->getNoiseParams("mgvalleys_np_filler_depth",       np_filler_depth);
176         settings->getNoiseParams("mgvalleys_np_inter_valley_fill",  np_inter_valley_fill);
177         settings->getNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
178         settings->getNoiseParams("mgvalleys_np_rivers",             np_rivers);
179         settings->getNoiseParams("mgvalleys_np_massive_caves",      np_massive_caves);
180         settings->getNoiseParams("mgvalleys_np_terrain_height",     np_terrain_height);
181         settings->getNoiseParams("mgvalleys_np_valley_depth",       np_valley_depth);
182         settings->getNoiseParams("mgvalleys_np_valley_profile",     np_valley_profile);
183 }
184
185
186 void MapgenValleysParams::writeParams(Settings *settings) const
187 {
188         settings->setFlagStr("mgvalleys_spflags",        spflags, flagdesc_mapgen_valleys, U32_MAX);
189         settings->setU16("mgvalleys_altitude_chill",     altitude_chill);
190         settings->setS16("mgvalleys_large_cave_depth",   large_cave_depth);
191         settings->setU16("mgvalleys_lava_features",      lava_features);
192         settings->setS16("mgvalleys_massive_cave_depth", massive_cave_depth);
193         settings->setU16("mgvalleys_river_depth",        river_depth);
194         settings->setU16("mgvalleys_river_size",         river_size);
195         settings->setU16("mgvalleys_water_features",     water_features);
196         settings->setFloat("mgvalleys_cave_width",       cave_width);
197
198         settings->setNoiseParams("mgvalleys_np_cave1",              np_cave1);
199         settings->setNoiseParams("mgvalleys_np_cave2",              np_cave2);
200         settings->setNoiseParams("mgvalleys_np_filler_depth",       np_filler_depth);
201         settings->setNoiseParams("mgvalleys_np_inter_valley_fill",  np_inter_valley_fill);
202         settings->setNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
203         settings->setNoiseParams("mgvalleys_np_rivers",             np_rivers);
204         settings->setNoiseParams("mgvalleys_np_massive_caves",      np_massive_caves);
205         settings->setNoiseParams("mgvalleys_np_terrain_height",     np_terrain_height);
206         settings->setNoiseParams("mgvalleys_np_valley_depth",       np_valley_depth);
207         settings->setNoiseParams("mgvalleys_np_valley_profile",     np_valley_profile);
208 }
209
210
211 ///////////////////////////////////////
212
213
214 void MapgenValleys::makeChunk(BlockMakeData *data)
215 {
216         // Pre-conditions
217         assert(data->vmanip);
218         assert(data->nodedef);
219         assert(data->blockpos_requested.X >= data->blockpos_min.X &&
220                 data->blockpos_requested.Y >= data->blockpos_min.Y &&
221                 data->blockpos_requested.Z >= data->blockpos_min.Z);
222         assert(data->blockpos_requested.X <= data->blockpos_max.X &&
223                 data->blockpos_requested.Y <= data->blockpos_max.Y &&
224                 data->blockpos_requested.Z <= data->blockpos_max.Z);
225
226         this->generating = true;
227         this->vm = data->vmanip;
228         this->ndef = data->nodedef;
229
230         //TimeTaker t("makeChunk");
231
232         v3s16 blockpos_min = data->blockpos_min;
233         v3s16 blockpos_max = data->blockpos_max;
234         node_min = blockpos_min * MAP_BLOCKSIZE;
235         node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
236         full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
237         full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
238
239         blockseed = getBlockSeed2(full_node_min, seed);
240
241         // Generate noise maps and base terrain height.
242         calculateNoise();
243
244         // Generate biome noises.  Note this must be executed strictly before
245         // generateTerrain, because generateTerrain depends on intermediate
246         // biome-related noises.
247         m_bgen->calcBiomeNoise(node_min);
248
249         // Generate base terrain with initial heightmaps
250         s16 stone_surface_max_y = generateTerrain();
251
252         // Place biome-specific nodes and build biomemap
253         MgStoneType stone_type = generateBiomes();
254
255         // Cave creation.
256         if (flags & MG_CAVES)
257                 generateCaves(stone_surface_max_y, large_cave_depth);
258
259         // Dungeon creation
260         if ((flags & MG_DUNGEONS) && node_max.Y < 50)
261                 generateDungeons(stone_surface_max_y, stone_type);
262
263         // Generate the registered decorations
264         if (flags & MG_DECORATIONS)
265                 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
266
267         // Generate the registered ores
268         m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
269
270         // Sprinkle some dust on top after everything else was generated
271         dustTopNodes();
272
273         //TimeTaker tll("liquid_lighting");
274
275         updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
276
277         if (flags & MG_LIGHT)
278                 calcLighting(
279                                 node_min - v3s16(0, 1, 0),
280                                 node_max + v3s16(0, 1, 0),
281                                 full_node_min,
282                                 full_node_max);
283
284         //mapgen_profiler->avg("liquid_lighting", tll.stop() / 1000.f);
285         //mapgen_profiler->avg("makeChunk", t.stop() / 1000.f);
286
287         this->generating = false;
288 }
289
290
291 // Populate the noise tables and do most of the
292 // calculation necessary to determine terrain height.
293 void MapgenValleys::calculateNoise()
294 {
295         //TimeTaker t("calculateNoise", NULL, PRECISION_MICRO);
296
297         int x = node_min.X;
298         int y = node_min.Y - 1;
299         int z = node_min.Z;
300
301         //TimeTaker tcn("actualNoise");
302
303         noise_inter_valley_slope->perlinMap2D(x, z);
304         noise_rivers->perlinMap2D(x, z);
305         noise_terrain_height->perlinMap2D(x, z);
306         noise_valley_depth->perlinMap2D(x, z);
307         noise_valley_profile->perlinMap2D(x, z);
308
309         noise_inter_valley_fill->perlinMap3D(x, y, z);
310
311         //mapgen_profiler->avg("noisemaps", tcn.stop() / 1000.f);
312
313         float heat_offset = 0.f;
314         float humidity_scale = 1.f;
315
316         // Altitude chill tends to reduce the average heat.
317         if (use_altitude_chill)
318                 heat_offset = 5.f;
319
320         // River humidity tends to increase the humidity range.
321         if (humid_rivers) {
322                 humidity_scale = 0.8f;
323         }
324
325         for (s32 index = 0; index < csize.X * csize.Z; index++) {
326                 m_bgen->heatmap[index] += heat_offset;
327                 m_bgen->humidmap[index] *= humidity_scale;
328         }
329
330         TerrainNoise tn;
331
332         u32 index = 0;
333         for (tn.z = node_min.Z; tn.z <= node_max.Z; tn.z++)
334         for (tn.x = node_min.X; tn.x <= node_max.X; tn.x++, index++) {
335                 // The parameters that we actually need to generate terrain
336                 //  are passed by address (and the return value).
337                 tn.terrain_height    = noise_terrain_height->result[index];
338                 // River noise is replaced with base terrain, which
339                 // is basically the height of the water table.
340                 tn.rivers            = &noise_rivers->result[index];
341                 // Valley depth noise is replaced with the valley
342                 // number that represents the height of terrain
343                 // over rivers and is used to determine about
344                 // how close a river is for humidity calculation.
345                 tn.valley            = &noise_valley_depth->result[index];
346                 tn.valley_profile    = noise_valley_profile->result[index];
347                 // Slope noise is replaced by the calculated slope
348                 // which is used to get terrain height in the slow
349                 // method, to create sharper mountains.
350                 tn.slope             = &noise_inter_valley_slope->result[index];
351                 tn.inter_valley_fill = noise_inter_valley_fill->result[index];
352
353                 // This is the actual terrain height.
354                 float mount = terrainLevelFromNoise(&tn);
355                 noise_terrain_height->result[index] = mount;
356         }
357 }
358
359
360 // This keeps us from having to maintain two similar sets of
361 //  complicated code to determine ground level.
362 float MapgenValleys::terrainLevelFromNoise(TerrainNoise *tn)
363 {
364         // The square function changes the behaviour of this noise:
365         //  very often small, and sometimes very high.
366         float valley_d = MYSQUARE(*tn->valley);
367
368         // valley_d is here because terrain is generally higher where valleys
369         //  are deep (mountains). base represents the height of the
370         //  rivers, most of the surface is above.
371         float base = tn->terrain_height + valley_d;
372
373         // "river" represents the distance from the river, in arbitrary units.
374         float river = fabs(*tn->rivers) - river_size_factor;
375
376         // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
377         //  Making "a" vary (0 < a <= 1) changes the shape of the valleys.
378         //  Try it with a geometry software !
379         //   (here x = "river" and a = valley_profile).
380         //  "valley" represents the height of the terrain, from the rivers.
381         {
382                 float t = river / tn->valley_profile;
383                 *tn->valley = valley_d * (1.f - exp(- MYSQUARE(t)));
384         }
385
386         // approximate height of the terrain at this point
387         float mount = base + *tn->valley;
388
389         *tn->slope *= *tn->valley;
390
391         // Rivers are placed where "river" is negative, so where the original
392         //  noise value is close to zero.
393         // Base ground is returned as rivers since it's basically the water table.
394         *tn->rivers = base;
395         if (river < 0.f) {
396                 // Use the the function -sqrt(1-x^2) which models a circle.
397                 float depth;
398                 {
399                         float t = river / river_size_factor + 1;
400                         depth = (river_depth_bed * sqrt(MYMAX(0, 1.f - MYSQUARE(t))));
401                 }
402
403                 // base - depth : height of the bottom of the river
404                 // water_level - 3 : don't make rivers below 3 nodes under the surface
405                 // We use three because that's as low as the swamp biomes go.
406                 // There is no logical equivalent to this using rangelim.
407                 mount = MYMIN(MYMAX(base - depth, (float)(water_level - 3)), mount);
408
409                 // Slope has no influence on rivers.
410                 *tn->slope = 0.f;
411         }
412
413         return mount;
414 }
415
416
417 // This avoids duplicating the code in terrainLevelFromNoise, adding
418 // only the final step of terrain generation without a noise map.
419 float MapgenValleys::adjustedTerrainLevelFromNoise(TerrainNoise *tn)
420 {
421         float mount = terrainLevelFromNoise(tn);
422         s16 y_start = myround(mount);
423
424         for (s16 y = y_start; y <= y_start + 1000; y++) {
425                 float fill = NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed);
426
427                 if (fill * *tn->slope < y - mount) {
428                         mount = MYMAX(y - 1, mount);
429                         break;
430                 }
431         }
432
433         return mount;
434 }
435
436
437 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
438 {
439         // Check to make sure this isn't a request for a location in a river.
440         float rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
441         if (fabs(rivers) < river_size_factor)
442                 return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
443
444         s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
445         if (level_at_point <= water_level ||
446                         level_at_point > water_level + 32)
447                 return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
448         else
449                 return level_at_point;
450 }
451
452
453 float MapgenValleys::terrainLevelAtPoint(s16 x, s16 z)
454 {
455         TerrainNoise tn;
456
457         float rivers = NoisePerlin2D(&noise_rivers->np, x, z, seed);
458         float valley = NoisePerlin2D(&noise_valley_depth->np, x, z, seed);
459         float inter_valley_slope = NoisePerlin2D(&noise_inter_valley_slope->np, x, z, seed);
460
461         tn.x                 = x;
462         tn.z                 = z;
463         tn.terrain_height    = NoisePerlin2D(&noise_terrain_height->np, x, z, seed);
464         tn.rivers            = &rivers;
465         tn.valley            = &valley;
466         tn.valley_profile    = NoisePerlin2D(&noise_valley_profile->np, x, z, seed);
467         tn.slope             = &inter_valley_slope;
468         tn.inter_valley_fill = 0.f;
469
470         return adjustedTerrainLevelFromNoise(&tn);
471 }
472
473
474 int MapgenValleys::generateTerrain()
475 {
476         // Raising this reduces the rate of evaporation.
477         static const float evaporation = 300.f;
478         // from the lua
479         static const float humidity_dropoff = 4.f;
480         // constant to convert altitude chill (compatible with lua) to heat
481         static const float alt_to_heat = 20.f;
482         // humidity reduction by altitude
483         static const float alt_to_humid = 10.f;
484
485         MapNode n_air(CONTENT_AIR);
486         MapNode n_river_water(c_river_water_source);
487         MapNode n_stone(c_stone);
488         MapNode n_water(c_water_source);
489
490         v3s16 em = vm->m_area.getExtent();
491         s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
492         u32 index_2d = 0;
493
494         for (s16 z = node_min.Z; z <= node_max.Z; z++)
495         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
496                 float river_y = noise_rivers->result[index_2d];
497                 float surface_y = noise_terrain_height->result[index_2d];
498                 float slope = noise_inter_valley_slope->result[index_2d];
499                 float t_heat = m_bgen->heatmap[index_2d];
500
501                 heightmap[index_2d] = -MAX_MAP_GENERATION_LIMIT;
502
503                 if (surface_y > surface_max_y)
504                         surface_max_y = ceil(surface_y);
505
506                 if (humid_rivers) {
507                         // Derive heat from (base) altitude. This will be most correct
508                         // at rivers, since other surface heights may vary below.
509                         if (use_altitude_chill && (surface_y > 0.f || river_y > 0.f))
510                                 t_heat -= alt_to_heat * MYMAX(surface_y, river_y) / altitude_chill;
511
512                         // If humidity is low or heat is high, lower the water table.
513                         float delta = m_bgen->humidmap[index_2d] - 50.f;
514                         if (delta < 0.f) {
515                                 float t_evap = (t_heat - 32.f) / evaporation;
516                                 river_y += delta * MYMAX(t_evap, 0.08f);
517                         }
518                 }
519
520                 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
521                 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
522
523                 // Mapgens concern themselves with stone and water.
524                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
525                         if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
526                                 float fill = noise_inter_valley_fill->result[index_3d];
527                                 float surface_delta = (float)y - surface_y;
528                                 bool river = y + 1 < river_y;
529
530                                 if (slope * fill > surface_delta) {
531                                         // ground
532                                         vm->m_data[index_data] = n_stone;
533                                         if (y > heightmap[index_2d])
534                                                 heightmap[index_2d] = y;
535                                         if (y > surface_max_y)
536                                                 surface_max_y = y;
537                                 } else if (y <= water_level) {
538                                         // sea
539                                         vm->m_data[index_data] = n_water;
540                                 } else if (river) {
541                                         // river
542                                         vm->m_data[index_data] = n_river_water;
543                                 } else {  // air
544                                         vm->m_data[index_data] = n_air;
545                                 }
546                         }
547
548                         vm->m_area.add_y(em, index_data, 1);
549                         index_3d += ystride;
550                 }
551
552                 // This happens if we're generating a chunk that doesn't
553                 // contain the terrain surface, in which case, we need
554                 // to set heightmap to a value outside of the chunk,
555                 // to avoid confusing lua mods that use heightmap.
556                 if (heightmap[index_2d] == -MAX_MAP_GENERATION_LIMIT) {
557                         s16 surface_y_int = myround(surface_y);
558                         if (surface_y_int > node_max.Y + 1 || surface_y_int < node_min.Y - 1) {
559                                 // If surface_y is outside the chunk, it's good enough.
560                                 heightmap[index_2d] = surface_y_int;
561                         } else {
562                                 // If the ground is outside of this chunk, but surface_y
563                                 // is within the chunk, give a value outside.
564                                 heightmap[index_2d] = node_min.Y - 2;
565                         }
566                 }
567
568                 if (humid_rivers) {
569                         // Use base ground (water table) in a riverbed, to
570                         // avoid an unnatural rise in humidity.
571                         float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
572                         float humid = m_bgen->humidmap[index_2d];
573                         float water_depth = (t_alt - river_y) / humidity_dropoff;
574                         humid *= 1.f + pow(0.5f, MYMAX(water_depth, 1.f));
575
576                         // Reduce humidity with altitude (ignoring riverbeds).
577                         // This is similar to the lua version's seawater adjustment,
578                         // but doesn't increase the base humidity, which causes
579                         // problems with the default biomes.
580                         if (t_alt > 0.f)
581                                 humid -= alt_to_humid * t_alt / altitude_chill;
582
583                         m_bgen->humidmap[index_2d] = humid;
584                 }
585
586                 // Assign the heat adjusted by any changed altitudes.
587                 // The altitude will change about half the time.
588                 if (use_altitude_chill) {
589                         // ground height ignoring riverbeds
590                         float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
591                         if (humid_rivers && heightmap[index_2d] == (s16)myround(surface_y))
592                                 // The altitude hasn't changed. Use the first result.
593                                 m_bgen->heatmap[index_2d] = t_heat;
594                         else if (t_alt > 0.f)
595                                 m_bgen->heatmap[index_2d] -= alt_to_heat * t_alt / altitude_chill;
596                 }
597         }
598
599         return surface_max_y;
600 }
601
602 void MapgenValleys::generateCaves(s16 max_stone_y, s16 large_cave_depth)
603 {
604         if (max_stone_y < node_min.Y)
605                 return;
606
607         noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
608         noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
609
610         PseudoRandom ps(blockseed + 72202);
611
612         MapNode n_air(CONTENT_AIR);
613         MapNode n_lava(c_lava_source);
614         MapNode n_water(c_river_water_source);
615
616         v3s16 em = vm->m_area.getExtent();
617
618         // Cave blend distance near YMIN, YMAX
619         const float massive_cave_blend = 128.f;
620         // noise threshold for massive caves
621         const float massive_cave_threshold = 0.6f;
622         // mct: 1 = small rare caves, 0.5 1/3rd ground volume, 0 = 1/2 ground volume.
623
624         float yblmin = -map_gen_limit + massive_cave_blend * 1.5f;
625         float yblmax = massive_cave_depth - massive_cave_blend * 1.5f;
626         bool made_a_big_one = false;
627
628         // Cache the tcave values as they only vary by altitude.
629         if (node_max.Y <= massive_cave_depth) {
630                 noise_massive_caves->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
631
632                 for (s16 y = node_min.Y - 1; y <= node_max.Y; y++) {
633                         float tcave = massive_cave_threshold;
634
635                         if (y < yblmin) {
636                                 float t = (yblmin - y) / massive_cave_blend;
637                                 tcave += MYSQUARE(t);
638                         } else if (y > yblmax) {
639                                 float t = (y - yblmax) / massive_cave_blend;
640                                 tcave += MYSQUARE(t);
641                         }
642
643                         tcave_cache[y - node_min.Y + 1] = tcave;
644                 }
645         }
646
647         // lava_depth varies between one and ten as you approach
648         //  the bottom of the world.
649         s16 lava_depth = ceil((lava_max_height - node_min.Y + 1) * 10.f / map_gen_limit);
650         // This allows random lava spawns to be less common at the surface.
651         s16 lava_chance = MYCUBE(lava_features_lim) * lava_depth;
652         // water_depth varies between ten and one on the way down.
653         s16 water_depth = ceil((map_gen_limit - abs(node_min.Y) + 1) * 10.f / map_gen_limit);
654         // This allows random water spawns to be more common at the surface.
655         s16 water_chance = MYCUBE(water_features_lim) * water_depth;
656
657         // Reduce the odds of overflows even further.
658         if (node_max.Y > water_level) {
659                 lava_chance /= 3;
660                 water_chance /= 3;
661         }
662
663         u32 index_2d = 0;
664         for (s16 z = node_min.Z; z <= node_max.Z; z++)
665         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
666                 Biome *biome = (Biome *)m_bmgr->getRaw(biomemap[index_2d]);
667                 bool tunnel_air_above = false;
668                 bool is_under_river = false;
669                 bool underground = false;
670                 u32 index_data = vm->m_area.index(x, node_max.Y, z);
671                 u32 index_3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride + (x - node_min.X);
672
673                 // Dig caves on down loop to check for air above.
674                 // Don't excavate the overgenerated stone at node_max.Y + 1,
675                 // this creates a 'roof' over the tunnel, preventing light in
676                 // tunnels at mapchunk borders when generating mapchunks upwards.
677                 // This 'roof' is removed when the mapchunk above is generated.
678                 for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
679                                 index_3d -= ystride,
680                                 vm->m_area.add_y(em, index_data, -1)) {
681
682                         float terrain = noise_terrain_height->result[index_2d];
683
684                         // Saves some time.
685                         if (y > terrain + 10)
686                                 continue;
687                         else if (y < terrain - 40)
688                                 underground = true;
689
690                         // Dig massive caves.
691                         if (node_max.Y <= massive_cave_depth
692                                         && noise_massive_caves->result[index_3d]
693                                         > tcave_cache[y - node_min.Y + 1]) {
694                                 vm->m_data[index_data] = n_air;
695                                 made_a_big_one = true;
696                                 continue;
697                         }
698
699                         content_t c = vm->m_data[index_data].getContent();
700                         // Detect river water to place riverbed nodes in tunnels
701                         if (c == biome->c_river_water)
702                                 is_under_river = true;
703
704                         float d1 = contour(noise_cave1->result[index_3d]);
705                         float d2 = contour(noise_cave2->result[index_3d]);
706
707                         if (d1 * d2 > cave_width && ndef->get(c).is_ground_content) {
708                                 // in a tunnel
709                                 vm->m_data[index_data] = n_air;
710                                 tunnel_air_above = true;
711                         } else if (c == biome->c_filler || c == biome->c_stone) {
712                                 if (tunnel_air_above) {
713                                         // at the tunnel floor
714                                         s16 sr = ps.range(0, 39);
715                                         u32 j = index_data;
716                                         vm->m_area.add_y(em, j, 1);
717
718                                         if (sr > terrain - y) {
719                                                 // Put biome nodes in tunnels near the surface
720                                                 if (is_under_river)
721                                                         vm->m_data[index_data] = MapNode(biome->c_riverbed);
722                                                 else if (underground)
723                                                         vm->m_data[index_data] = MapNode(biome->c_filler);
724                                                 else
725                                                         vm->m_data[index_data] = MapNode(biome->c_top);
726                                         } else if (sr < 3 && underground) {
727                                                 sr = abs(ps.next());
728                                                 if (lava_features_lim > 0 && y <= lava_max_height
729                                                                 && c == biome->c_stone && sr < lava_chance)
730                                                         vm->m_data[j] = n_lava;
731
732                                                 sr -= lava_chance;
733
734                                                 // If sr < 0 then we should have already placed lava --
735                                                 // don't immediately dump water on it.
736                                                 if (water_features_lim > 0 && y <= cave_water_max_height
737                                                                 && sr >= 0 && sr < water_chance)
738                                                         vm->m_data[j] = n_water;
739                                         }
740                                 }
741
742                                 tunnel_air_above = false;
743                                 underground = true;
744                         } else {
745                                 tunnel_air_above = false;
746                         }
747                 }
748         }
749
750         if (node_max.Y <= large_cave_depth && !made_a_big_one) {
751                 u32 bruises_count = ps.range(0, 2);
752                 for (u32 i = 0; i < bruises_count; i++) {
753                         CavesRandomWalk cave(ndef, &gennotify, seed, water_level,
754                                 c_water_source, c_lava_source);
755
756                         cave.makeCave(vm, node_min, node_max, &ps, true, max_stone_y, heightmap);
757                 }
758         }
759 }