]> git.lizzy.rs Git - dragonfireclient.git/blob - src/mapgen/mapgen_valleys.cpp
ContentCAO: Fix broken attachments on join (#8701)
[dragonfireclient.git] / src / mapgen / mapgen_valleys.cpp
1 /*
2 Minetest
3 Copyright (C) 2016-2019 Duane Robertson <duane@duanerobertson.com>
4 Copyright (C) 2016-2019 paramat
5
6 Based on Valleys Mapgen by Gael de Sailly
7 (https://forum.minetest.net/viewtopic.php?f=9&t=11430)
8 and mapgen_v7, mapgen_flat by kwolekr and paramat.
9
10 Licensing changed by permission of Gael de Sailly.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU Lesser General Public License as published by
14 the Free Software Foundation; either version 2.1 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU Lesser General Public License for more details.
21
22 You should have received a copy of the GNU Lesser General Public License along
23 with this program; if not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 */
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 "nodedef.h"
35 #include "voxelalgorithms.h"
36 //#include "profiler.h" // For TimeTaker
37 #include "settings.h" // For g_settings
38 #include "emerge.h"
39 #include "dungeongen.h"
40 #include "mg_biome.h"
41 #include "mg_ore.h"
42 #include "mg_decoration.h"
43 #include "mapgen_valleys.h"
44 #include "cavegen.h"
45 #include <cmath>
46
47
48 FlagDesc flagdesc_mapgen_valleys[] = {
49         {"altitude_chill",   MGVALLEYS_ALT_CHILL},
50         {"humid_rivers",     MGVALLEYS_HUMID_RIVERS},
51         {"vary_river_depth", MGVALLEYS_VARY_RIVER_DEPTH},
52         {"altitude_dry",     MGVALLEYS_ALT_DRY},
53         {NULL,               0}
54 };
55
56
57 MapgenValleys::MapgenValleys(MapgenValleysParams *params, EmergeManager *emerge)
58         : MapgenBasic(MAPGEN_VALLEYS, params, emerge)
59 {
60         // NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal
61         m_bgen = (BiomeGenOriginal *)biomegen;
62
63         spflags            = params->spflags;
64         altitude_chill     = params->altitude_chill;
65         river_depth_bed    = params->river_depth + 1.0f;
66         river_size_factor  = params->river_size / 100.0f;
67
68         cave_width         = params->cave_width;
69         large_cave_depth   = params->large_cave_depth;
70         lava_depth         = params->lava_depth;
71         cavern_limit       = params->cavern_limit;
72         cavern_taper       = params->cavern_taper;
73         cavern_threshold   = params->cavern_threshold;
74         dungeon_ymin       = params->dungeon_ymin;
75         dungeon_ymax       = params->dungeon_ymax;
76
77         //// 2D Terrain noise
78         noise_filler_depth       = new Noise(&params->np_filler_depth,       seed, csize.X, csize.Z);
79         noise_inter_valley_slope = new Noise(&params->np_inter_valley_slope, seed, csize.X, csize.Z);
80         noise_rivers             = new Noise(&params->np_rivers,             seed, csize.X, csize.Z);
81         noise_terrain_height     = new Noise(&params->np_terrain_height,     seed, csize.X, csize.Z);
82         noise_valley_depth       = new Noise(&params->np_valley_depth,       seed, csize.X, csize.Z);
83         noise_valley_profile     = new Noise(&params->np_valley_profile,     seed, csize.X, csize.Z);
84
85         //// 3D Terrain noise
86         // 1-up 1-down overgeneration
87         noise_inter_valley_fill = new Noise(&params->np_inter_valley_fill,
88                 seed, csize.X, csize.Y + 2, csize.Z);
89         // 1-down overgeneraion
90         MapgenBasic::np_cave1    = params->np_cave1;
91         MapgenBasic::np_cave2    = params->np_cave2;
92         MapgenBasic::np_cavern   = params->np_cavern;
93         MapgenBasic::np_dungeons = params->np_dungeons;
94 }
95
96
97 MapgenValleys::~MapgenValleys()
98 {
99         delete noise_filler_depth;
100         delete noise_inter_valley_fill;
101         delete noise_inter_valley_slope;
102         delete noise_rivers;
103         delete noise_terrain_height;
104         delete noise_valley_depth;
105         delete noise_valley_profile;
106 }
107
108
109 MapgenValleysParams::MapgenValleysParams():
110         np_filler_depth       (0.0,   1.2,  v3f(256,  256,  256),  1605,  3, 0.5,  2.0),
111         np_inter_valley_fill  (0.0,   1.0,  v3f(256,  512,  256),  1993,  6, 0.8,  2.0),
112         np_inter_valley_slope (0.5,   0.5,  v3f(128,  128,  128),  746,   1, 1.0,  2.0),
113         np_rivers             (0.0,   1.0,  v3f(256,  256,  256),  -6050, 5, 0.6,  2.0),
114         np_terrain_height     (-10.0, 50.0, v3f(1024, 1024, 1024), 5202,  6, 0.4,  2.0),
115         np_valley_depth       (5.0,   4.0,  v3f(512,  512,  512),  -1914, 1, 1.0,  2.0),
116         np_valley_profile     (0.6,   0.50, v3f(512,  512,  512),  777,   1, 1.0,  2.0),
117         np_cave1              (0.0,   12.0, v3f(61,   61,   61),   52534, 3, 0.5,  2.0),
118         np_cave2              (0.0,   12.0, v3f(67,   67,   67),   10325, 3, 0.5,  2.0),
119         np_cavern             (0.0,   1.0,  v3f(768,  256,  768),  59033, 6, 0.63, 2.0),
120         np_dungeons           (0.9,   0.5,  v3f(500,  500,  500),  0,     2, 0.8,  2.0)
121 {
122 }
123
124
125 void MapgenValleysParams::readParams(const Settings *settings)
126 {
127         settings->getFlagStrNoEx("mgvalleys_spflags",        spflags, flagdesc_mapgen_valleys);
128         settings->getU16NoEx("mgvalleys_altitude_chill",     altitude_chill);
129         settings->getS16NoEx("mgvalleys_large_cave_depth",   large_cave_depth);
130         settings->getS16NoEx("mgvalleys_lava_depth",         lava_depth);
131         settings->getU16NoEx("mgvalleys_river_depth",        river_depth);
132         settings->getU16NoEx("mgvalleys_river_size",         river_size);
133         settings->getFloatNoEx("mgvalleys_cave_width",       cave_width);
134         settings->getS16NoEx("mgvalleys_cavern_limit",       cavern_limit);
135         settings->getS16NoEx("mgvalleys_cavern_taper",       cavern_taper);
136         settings->getFloatNoEx("mgvalleys_cavern_threshold", cavern_threshold);
137         settings->getS16NoEx("mgvalleys_dungeon_ymin",       dungeon_ymin);
138         settings->getS16NoEx("mgvalleys_dungeon_ymax",       dungeon_ymax);
139
140         settings->getNoiseParams("mgvalleys_np_filler_depth",       np_filler_depth);
141         settings->getNoiseParams("mgvalleys_np_inter_valley_fill",  np_inter_valley_fill);
142         settings->getNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
143         settings->getNoiseParams("mgvalleys_np_rivers",             np_rivers);
144         settings->getNoiseParams("mgvalleys_np_terrain_height",     np_terrain_height);
145         settings->getNoiseParams("mgvalleys_np_valley_depth",       np_valley_depth);
146         settings->getNoiseParams("mgvalleys_np_valley_profile",     np_valley_profile);
147
148         settings->getNoiseParams("mgvalleys_np_cave1",              np_cave1);
149         settings->getNoiseParams("mgvalleys_np_cave2",              np_cave2);
150         settings->getNoiseParams("mgvalleys_np_cavern",             np_cavern);
151         settings->getNoiseParams("mgvalleys_np_dungeons",           np_dungeons);
152 }
153
154
155 void MapgenValleysParams::writeParams(Settings *settings) const
156 {
157         settings->setFlagStr("mgvalleys_spflags",        spflags, flagdesc_mapgen_valleys, U32_MAX);
158         settings->setU16("mgvalleys_altitude_chill",     altitude_chill);
159         settings->setS16("mgvalleys_large_cave_depth",   large_cave_depth);
160         settings->setS16("mgvalleys_lava_depth",         lava_depth);
161         settings->setU16("mgvalleys_river_depth",        river_depth);
162         settings->setU16("mgvalleys_river_size",         river_size);
163         settings->setFloat("mgvalleys_cave_width",       cave_width);
164         settings->setS16("mgvalleys_cavern_limit",       cavern_limit);
165         settings->setS16("mgvalleys_cavern_taper",       cavern_taper);
166         settings->setFloat("mgvalleys_cavern_threshold", cavern_threshold);
167         settings->setS16("mgvalleys_dungeon_ymin",       dungeon_ymin);
168         settings->setS16("mgvalleys_dungeon_ymax",       dungeon_ymax);
169
170         settings->setNoiseParams("mgvalleys_np_filler_depth",       np_filler_depth);
171         settings->setNoiseParams("mgvalleys_np_inter_valley_fill",  np_inter_valley_fill);
172         settings->setNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
173         settings->setNoiseParams("mgvalleys_np_rivers",             np_rivers);
174         settings->setNoiseParams("mgvalleys_np_terrain_height",     np_terrain_height);
175         settings->setNoiseParams("mgvalleys_np_valley_depth",       np_valley_depth);
176         settings->setNoiseParams("mgvalleys_np_valley_profile",     np_valley_profile);
177
178         settings->setNoiseParams("mgvalleys_np_cave1",              np_cave1);
179         settings->setNoiseParams("mgvalleys_np_cave2",              np_cave2);
180         settings->setNoiseParams("mgvalleys_np_cavern",             np_cavern);
181         settings->setNoiseParams("mgvalleys_np_dungeons",           np_dungeons);
182 }
183
184
185 void MapgenValleys::makeChunk(BlockMakeData *data)
186 {
187         // Pre-conditions
188         assert(data->vmanip);
189         assert(data->nodedef);
190         assert(data->blockpos_requested.X >= data->blockpos_min.X &&
191                 data->blockpos_requested.Y >= data->blockpos_min.Y &&
192                 data->blockpos_requested.Z >= data->blockpos_min.Z);
193         assert(data->blockpos_requested.X <= data->blockpos_max.X &&
194                 data->blockpos_requested.Y <= data->blockpos_max.Y &&
195                 data->blockpos_requested.Z <= data->blockpos_max.Z);
196
197         //TimeTaker t("makeChunk");
198
199         this->generating = true;
200         this->vm = data->vmanip;
201         this->ndef = data->nodedef;
202
203         v3s16 blockpos_min = data->blockpos_min;
204         v3s16 blockpos_max = data->blockpos_max;
205         node_min = blockpos_min * MAP_BLOCKSIZE;
206         node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
207         full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
208         full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
209
210         blockseed = getBlockSeed2(full_node_min, seed);
211
212         // Generate biome noises. Note this must be executed strictly before
213         // generateTerrain, because generateTerrain depends on intermediate
214         // biome-related noises.
215         m_bgen->calcBiomeNoise(node_min);
216
217         // Generate terrain
218         s16 stone_surface_max_y = generateTerrain();
219
220         // Create heightmap
221         updateHeightmap(node_min, node_max);
222
223         // Place biome-specific nodes and build biomemap
224         if (flags & MG_BIOMES) {
225                 generateBiomes();
226         }
227
228         // Generate tunnels, caverns and large randomwalk caves
229         if (flags & MG_CAVES) {
230                 // Generate tunnels first as caverns confuse them
231                 generateCavesNoiseIntersection(stone_surface_max_y);
232
233                 // Generate caverns
234                 bool near_cavern = generateCavernsNoise(stone_surface_max_y);
235
236                 // Generate large randomwalk caves
237                 if (near_cavern)
238                         // Disable large randomwalk caves in this mapchunk by setting
239                         // 'large cave depth' to world base. Avoids excessive liquid in
240                         // large caverns and floating blobs of overgenerated liquid.
241                         generateCavesRandomWalk(stone_surface_max_y,
242                                 -MAX_MAP_GENERATION_LIMIT);
243                 else
244                         generateCavesRandomWalk(stone_surface_max_y, large_cave_depth);
245         }
246
247         // Generate the registered ores
248         m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
249
250         // Dungeon creation
251         if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
252                         full_node_max.Y <= dungeon_ymax)
253                 generateDungeons(stone_surface_max_y);
254
255         // Generate the registered decorations
256         if (flags & MG_DECORATIONS)
257                 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
258
259         // Sprinkle some dust on top after everything else was generated
260         if (flags & MG_BIOMES)
261                 dustTopNodes();
262
263         updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
264
265         if (flags & MG_LIGHT)
266                 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
267                         full_node_min, full_node_max);
268
269         this->generating = false;
270
271         //printf("makeChunk: %lums\n", t.stop());
272 }
273
274
275 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
276 {
277         // Check if in a river channel
278         float n_rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
279         if (std::fabs(n_rivers) <= river_size_factor)
280                 // Unsuitable spawn point
281                 return MAX_MAP_GENERATION_LIMIT;
282
283         float n_slope          = NoisePerlin2D(&noise_inter_valley_slope->np, p.X, p.Y, seed);
284         float n_terrain_height = NoisePerlin2D(&noise_terrain_height->np, p.X, p.Y, seed);
285         float n_valley         = NoisePerlin2D(&noise_valley_depth->np, p.X, p.Y, seed);
286         float n_valley_profile = NoisePerlin2D(&noise_valley_profile->np, p.X, p.Y, seed);
287
288         float valley_d = n_valley * n_valley;
289         float base = n_terrain_height + valley_d;
290         float river = std::fabs(n_rivers) - river_size_factor;
291         float tv = std::fmax(river / n_valley_profile, 0.0f);
292         float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
293         float surface_y = base + valley_h;
294         float slope = n_slope * valley_h;
295         float river_y = base - 1.0f;
296
297         // Raising the maximum spawn level above 'water_level + 16' is necessary for custom
298         // parameters that set average terrain level much higher than water_level.
299         s16 max_spawn_y = std::fmax(
300                 noise_terrain_height->np.offset +
301                 noise_valley_depth->np.offset * noise_valley_depth->np.offset,
302                 water_level + 16);
303
304         // Starting spawn search at max_spawn_y + 128 ensures 128 nodes of open
305         // space above spawn position. Avoids spawning in possibly sealed voids.
306         for (s16 y = max_spawn_y + 128; y >= water_level; y--) {
307                 float n_fill = NoisePerlin3D(&noise_inter_valley_fill->np, p.X, y, p.Y, seed);
308                 float surface_delta = (float)y - surface_y;
309                 float density = slope * n_fill - surface_delta;
310
311                 if (density > 0.0f) {  // If solid
312                         // Sometimes surface level is below river water level in places that are not
313                         // river channels.
314                         if (y < water_level || y > max_spawn_y || y < (s16)river_y)
315                                 // Unsuitable spawn point
316                                 return MAX_MAP_GENERATION_LIMIT;
317
318                         // y + 2 because y is surface and due to biome 'dust' nodes.
319                         return y + 2;
320                 }
321         }
322         // Unsuitable spawn position, no ground found
323         return MAX_MAP_GENERATION_LIMIT;
324 }
325
326
327 int MapgenValleys::generateTerrain()
328 {
329         MapNode n_air(CONTENT_AIR);
330         MapNode n_river_water(c_river_water_source);
331         MapNode n_stone(c_stone);
332         MapNode n_water(c_water_source);
333
334         noise_inter_valley_slope->perlinMap2D(node_min.X, node_min.Z);
335         noise_rivers->perlinMap2D(node_min.X, node_min.Z);
336         noise_terrain_height->perlinMap2D(node_min.X, node_min.Z);
337         noise_valley_depth->perlinMap2D(node_min.X, node_min.Z);
338         noise_valley_profile->perlinMap2D(node_min.X, node_min.Z);
339
340         noise_inter_valley_fill->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
341
342         const v3s16 &em = vm->m_area.getExtent();
343         s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
344         u32 index_2d = 0;
345
346         for (s16 z = node_min.Z; z <= node_max.Z; z++)
347         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
348                 float n_slope          = noise_inter_valley_slope->result[index_2d];
349                 float n_rivers         = noise_rivers->result[index_2d];
350                 float n_terrain_height = noise_terrain_height->result[index_2d];
351                 float n_valley         = noise_valley_depth->result[index_2d];
352                 float n_valley_profile = noise_valley_profile->result[index_2d];
353
354                 float valley_d = n_valley * n_valley;
355                 // 'base' represents the level of the river banks
356                 float base = n_terrain_height + valley_d;
357                 // 'river' represents the distance from the river edge
358                 float river = std::fabs(n_rivers) - river_size_factor;
359                 // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
360                 // 'valley_h' represents the height of the terrain, from the rivers.
361                 float tv = std::fmax(river / n_valley_profile, 0.0f);
362                 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
363                 // Approximate height of the terrain
364                 float surface_y = base + valley_h;
365                 float slope = n_slope * valley_h;
366                 // River water surface is 1 node below river banks
367                 float river_y = base - 1.0f;
368
369                 // Rivers are placed where 'river' is negative
370                 if (river < 0.0f) {
371                         // Use the the function -sqrt(1-x^2) which models a circle
372                         float tr = river / river_size_factor + 1.0f;
373                         float depth = (river_depth_bed *
374                                 std::sqrt(std::fmax(0.0f, 1.0f - tr * tr)));
375                         // There is no logical equivalent to this using rangelim
376                         surface_y = std::fmin(
377                                 std::fmax(base - depth, (float)(water_level - 3)),
378                                 surface_y);
379                         slope = 0.0f;
380                 }
381
382                 // Optionally vary river depth according to heat and humidity
383                 if (spflags & MGVALLEYS_VARY_RIVER_DEPTH) {
384                         float t_heat = m_bgen->heatmap[index_2d];
385                         float heat = (spflags & MGVALLEYS_ALT_CHILL) ?
386                                 // Match heat value calculated below in
387                                 // 'Optionally decrease heat with altitude'.
388                                 // In rivers, 'ground height ignoring riverbeds' is 'base'.
389                                 // As this only affects river water we can assume y > water_level.
390                                 t_heat + 5.0f - (base - water_level) * 20.0f / altitude_chill :
391                                 t_heat;
392                         float delta = m_bgen->humidmap[index_2d] - 50.0f;
393                         if (delta < 0.0f) {
394                                 float t_evap = (heat - 32.0f) / 300.0f;
395                                 river_y += delta * std::fmax(t_evap, 0.08f);
396                         }
397                 }
398
399                 // Highest solid node in column
400                 s16 column_max_y = surface_y;
401                 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
402                 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
403
404                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
405                         if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
406                                 float n_fill = noise_inter_valley_fill->result[index_3d];
407                                 float surface_delta = (float)y - surface_y;
408                                 // Density = density noise + density gradient
409                                 float density = slope * n_fill - surface_delta;
410
411                                 if (density > 0.0f) {
412                                         vm->m_data[index_data] = n_stone; // Stone
413                                         if (y > surface_max_y)
414                                                 surface_max_y = y;
415                                         if (y > column_max_y)
416                                                 column_max_y = y;
417                                 } else if (y <= water_level) {
418                                         vm->m_data[index_data] = n_water; // Water
419                                 } else if (y <= (s16)river_y) {
420                                         vm->m_data[index_data] = n_river_water; // River water
421                                 } else {
422                                         vm->m_data[index_data] = n_air; // Air
423                                 }
424                         }
425
426                         VoxelArea::add_y(em, index_data, 1);
427                         index_3d += ystride;
428                 }
429
430                 // Optionally increase humidity around rivers
431                 if (spflags & MGVALLEYS_HUMID_RIVERS) {
432                         // Compensate to avoid increasing average humidity
433                         m_bgen->humidmap[index_2d] *= 0.8f;
434                         // Ground height ignoring riverbeds
435                         float t_alt = std::fmax(base, (float)column_max_y);
436                         float water_depth = (t_alt - base) / 4.0f;
437                         m_bgen->humidmap[index_2d] *=
438                                 1.0f + std::pow(0.5f, std::fmax(water_depth, 1.0f));
439                 }
440
441                 // Optionally decrease humidity with altitude
442                 if (spflags & MGVALLEYS_ALT_DRY) {
443                         // Ground height ignoring riverbeds
444                         float t_alt = std::fmax(base, (float)column_max_y);
445                         // Only decrease above water_level
446                         if (t_alt > water_level)
447                                 m_bgen->humidmap[index_2d] -=
448                                         (t_alt - water_level) * 10.0f / altitude_chill;
449                 }
450
451                 // Optionally decrease heat with altitude
452                 if (spflags & MGVALLEYS_ALT_CHILL) {
453                         // Compensate to avoid reducing the average heat
454                         m_bgen->heatmap[index_2d] += 5.0f;
455                         // Ground height ignoring riverbeds
456                         float t_alt = std::fmax(base, (float)column_max_y);
457                         // Only decrease above water_level
458                         if (t_alt > water_level)
459                                 m_bgen->heatmap[index_2d] -=
460                                         (t_alt - water_level) * 20.0f / altitude_chill;
461                 }
462         }
463
464         return surface_max_y;
465 }