]> git.lizzy.rs Git - minetest.git/blob - src/mapgen/mapgen_carpathian.cpp
Mgcarpathian: Fix spawn level calculation (#7212)
[minetest.git] / src / mapgen / mapgen_carpathian.cpp
1 /*
2 Minetest
3 Copyright (C) 2017-2018 vlapsley, Vaughan Lapsley <vlapsley@gmail.com>
4 Copyright (C) 2010-2018 paramat
5 Copyright (C) 2010-2018 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22
23 #include <cmath>
24 #include "mapgen.h"
25 #include "voxel.h"
26 #include "noise.h"
27 #include "mapblock.h"
28 #include "mapnode.h"
29 #include "map.h"
30 #include "content_sao.h"
31 #include "nodedef.h"
32 #include "voxelalgorithms.h"
33 //#include "profiler.h" // For TimeTaker
34 #include "settings.h" // For g_settings
35 #include "emerge.h"
36 #include "dungeongen.h"
37 #include "cavegen.h"
38 #include "mg_biome.h"
39 #include "mg_ore.h"
40 #include "mg_decoration.h"
41 #include "mapgen_carpathian.h"
42
43
44 FlagDesc flagdesc_mapgen_carpathian[] = {
45         {"caverns", MGCARPATHIAN_CAVERNS},
46         {NULL,      0}
47 };
48
49
50 ///////////////////////////////////////////////////////////////////////////////
51
52
53 MapgenCarpathian::MapgenCarpathian(
54                 int mapgenid, MapgenCarpathianParams *params, EmergeManager *emerge)
55         : MapgenBasic(mapgenid, params, emerge)
56 {
57         base_level       = params->base_level;
58
59         spflags          = params->spflags;
60         cave_width       = params->cave_width;
61         large_cave_depth = params->large_cave_depth;
62         lava_depth       = params->lava_depth;
63         cavern_limit     = params->cavern_limit;
64         cavern_taper     = params->cavern_taper;
65         cavern_threshold = params->cavern_threshold;
66         dungeon_ymin     = params->dungeon_ymin;
67         dungeon_ymax     = params->dungeon_ymax;
68
69         grad_wl = 1 - water_level;
70
71         //// 2D Terrain noise
72         noise_filler_depth  = new Noise(&params->np_filler_depth,  seed, csize.X, csize.Z);
73         noise_height1       = new Noise(&params->np_height1,       seed, csize.X, csize.Z);
74         noise_height2       = new Noise(&params->np_height2,       seed, csize.X, csize.Z);
75         noise_height3       = new Noise(&params->np_height3,       seed, csize.X, csize.Z);
76         noise_height4       = new Noise(&params->np_height4,       seed, csize.X, csize.Z);
77         noise_hills_terrain = new Noise(&params->np_hills_terrain, seed, csize.X, csize.Z);
78         noise_ridge_terrain = new Noise(&params->np_ridge_terrain, seed, csize.X, csize.Z);
79         noise_step_terrain  = new Noise(&params->np_step_terrain,  seed, csize.X, csize.Z);
80         noise_hills         = new Noise(&params->np_hills,         seed, csize.X, csize.Z);
81         noise_ridge_mnt     = new Noise(&params->np_ridge_mnt,     seed, csize.X, csize.Z);
82         noise_step_mnt      = new Noise(&params->np_step_mnt,      seed, csize.X, csize.Z);
83
84         //// 3D terrain noise
85         // 1 up 1 down overgeneration
86         noise_mnt_var = new Noise(&params->np_mnt_var, seed, csize.X, csize.Y + 2, csize.Z);
87
88         //// Cave noise
89         MapgenBasic::np_cave1  = params->np_cave1;
90         MapgenBasic::np_cave2  = params->np_cave2;
91         MapgenBasic::np_cavern = params->np_cavern;
92 }
93
94
95 MapgenCarpathian::~MapgenCarpathian()
96 {
97         delete noise_filler_depth;
98         delete noise_height1;
99         delete noise_height2;
100         delete noise_height3;
101         delete noise_height4;
102         delete noise_hills_terrain;
103         delete noise_ridge_terrain;
104         delete noise_step_terrain;
105         delete noise_hills;
106         delete noise_ridge_mnt;
107         delete noise_step_mnt;
108         delete noise_mnt_var;
109 }
110
111
112 MapgenCarpathianParams::MapgenCarpathianParams():
113         np_filler_depth  (0,  1,  v3f(128,  128,  128),  261,   3, 0.7,  2.0),
114         np_height1       (0,  5,  v3f(251,  251,  251),  9613,  5, 0.5,  2.0),
115         np_height2       (0,  5,  v3f(383,  383,  383),  1949,  5, 0.5,  2.0),
116         np_height3       (0,  5,  v3f(509,  509,  509),  3211,  5, 0.5,  2.0),
117         np_height4       (0,  5,  v3f(631,  631,  631),  1583,  5, 0.5,  2.0),
118         np_hills_terrain (1,  1,  v3f(1301, 1301, 1301), 1692,  5, 0.5,  2.0),
119         np_ridge_terrain (1,  1,  v3f(1889, 1889, 1889), 3568,  5, 0.5,  2.0),
120         np_step_terrain  (1,  1,  v3f(1889, 1889, 1889), 4157,  5, 0.5,  2.0),
121         np_hills         (0,  3,  v3f(257,  257,  257),  6604,  6, 0.5,  2.0),
122         np_ridge_mnt     (0,  12, v3f(743,  743,  743),  5520,  6, 0.7,  2.0),
123         np_step_mnt      (0,  8,  v3f(509,  509,  509),  2590,  6, 0.6,  2.0),
124         np_mnt_var       (0,  1,  v3f(499,  499,  499),  2490,  5, 0.55, 2.0),
125         np_cave1         (0,  12, v3f(61,   61,   61),   52534, 3, 0.5,  2.0),
126         np_cave2         (0,  12, v3f(67,   67,   67),   10325, 3, 0.5,  2.0),
127         np_cavern        (0,  1,  v3f(384,  128,  384),  723,   5, 0.63, 2.0)
128 {
129 }
130
131
132 void MapgenCarpathianParams::readParams(const Settings *settings)
133 {
134         settings->getFlagStrNoEx("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian);
135         settings->getFloatNoEx("mgcarpathian_base_level",       base_level);
136         settings->getFloatNoEx("mgcarpathian_cave_width",       cave_width);
137         settings->getS16NoEx("mgcarpathian_large_cave_depth",   large_cave_depth);
138         settings->getS16NoEx("mgcarpathian_lava_depth",         lava_depth);
139         settings->getS16NoEx("mgcarpathian_cavern_limit",       cavern_limit);
140         settings->getS16NoEx("mgcarpathian_cavern_taper",       cavern_taper);
141         settings->getFloatNoEx("mgcarpathian_cavern_threshold", cavern_threshold);
142         settings->getS16NoEx("mgcarpathian_dungeon_ymin",       dungeon_ymin);
143         settings->getS16NoEx("mgcarpathian_dungeon_ymax",       dungeon_ymax);
144
145         settings->getNoiseParams("mgcarpathian_np_filler_depth",  np_filler_depth);
146         settings->getNoiseParams("mgcarpathian_np_height1",       np_height1);
147         settings->getNoiseParams("mgcarpathian_np_height2",       np_height2);
148         settings->getNoiseParams("mgcarpathian_np_height3",       np_height3);
149         settings->getNoiseParams("mgcarpathian_np_height4",       np_height4);
150         settings->getNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain);
151         settings->getNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain);
152         settings->getNoiseParams("mgcarpathian_np_step_terrain",  np_step_terrain);
153         settings->getNoiseParams("mgcarpathian_np_hills",         np_hills);
154         settings->getNoiseParams("mgcarpathian_np_ridge_mnt",     np_ridge_mnt);
155         settings->getNoiseParams("mgcarpathian_np_step_mnt",      np_step_mnt);
156         settings->getNoiseParams("mgcarpathian_np_mnt_var",       np_mnt_var);
157         settings->getNoiseParams("mgcarpathian_np_cave1",         np_cave1);
158         settings->getNoiseParams("mgcarpathian_np_cave2",         np_cave2);
159         settings->getNoiseParams("mgcarpathian_np_cavern",        np_cavern);
160 }
161
162
163 void MapgenCarpathianParams::writeParams(Settings *settings) const
164 {
165         settings->setFlagStr("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian, U32_MAX);
166         settings->setFloat("mgcarpathian_base_level",       base_level);
167         settings->setFloat("mgcarpathian_cave_width",       cave_width);
168         settings->setS16("mgcarpathian_large_cave_depth",   large_cave_depth);
169         settings->setS16("mgcarpathian_lava_depth",         lava_depth);
170         settings->setS16("mgcarpathian_cavern_limit",       cavern_limit);
171         settings->setS16("mgcarpathian_cavern_taper",       cavern_taper);
172         settings->setFloat("mgcarpathian_cavern_threshold", cavern_threshold);
173         settings->setS16("mgcarpathian_dungeon_ymin",       dungeon_ymin);
174         settings->setS16("mgcarpathian_dungeon_ymax",       dungeon_ymax);
175
176         settings->setNoiseParams("mgcarpathian_np_filler_depth",  np_filler_depth);
177         settings->setNoiseParams("mgcarpathian_np_height1",       np_height1);
178         settings->setNoiseParams("mgcarpathian_np_height2",       np_height2);
179         settings->setNoiseParams("mgcarpathian_np_height3",       np_height3);
180         settings->setNoiseParams("mgcarpathian_np_height4",       np_height4);
181         settings->setNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain);
182         settings->setNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain);
183         settings->setNoiseParams("mgcarpathian_np_step_terrain",  np_step_terrain);
184         settings->setNoiseParams("mgcarpathian_np_hills",         np_hills);
185         settings->setNoiseParams("mgcarpathian_np_ridge_mnt",     np_ridge_mnt);
186         settings->setNoiseParams("mgcarpathian_np_step_mnt",      np_step_mnt);
187         settings->setNoiseParams("mgcarpathian_np_mnt_var",       np_mnt_var);
188         settings->setNoiseParams("mgcarpathian_np_cave1",         np_cave1);
189         settings->setNoiseParams("mgcarpathian_np_cave2",         np_cave2);
190         settings->setNoiseParams("mgcarpathian_np_cavern",        np_cavern);
191 }
192
193
194 ////////////////////////////////////////////////////////////////////////////////
195
196
197 // Lerp function
198 inline float MapgenCarpathian::getLerp(float noise1, float noise2, float mod)
199 {
200         return noise1 + mod * (noise2 - noise1);
201 }
202
203 // Steps function
204 float MapgenCarpathian::getSteps(float noise)
205 {
206         float w = 0.5f;
207         float k = std::floor(noise / w);
208         float f = (noise - k * w) / w;
209         float s = std::fmin(2.f * f, 1.f);
210         return (k + s) * w;
211 }
212
213
214 ////////////////////////////////////////////////////////////////////////////////
215
216
217 void MapgenCarpathian::makeChunk(BlockMakeData *data)
218 {
219         // Pre-conditions
220         assert(data->vmanip);
221         assert(data->nodedef);
222         assert(data->blockpos_requested.X >= data->blockpos_min.X &&
223                         data->blockpos_requested.Y >= data->blockpos_min.Y &&
224                         data->blockpos_requested.Z >= data->blockpos_min.Z);
225         assert(data->blockpos_requested.X <= data->blockpos_max.X &&
226                         data->blockpos_requested.Y <= data->blockpos_max.Y &&
227                         data->blockpos_requested.Z <= data->blockpos_max.Z);
228
229         this->generating = true;
230         this->vm = data->vmanip;
231         this->ndef = data->nodedef;
232
233         v3s16 blockpos_min = data->blockpos_min;
234         v3s16 blockpos_max = data->blockpos_max;
235         node_min = blockpos_min * MAP_BLOCKSIZE;
236         node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
237         full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
238         full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
239
240         // Create a block-specific seed
241         blockseed = getBlockSeed2(full_node_min, seed);
242
243         // Generate terrain
244         s16 stone_surface_max_y = generateTerrain();
245
246         // Create heightmap
247         updateHeightmap(node_min, node_max);
248
249         // Init biome generator, place biome-specific nodes, and build biomemap
250         biomegen->calcBiomeNoise(node_min);
251
252         MgStoneType mgstone_type;
253         content_t biome_stone;
254         generateBiomes(&mgstone_type, &biome_stone);
255
256         // Generate caverns, tunnels and classic caves
257         if (flags & MG_CAVES) {
258                 bool has_cavern = false;
259                 // Generate caverns
260                 if (spflags & MGCARPATHIAN_CAVERNS)
261                         has_cavern = generateCaverns(stone_surface_max_y);
262                 // Generate tunnels and classic caves
263                 if (has_cavern)
264                         // Disable classic caves in this mapchunk by setting
265                         // 'large cave depth' to world base. Avoids excessive liquid in
266                         // large caverns and floating blobs of overgenerated liquid.
267                         generateCaves(stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT);
268                 else
269                         generateCaves(stone_surface_max_y, large_cave_depth);
270         }
271
272         // Generate dungeons
273         if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
274                         full_node_max.Y <= dungeon_ymax)
275                 generateDungeons(stone_surface_max_y, mgstone_type, biome_stone);
276
277         // Generate the registered decorations
278         if (flags & MG_DECORATIONS)
279                 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
280
281         // Generate the registered ores
282         m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
283
284         // Sprinkle some dust on top after everything else was generated
285         dustTopNodes();
286
287         // Update liquids
288         updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
289
290         // Calculate lighting
291         if (flags & MG_LIGHT) {
292                 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
293                                 full_node_min, full_node_max);
294         }
295
296         this->generating = false;
297 }
298
299
300 ////////////////////////////////////////////////////////////////////////////////
301
302
303 int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p)
304 {
305         s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
306         if (level_at_point <= water_level || level_at_point > water_level + 32)
307                 return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
308
309         return level_at_point;
310 }
311
312
313 float MapgenCarpathian::terrainLevelAtPoint(s16 x, s16 z)
314 {
315         float height1 = NoisePerlin2D(&noise_height1->np, x, z, seed);
316         float height2 = NoisePerlin2D(&noise_height2->np, x, z, seed);
317         float height3 = NoisePerlin2D(&noise_height3->np, x, z, seed);
318         float height4 = NoisePerlin2D(&noise_height4->np, x, z, seed);
319         float hter = NoisePerlin2D(&noise_hills_terrain->np, x, z, seed);
320         float rter = NoisePerlin2D(&noise_ridge_terrain->np, x, z, seed);
321         float ster = NoisePerlin2D(&noise_step_terrain->np, x, z, seed);
322         float n_hills = NoisePerlin2D(&noise_hills->np, x, z, seed);
323         float n_ridge_mnt = NoisePerlin2D(&noise_ridge_mnt->np, x, z, seed);
324         float n_step_mnt = NoisePerlin2D(&noise_step_mnt->np, x, z, seed);
325
326         int height = -MAX_MAP_GENERATION_LIMIT;
327
328         for (s16 y = 1; y <= 30; y++) {
329                 float mnt_var = NoisePerlin3D(&noise_mnt_var->np, x, y, z, seed);
330
331                 // Gradient & shallow seabed
332                 s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y;
333
334                 // Hill/Mountain height (hilliness)
335                 float hill1 = getLerp(height1, height2, mnt_var);
336                 float hill2 = getLerp(height3, height4, mnt_var);
337                 float hill3 = getLerp(height3, height2, mnt_var);
338                 float hill4 = getLerp(height1, height4, mnt_var);
339                 float hilliness =
340                         std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
341
342                 // Rolling hills
343                 float hill_mnt = hilliness * std::pow(n_hills, 2.f);
344                 float hills = std::pow(std::fabs(hter), 3.f) * hill_mnt;
345
346                 // Ridged mountains
347                 float ridge_mnt = hilliness * (1.f - std::fabs(n_ridge_mnt));
348                 float ridged_mountains = std::pow(std::fabs(rter), 3.f) * ridge_mnt;
349
350                 // Step (terraced) mountains
351                 float step_mnt = hilliness * getSteps(n_step_mnt);
352                 float step_mountains = std::pow(std::fabs(ster), 3.f) * step_mnt;
353
354                 // Final terrain level
355                 float mountains = hills + ridged_mountains + step_mountains;
356                 float surface_level = base_level + mountains + grad;
357
358                 if (y > surface_level && height < 0)
359                         height = y;
360         }
361
362         return height;
363 }
364
365
366 ////////////////////////////////////////////////////////////////////////////////
367
368
369 int MapgenCarpathian::generateTerrain()
370 {
371         MapNode mn_air(CONTENT_AIR);
372         MapNode mn_stone(c_stone);
373         MapNode mn_water(c_water_source);
374
375         // Calculate noise for terrain generation
376         noise_height1->perlinMap2D(node_min.X, node_min.Z);
377         noise_height2->perlinMap2D(node_min.X, node_min.Z);
378         noise_height3->perlinMap2D(node_min.X, node_min.Z);
379         noise_height4->perlinMap2D(node_min.X, node_min.Z);
380         noise_hills_terrain->perlinMap2D(node_min.X, node_min.Z);
381         noise_ridge_terrain->perlinMap2D(node_min.X, node_min.Z);
382         noise_step_terrain->perlinMap2D(node_min.X, node_min.Z);
383         noise_hills->perlinMap2D(node_min.X, node_min.Z);
384         noise_ridge_mnt->perlinMap2D(node_min.X, node_min.Z);
385         noise_step_mnt->perlinMap2D(node_min.X, node_min.Z);
386         noise_mnt_var->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
387
388         //// Place nodes
389         const v3s16 &em = vm->m_area.getExtent();
390         s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
391         u32 index2d = 0;
392
393         for (s16 z = node_min.Z; z <= node_max.Z; z++)
394         for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
395                 // Hill/Mountain height (hilliness)
396                 float height1 = noise_height1->result[index2d];
397                 float height2 = noise_height2->result[index2d];
398                 float height3 = noise_height3->result[index2d];
399                 float height4 = noise_height4->result[index2d];
400
401                 // Rolling hills
402                 float hterabs = std::fabs(noise_hills_terrain->result[index2d]);
403                 float n_hills = noise_hills->result[index2d];
404                 float hill_mnt = hterabs * hterabs * hterabs * n_hills * n_hills;
405
406                 // Ridged mountains
407                 float rterabs = std::fabs(noise_ridge_terrain->result[index2d]);
408                 float n_ridge_mnt = noise_ridge_mnt->result[index2d];
409                 float ridge_mnt = rterabs * rterabs * rterabs *
410                         (1.f - std::fabs(n_ridge_mnt));
411
412                 // Step (terraced) mountains
413                 float sterabs = std::fabs(noise_step_terrain->result[index2d]);
414                 float n_step_mnt = noise_step_mnt->result[index2d];
415                 float step_mnt = sterabs * sterabs * sterabs * getSteps(n_step_mnt);
416
417                 // Initialise 3D noise index and voxelmanip index to column base
418                 u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
419                 u32 vi = vm->m_area.index(x, node_min.Y - 1, z);
420
421                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1;
422                                 y++,
423                                 index3d += ystride,
424                                 VoxelArea::add_y(em, vi, 1)) {
425                         if (vm->m_data[vi].getContent() != CONTENT_IGNORE)
426                                 continue;
427
428                         // Combine height noises and apply 3D variation
429                         float mnt_var = noise_mnt_var->result[index3d];
430                         float hill1 = getLerp(height1, height2, mnt_var);
431                         float hill2 = getLerp(height3, height4, mnt_var);
432                         float hill3 = getLerp(height3, height2, mnt_var);
433                         float hill4 = getLerp(height1, height4, mnt_var);
434
435                         // 'hilliness' determines whether hills/mountains are
436                         // small or large
437                         float hilliness =
438                                 std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
439                         float hills = hill_mnt * hilliness;
440                         float ridged_mountains = ridge_mnt * hilliness;
441                         float step_mountains = step_mnt * hilliness;
442
443                         // Gradient & shallow seabed
444                         s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 :
445                                 1 - y;
446
447                         // Final terrain level
448                         float mountains = hills + ridged_mountains + step_mountains;
449                         float surface_level = base_level + mountains + grad;
450
451                         if (y < surface_level) {
452                                 vm->m_data[vi] = mn_stone; // Stone
453                                 if (y > stone_surface_max_y)
454                                         stone_surface_max_y = y;
455                         } else if (y <= water_level) {
456                                 vm->m_data[vi] = mn_water; // Sea water
457                         } else {
458                                 vm->m_data[vi] = mn_air; // Air
459                         }
460                 }
461         }
462
463         return stone_surface_max_y;
464 }