Re-add dungeons in new dungeongen.cpp
[oweals/minetest.git] / src / mapgen.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "mapgen.h"
21 #include "voxel.h"
22 #include "noise.h"
23 #include "biome.h"
24 #include "mapblock.h"
25 #include "mapnode.h"
26 #include "map.h"
27 //#include "serverobject.h"
28 #include "content_sao.h"
29 #include "nodedef.h"
30 #include "content_mapnode.h" // For content_mapnode_get_new_name
31 #include "voxelalgorithms.h"
32 #include "profiler.h"
33 #include "settings.h" // For g_settings
34 #include "main.h" // For g_profiler
35 #include "treegen.h"
36 #include "mapgen_v6.h"
37
38 FlagDesc flagdesc_mapgen[] = {
39         {"trees",          MG_TREES},
40         {"caves",          MG_CAVES},
41         {"dungeons",       MG_DUNGEONS},
42         {"v6_forests",     MGV6_FORESTS},
43         {"v6_biome_blend", MGV6_BIOME_BLEND},
44         {"flat",           MG_FLAT},
45         {NULL,                     0}
46 };
47
48 ///////////////////////////////////////////////////////////////////////////////
49
50 /////////////////////
51
52 bool MapgenV6Params::readParams(Settings *settings) {
53         freq_desert = settings->getFloat("mgv6_freq_desert");
54         freq_beach  = settings->getFloat("mgv6_freq_beach");
55
56         np_terrain_base   = settings->getNoiseParams("mgv6_np_terrain_base");
57         np_terrain_higher = settings->getNoiseParams("mgv6_np_terrain_higher");
58         np_steepness      = settings->getNoiseParams("mgv6_np_steepness");
59         np_height_select  = settings->getNoiseParams("mgv6_np_height_select");
60         np_trees          = settings->getNoiseParams("mgv6_np_trees");
61         np_mud            = settings->getNoiseParams("mgv6_np_mud");
62         np_beach          = settings->getNoiseParams("mgv6_np_beach");
63         np_biome          = settings->getNoiseParams("mgv6_np_biome");
64         np_cave           = settings->getNoiseParams("mgv6_np_cave");
65
66         bool success =
67                 np_terrain_base  && np_terrain_higher && np_steepness &&
68                 np_height_select && np_trees          && np_mud       &&
69                 np_beach         && np_biome          && np_cave;
70         return success;
71 }
72
73
74 void MapgenV6Params::writeParams(Settings *settings) {
75         settings->setFloat("mgv6_freq_desert", freq_desert);
76         settings->setFloat("mgv6_freq_beach",  freq_beach);
77         
78         settings->setNoiseParams("mgv6_np_terrain_base",   np_terrain_base);
79         settings->setNoiseParams("mgv6_np_terrain_higher", np_terrain_higher);
80         settings->setNoiseParams("mgv6_np_steepness",      np_steepness);
81         settings->setNoiseParams("mgv6_np_height_select",  np_height_select);
82         settings->setNoiseParams("mgv6_np_trees",          np_trees);
83         settings->setNoiseParams("mgv6_np_mud",            np_mud);
84         settings->setNoiseParams("mgv6_np_beach",          np_beach);
85         settings->setNoiseParams("mgv6_np_biome",          np_biome);
86         settings->setNoiseParams("mgv6_np_cave",           np_cave);
87 }
88
89
90 /////////////////////////////////// legacy static functions for farmesh
91
92
93 s16 Mapgen::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) {
94         //just need to return something
95         s16 level = 5;
96         return level;
97 }
98
99
100 bool Mapgen::get_have_beach(u64 seed, v2s16 p2d) {
101         double sandnoise = noise2d_perlin(
102                         0.2+(float)p2d.X/250, 0.7+(float)p2d.Y/250,
103                         seed+59420, 3, 0.50);
104
105         return (sandnoise > 0.15);
106 }
107
108
109 double Mapgen::tree_amount_2d(u64 seed, v2s16 p) {
110         double noise = noise2d_perlin(
111                         0.5+(float)p.X/125, 0.5+(float)p.Y/125,
112                         seed+2, 4, 0.66);
113         double zeroval = -0.39;
114         if(noise < zeroval)
115                 return 0;
116         else
117                 return 0.04 * (noise-zeroval) / (1.0-zeroval);
118 }
119
120
121 #if 0 /// BIG COMMENT
122 namespace mapgen
123 {
124
125 /*
126         Some helper functions for the map generator
127 */
128
129 #if 1
130 // Returns Y one under area minimum if not found
131 static s16 find_ground_level(VoxelManipulator &vmanip, v2s16 p2d,
132                 INodeDefManager *ndef)
133 {
134         v3s16 em = vmanip.m_area.getExtent();
135         s16 y_nodes_max = vmanip.m_area.MaxEdge.Y;
136         s16 y_nodes_min = vmanip.m_area.MinEdge.Y;
137         u32 i = vmanip.m_area.index(v3s16(p2d.X, y_nodes_max, p2d.Y));
138         s16 y;
139         for(y=y_nodes_max; y>=y_nodes_min; y--)
140         {
141                 MapNode &n = vmanip.m_data[i];
142                 if(ndef->get(n).walkable)
143                         break;
144
145                 vmanip.m_area.add_y(em, i, -1);
146         }
147         if(y >= y_nodes_min)
148                 return y;
149         else
150                 return y_nodes_min - 1;
151 }
152
153 #if 0
154 // Returns Y one under area minimum if not found
155 static s16 find_ground_level_clever(VoxelManipulator &vmanip, v2s16 p2d,
156                 INodeDefManager *ndef)
157 {
158         if(!vmanip.m_area.contains(v3s16(p2d.X, vmanip.m_area.MaxEdge.Y, p2d.Y)))
159                 return vmanip.m_area.MinEdge.Y-1;
160         v3s16 em = vmanip.m_area.getExtent();
161         s16 y_nodes_max = vmanip.m_area.MaxEdge.Y;
162         s16 y_nodes_min = vmanip.m_area.MinEdge.Y;
163         u32 i = vmanip.m_area.index(v3s16(p2d.X, y_nodes_max, p2d.Y));
164         s16 y;
165         content_t c_tree = ndef->getId("mapgen_tree");
166         content_t c_leaves = ndef->getId("mapgen_leaves");
167         for(y=y_nodes_max; y>=y_nodes_min; y--)
168         {
169                 MapNode &n = vmanip.m_data[i];
170                 if(ndef->get(n).walkable
171                                 && n.getContent() != c_tree
172                                 && n.getContent() != c_leaves)
173                         break;
174
175                 vmanip.m_area.add_y(em, i, -1);
176         }
177         if(y >= y_nodes_min)
178                 return y;
179         else
180                 return y_nodes_min - 1;
181 }
182 #endif
183
184 // Returns Y one under area minimum if not found
185 static s16 find_stone_level(VoxelManipulator &vmanip, v2s16 p2d,
186                 INodeDefManager *ndef)
187 {
188         v3s16 em = vmanip.m_area.getExtent();
189         s16 y_nodes_max = vmanip.m_area.MaxEdge.Y;
190         s16 y_nodes_min = vmanip.m_area.MinEdge.Y;
191         u32 i = vmanip.m_area.index(v3s16(p2d.X, y_nodes_max, p2d.Y));
192         s16 y;
193         content_t c_stone = ndef->getId("mapgen_stone");
194         content_t c_desert_stone = ndef->getId("mapgen_desert_stone");
195         for(y=y_nodes_max; y>=y_nodes_min; y--)
196         {
197                 MapNode &n = vmanip.m_data[i];
198                 content_t c = n.getContent();
199                 if(c != CONTENT_IGNORE && (
200                                 c == c_stone || c == c_desert_stone))
201                         break;
202
203                 vmanip.m_area.add_y(em, i, -1);
204         }
205         if(y >= y_nodes_min)
206                 return y;
207         else
208                 return y_nodes_min - 1;
209 }
210 #endif
211
212
213 #if 0
214
215 static void make_papyrus(VoxelManipulator &vmanip, v3s16 p0,
216                 INodeDefManager *ndef)
217 {
218         MapNode papyrusnode(ndef->getId("mapgen_papyrus"));
219
220         s16 trunk_h = myrand_range(2, 3);
221         v3s16 p1 = p0;
222         for(s16 ii=0; ii<trunk_h; ii++)
223         {
224                 if(vmanip.m_area.contains(p1))
225                         vmanip.m_data[vmanip.m_area.index(p1)] = papyrusnode;
226                 p1.Y++;
227         }
228 }
229
230 static void make_cactus(VoxelManipulator &vmanip, v3s16 p0,
231                 INodeDefManager *ndef)
232 {
233         MapNode cactusnode(ndef->getId("mapgen_cactus"));
234
235         s16 trunk_h = 3;
236         v3s16 p1 = p0;
237         for(s16 ii=0; ii<trunk_h; ii++)
238         {
239                 if(vmanip.m_area.contains(p1))
240                         vmanip.m_data[vmanip.m_area.index(p1)] = cactusnode;
241                 p1.Y++;
242         }
243 }
244 #endif
245
246
247
248 #if 0
249 static void make_nc(VoxelManipulator &vmanip, PseudoRandom &random,
250                 INodeDefManager *ndef)
251 {
252         v3s16 dir;
253         u8 facedir_i = 0;
254         s32 r = random.range(0, 3);
255         if(r == 0){
256                 dir = v3s16( 1, 0, 0);
257                 facedir_i = 3;
258         }
259         if(r == 1){
260                 dir = v3s16(-1, 0, 0);
261                 facedir_i = 1;
262         }
263         if(r == 2){
264                 dir = v3s16( 0, 0, 1);
265                 facedir_i = 2;
266         }
267         if(r == 3){
268                 dir = v3s16( 0, 0,-1);
269                 facedir_i = 0;
270         }
271         v3s16 p = vmanip.m_area.MinEdge + v3s16(
272                         16+random.range(0,15),
273                         16+random.range(0,15),
274                         16+random.range(0,15));
275         vmanip.m_data[vmanip.m_area.index(p)] = MapNode(ndef->getId("mapgen_nyancat"), facedir_i);
276         u32 length = random.range(3,15);
277         for(u32 j=0; j<length; j++)
278         {
279                 p -= dir;
280                 vmanip.m_data[vmanip.m_area.index(p)] = MapNode(ndef->getId("mapgen_nyancat_rainbow"));
281         }
282 }
283 #endif
284
285 /*
286         Noise functions. Make sure seed is mangled differently in each one.
287 */
288
289 #if 0
290 /*
291         Scaling the output of the noise function affects the overdrive of the
292         contour function, which affects the shape of the output considerably.
293 */
294 #define CAVE_NOISE_SCALE 12.0
295 //#define CAVE_NOISE_SCALE 10.0
296 //#define CAVE_NOISE_SCALE 7.5
297 //#define CAVE_NOISE_SCALE 5.0
298 //#define CAVE_NOISE_SCALE 1.0
299
300 //#define CAVE_NOISE_THRESHOLD (2.5/CAVE_NOISE_SCALE)
301 #define CAVE_NOISE_THRESHOLD (1.5/CAVE_NOISE_SCALE)
302
303 NoiseParams get_cave_noise1_params(u64 seed)
304 {
305         /*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.7,
306                         200, CAVE_NOISE_SCALE);*/
307         /*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 4, 0.7,
308                         100, CAVE_NOISE_SCALE);*/
309         /*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.6,
310                         100, CAVE_NOISE_SCALE);*/
311         /*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.3,
312                         100, CAVE_NOISE_SCALE);*/
313         return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 4, 0.5,
314                         50, CAVE_NOISE_SCALE);
315         //return NoiseParams(NOISE_CONSTANT_ONE);
316 }
317
318 NoiseParams get_cave_noise2_params(u64 seed)
319 {
320         /*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.7,
321                         200, CAVE_NOISE_SCALE);*/
322         /*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 4, 0.7,
323                         100, CAVE_NOISE_SCALE);*/
324         /*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.3,
325                         100, CAVE_NOISE_SCALE);*/
326         return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 4, 0.5,
327                         50, CAVE_NOISE_SCALE);
328         //return NoiseParams(NOISE_CONSTANT_ONE);
329 }
330
331 NoiseParams get_ground_noise1_params(u64 seed)
332 {
333         return NoiseParams(NOISE_PERLIN, seed+983240, 4,
334                         0.55, 80.0, 40.0);
335 }
336
337 NoiseParams get_ground_crumbleness_params(u64 seed)
338 {
339         return NoiseParams(NOISE_PERLIN, seed+34413, 3,
340                         1.3, 20.0, 1.0);
341 }
342
343 NoiseParams get_ground_wetness_params(u64 seed)
344 {
345         return NoiseParams(NOISE_PERLIN, seed+32474, 4,
346                         1.1, 40.0, 1.0);
347 }
348
349 bool is_cave(u64 seed, v3s16 p)
350 {
351         double d1 = noise3d_param(get_cave_noise1_params(seed), p.X,p.Y,p.Z);
352         double d2 = noise3d_param(get_cave_noise2_params(seed), p.X,p.Y,p.Z);
353         return d1*d2 > CAVE_NOISE_THRESHOLD;
354 }
355
356 /*
357         Ground density noise shall be interpreted by using this.
358
359         TODO: No perlin noises here, they should be outsourced
360               and buffered
361                   NOTE: The speed of these actually isn't terrible
362 */
363 bool val_is_ground(double ground_noise1_val, v3s16 p, u64 seed)
364 {
365         //return ((double)p.Y < ground_noise1_val);
366
367         double f = 0.55 + noise2d_perlin(
368                         0.5+(float)p.X/250, 0.5+(float)p.Z/250,
369                         seed+920381, 3, 0.45);
370         if(f < 0.01)
371                 f = 0.01;
372         else if(f >= 1.0)
373                 f *= 1.6;
374         double h = WATER_LEVEL + 10 * noise2d_perlin(
375                         0.5+(float)p.X/250, 0.5+(float)p.Z/250,
376                         seed+84174, 4, 0.5);
377         /*double f = 1;
378         double h = 0;*/
379         return ((double)p.Y - h < ground_noise1_val * f);
380 }
381
382 /*
383         Queries whether a position is ground or not.
384 */
385 bool is_ground(u64 seed, v3s16 p)
386 {
387         double val1 = noise3d_param(get_ground_noise1_params(seed), p.X,p.Y,p.Z);
388         return val_is_ground(val1, p, seed);
389 }
390 #endif
391
392 // Amount of trees per area in nodes
393 double tree_amount_2d(u64 seed, v2s16 p)
394 {
395         /*double noise = noise2d_perlin(
396                         0.5+(float)p.X/250, 0.5+(float)p.Y/250,
397                         seed+2, 5, 0.66);*/
398         double noise = noise2d_perlin(
399                         0.5+(float)p.X/125, 0.5+(float)p.Y/125,
400                         seed+2, 4, 0.66);
401         double zeroval = -0.39;
402         if(noise < zeroval)
403                 return 0;
404         else
405                 return 0.04 * (noise-zeroval) / (1.0-zeroval);
406 }
407
408 #if 0
409 double surface_humidity_2d(u64 seed, v2s16 p)
410 {
411         double noise = noise2d_perlin(
412                         0.5+(float)p.X/500, 0.5+(float)p.Y/500,
413                         seed+72384, 4, 0.66);
414         noise = (noise + 1.0)/2.0;
415         if(noise < 0.0)
416                 noise = 0.0;
417         if(noise > 1.0)
418                 noise = 1.0;
419         return noise;
420 }
421
422 /*
423         Incrementally find ground level from 3d noise
424 */
425 s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision)
426 {
427         // Start a bit fuzzy to make averaging lower precision values
428         // more useful
429         s16 level = myrand_range(-precision/2, precision/2);
430         s16 dec[] = {31000, 100, 20, 4, 1, 0};
431         s16 i;
432         for(i = 1; dec[i] != 0 && precision <= dec[i]; i++)
433         {
434                 // First find non-ground by going upwards
435                 // Don't stop in caves.
436                 {
437                         s16 max = level+dec[i-1]*2;
438                         v3s16 p(p2d.X, level, p2d.Y);
439                         for(; p.Y < max; p.Y += dec[i])
440                         {
441                                 if(!is_ground(seed, p))
442                                 {
443                                         level = p.Y;
444                                         break;
445                                 }
446                         }
447                 }
448                 // Then find ground by going downwards from there.
449                 // Go in caves, too, when precision is 1.
450                 {
451                         s16 min = level-dec[i-1]*2;
452                         v3s16 p(p2d.X, level, p2d.Y);
453                         for(; p.Y>min; p.Y-=dec[i])
454                         {
455                                 bool ground = is_ground(seed, p);
456                                 /*if(dec[i] == 1 && is_cave(seed, p))
457                                         ground = false;*/
458                                 if(ground)
459                                 {
460                                         level = p.Y;
461                                         break;
462                                 }
463                         }
464                 }
465         }
466
467         // This is more like the actual ground level
468         level += dec[i-1]/2;
469
470         return level;
471 }
472
473 double get_sector_average_ground_level(u64 seed, v2s16 sectorpos, double p=4);
474
475 double get_sector_average_ground_level(u64 seed, v2s16 sectorpos, double p)
476 {
477         v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
478         v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
479         double a = 0;
480         a += find_ground_level_from_noise(seed,
481                         v2s16(node_min.X, node_min.Y), p);
482         a += find_ground_level_from_noise(seed,
483                         v2s16(node_min.X, node_max.Y), p);
484         a += find_ground_level_from_noise(seed,
485                         v2s16(node_max.X, node_max.Y), p);
486         a += find_ground_level_from_noise(seed,
487                         v2s16(node_max.X, node_min.Y), p);
488         a += find_ground_level_from_noise(seed,
489                         v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p);
490         a /= 5;
491         return a;
492 }
493
494 double get_sector_maximum_ground_level(u64 seed, v2s16 sectorpos, double p=4);
495
496 double get_sector_maximum_ground_level(u64 seed, v2s16 sectorpos, double p)
497 {
498         v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
499         v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
500         double a = -31000;
501         // Corners
502         a = MYMAX(a, find_ground_level_from_noise(seed,
503                         v2s16(node_min.X, node_min.Y), p));
504         a = MYMAX(a, find_ground_level_from_noise(seed,
505                         v2s16(node_min.X, node_max.Y), p));
506         a = MYMAX(a, find_ground_level_from_noise(seed,
507                         v2s16(node_max.X, node_max.Y), p));
508         a = MYMAX(a, find_ground_level_from_noise(seed,
509                         v2s16(node_min.X, node_min.Y), p));
510         // Center
511         a = MYMAX(a, find_ground_level_from_noise(seed,
512                         v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p));
513         // Side middle points
514         a = MYMAX(a, find_ground_level_from_noise(seed,
515                         v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y), p));
516         a = MYMAX(a, find_ground_level_from_noise(seed,
517                         v2s16(node_min.X+MAP_BLOCKSIZE/2, node_max.Y), p));
518         a = MYMAX(a, find_ground_level_from_noise(seed,
519                         v2s16(node_min.X, node_min.Y+MAP_BLOCKSIZE/2), p));
520         a = MYMAX(a, find_ground_level_from_noise(seed,
521                         v2s16(node_max.X, node_min.Y+MAP_BLOCKSIZE/2), p));
522         return a;
523 }
524
525 double get_sector_minimum_ground_level(u64 seed, v2s16 sectorpos, double p=4);
526
527 double get_sector_minimum_ground_level(u64 seed, v2s16 sectorpos, double p)
528 {
529         v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
530         v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
531         double a = 31000;
532         // Corners
533         a = MYMIN(a, find_ground_level_from_noise(seed,
534                         v2s16(node_min.X, node_min.Y), p));
535         a = MYMIN(a, find_ground_level_from_noise(seed,
536                         v2s16(node_min.X, node_max.Y), p));
537         a = MYMIN(a, find_ground_level_from_noise(seed,
538                         v2s16(node_max.X, node_max.Y), p));
539         a = MYMIN(a, find_ground_level_from_noise(seed,
540                         v2s16(node_min.X, node_min.Y), p));
541         // Center
542         a = MYMIN(a, find_ground_level_from_noise(seed,
543                         v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p));
544         // Side middle points
545         a = MYMIN(a, find_ground_level_from_noise(seed,
546                         v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y), p));
547         a = MYMIN(a, find_ground_level_from_noise(seed,
548                         v2s16(node_min.X+MAP_BLOCKSIZE/2, node_max.Y), p));
549         a = MYMIN(a, find_ground_level_from_noise(seed,
550                         v2s16(node_min.X, node_min.Y+MAP_BLOCKSIZE/2), p));
551         a = MYMIN(a, find_ground_level_from_noise(seed,
552                         v2s16(node_max.X, node_min.Y+MAP_BLOCKSIZE/2), p));
553         return a;
554 }
555 #endif
556
557 // Required by mapgen.h
558 bool block_is_underground(u64 seed, v3s16 blockpos)
559 {
560         /*s16 minimum_groundlevel = (s16)get_sector_minimum_ground_level(
561                         seed, v2s16(blockpos.X, blockpos.Z));*/
562         // Nah, this is just a heuristic, just return something
563         s16 minimum_groundlevel = WATER_LEVEL;
564
565         if(blockpos.Y*MAP_BLOCKSIZE + MAP_BLOCKSIZE <= minimum_groundlevel)
566                 return true;
567         else
568                 return false;
569 }
570
571 #define AVERAGE_MUD_AMOUNT 4
572
573 double base_rock_level_2d(u64 seed, v2s16 p)
574 {
575         // The base ground level
576         double base = (double)WATER_LEVEL - (double)AVERAGE_MUD_AMOUNT
577                         + 20. * noise2d_perlin(
578                         0.5+(float)p.X/250., 0.5+(float)p.Y/250.,
579                         seed+82341, 5, 0.6);
580
581         /*// A bit hillier one
582         double base2 = WATER_LEVEL - 4.0 + 40. * noise2d_perlin(
583                         0.5+(float)p.X/250., 0.5+(float)p.Y/250.,
584                         seed+93413, 6, 0.69);
585         if(base2 > base)
586                 base = base2;*/
587 #if 1
588         // Higher ground level
589         double higher = (double)WATER_LEVEL + 20. + 16. * noise2d_perlin(
590                         0.5+(float)p.X/500., 0.5+(float)p.Y/500.,
591                         seed+85039, 5, 0.6);
592         //higher = 30; // For debugging
593
594         // Limit higher to at least base
595         if(higher < base)
596                 higher = base;
597
598         // Steepness factor of cliffs
599         double b = 0.85 + 0.5 * noise2d_perlin(
600                         0.5+(float)p.X/125., 0.5+(float)p.Y/125.,
601                         seed-932, 5, 0.7);
602         b = rangelim(b, 0.0, 1000.0);
603         b = b*b*b*b*b*b*b;
604         b *= 5;
605         b = rangelim(b, 0.5, 1000.0);
606         // Values 1.5...100 give quite horrible looking slopes
607         if(b > 1.5 && b < 100.0){
608                 if(b < 10.0)
609                         b = 1.5;
610                 else
611                         b = 100.0;
612         }
613         //dstream<<"b="<<b<<std::endl;
614         //double b = 20;
615         //b = 0.25;
616
617         // Offset to more low
618         double a_off = -0.20;
619         // High/low selector
620         /*double a = 0.5 + b * (a_off + noise2d_perlin(
621                         0.5+(float)p.X/500., 0.5+(float)p.Y/500.,
622                         seed+4213, 6, 0.7));*/
623         double a = (double)0.5 + b * (a_off + noise2d_perlin(
624                         0.5+(float)p.X/250., 0.5+(float)p.Y/250.,
625                         seed+4213, 5, 0.69));
626         // Limit
627         a = rangelim(a, 0.0, 1.0);
628
629         //dstream<<"a="<<a<<std::endl;
630
631         double h = base*(1.0-a) + higher*a;
632 #else
633         double h = base;
634 #endif
635         return h;
636 }
637
638 s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision)
639 {
640         return base_rock_level_2d(seed, p2d) + AVERAGE_MUD_AMOUNT;
641 }
642
643 double get_mud_add_amount(u64 seed, v2s16 p)
644 {
645         return ((float)AVERAGE_MUD_AMOUNT + 2.0 * noise2d_perlin(
646                         0.5+(float)p.X/200, 0.5+(float)p.Y/200,
647                         seed+91013, 3, 0.55));
648 }
649
650 bool get_have_beach(u64 seed, v2s16 p2d)
651 {
652         // Determine whether to have sand here
653         double sandnoise = noise2d_perlin(
654                         0.2+(float)p2d.X/250, 0.7+(float)p2d.Y/250,
655                         seed+59420, 3, 0.50);
656
657         return (sandnoise > 0.15);
658 }
659
660 enum BiomeType
661 {
662         BT_NORMAL,
663         BT_DESERT
664 };
665
666 BiomeType get_biome(u64 seed, v2s16 p2d)
667 {
668         // Just do something very simple as for now
669         double d = noise2d_perlin(
670                         0.6+(float)p2d.X/250, 0.2+(float)p2d.Y/250,
671                         seed+9130, 3, 0.50);
672         if(d > 0.45)
673                 return BT_DESERT;
674         if(d > 0.35 && (noise2d( p2d.X, p2d.Y, int(seed) ) + 1.0) > ( 0.45 - d ) * 20.0  )
675                 return BT_DESERT;
676         return BT_NORMAL;
677 };
678
679 u32 get_blockseed(u64 seed, v3s16 p)
680 {
681         s32 x=p.X, y=p.Y, z=p.Z;
682         return (u32)(seed%0x100000000ULL) + z*38134234 + y*42123 + x*23;
683 }
684
685 #define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1
686
687 void make_block(BlockMakeData *data)
688 {
689         if(data->no_op)
690         {
691                 //dstream<<"makeBlock: no-op"<<std::endl;
692                 return;
693         }
694
695         assert(data->vmanip);
696         assert(data->nodedef);
697         assert(data->blockpos_requested.X >= data->blockpos_min.X &&
698                         data->blockpos_requested.Y >= data->blockpos_min.Y &&
699                         data->blockpos_requested.Z >= data->blockpos_min.Z);
700         assert(data->blockpos_requested.X <= data->blockpos_max.X &&
701                         data->blockpos_requested.Y <= data->blockpos_max.Y &&
702                         data->blockpos_requested.Z <= data->blockpos_max.Z);
703
704         INodeDefManager *ndef = data->nodedef;
705
706         // Hack: use minimum block coordinates for old code that assumes
707         // a single block
708         v3s16 blockpos = data->blockpos_requested;
709
710         /*dstream<<"makeBlock(): ("<<blockpos.X<<","<<blockpos.Y<<","
711                         <<blockpos.Z<<")"<<std::endl;*/
712
713         v3s16 blockpos_min = data->blockpos_min;
714         v3s16 blockpos_max = data->blockpos_max;
715         v3s16 blockpos_full_min = blockpos_min - v3s16(1,1,1);
716         v3s16 blockpos_full_max = blockpos_max + v3s16(1,1,1);
717
718         ManualMapVoxelManipulator &vmanip = *(data->vmanip);
719         // Area of central chunk
720         v3s16 node_min = blockpos_min*MAP_BLOCKSIZE;
721         v3s16 node_max = (blockpos_max+v3s16(1,1,1))*MAP_BLOCKSIZE-v3s16(1,1,1);
722         // Full allocated area
723         v3s16 full_node_min = (blockpos_min-1)*MAP_BLOCKSIZE;
724         v3s16 full_node_max = (blockpos_max+2)*MAP_BLOCKSIZE-v3s16(1,1,1);
725
726         v3s16 central_area_size = node_max - node_min + v3s16(1,1,1);
727
728         const s16 max_spread_amount = MAP_BLOCKSIZE;
729
730         int volume_blocks = (blockpos_max.X - blockpos_min.X + 1)
731                         * (blockpos_max.Y - blockpos_min.Y + 1)
732                         * (blockpos_max.Z - blockpos_max.Z + 1);
733
734         int volume_nodes = volume_blocks *
735                         MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
736
737         // Generated surface area
738         //double gen_area_nodes = MAP_BLOCKSIZE*MAP_BLOCKSIZE * rel_volume;
739
740         // Horribly wrong heuristic, but better than nothing
741         bool block_is_underground = (WATER_LEVEL > node_max.Y);
742
743         /*
744                 Create a block-specific seed
745         */
746         u32 blockseed = get_blockseed(data->seed, full_node_min);
747
748         /*
749                 Cache some ground type values for speed
750         */
751
752 // Creates variables c_name=id and n_name=node
753 #define CONTENT_VARIABLE(ndef, name)\
754         content_t c_##name = ndef->getId("mapgen_" #name);\
755         MapNode n_##name(c_##name);
756 // Default to something else if was CONTENT_IGNORE
757 #define CONTENT_VARIABLE_FALLBACK(name, dname)\
758         if(c_##name == CONTENT_IGNORE){\
759                 c_##name = c_##dname;\
760                 n_##name = n_##dname;\
761         }
762
763         CONTENT_VARIABLE(ndef, stone);
764         CONTENT_VARIABLE(ndef, air);
765         CONTENT_VARIABLE(ndef, water_source);
766         CONTENT_VARIABLE(ndef, dirt);
767         CONTENT_VARIABLE(ndef, sand);
768         CONTENT_VARIABLE(ndef, gravel);
769         CONTENT_VARIABLE(ndef, clay);
770         CONTENT_VARIABLE(ndef, lava_source);
771         CONTENT_VARIABLE(ndef, cobble);
772         CONTENT_VARIABLE(ndef, mossycobble);
773         CONTENT_VARIABLE(ndef, dirt_with_grass);
774         CONTENT_VARIABLE(ndef, junglegrass);
775         CONTENT_VARIABLE(ndef, stone_with_coal);
776         CONTENT_VARIABLE(ndef, stone_with_iron);
777         CONTENT_VARIABLE(ndef, mese);
778         CONTENT_VARIABLE(ndef, desert_sand);
779         CONTENT_VARIABLE_FALLBACK(desert_sand, sand);
780         CONTENT_VARIABLE(ndef, desert_stone);
781         CONTENT_VARIABLE_FALLBACK(desert_stone, stone);
782
783         // Maximum height of the stone surface and obstacles.
784         // This is used to guide the cave generation
785         s16 stone_surface_max_y = 0;
786
787         /*
788                 Generate general ground level to full area
789         */
790         {
791 #if 1
792         TimeTaker timer1("Generating ground level");
793
794         for(s16 x=node_min.X; x<=node_max.X; x++)
795         for(s16 z=node_min.Z; z<=node_max.Z; z++)
796         {
797                 // Node position
798                 v2s16 p2d = v2s16(x,z);
799
800                 /*
801                         Skip of already generated
802                 */
803                 /*{
804                         v3s16 p(p2d.X, node_min.Y, p2d.Y);
805                         if(vmanip.m_data[vmanip.m_area.index(p)].d != CONTENT_AIR)
806                                 continue;
807                 }*/
808
809                 // Ground height at this point
810                 float surface_y_f = 0.0;
811
812                 // Use perlin noise for ground height
813                 surface_y_f = base_rock_level_2d(data->seed, p2d);
814
815                 /*// Experimental stuff
816                 {
817                         float a = highlands_level_2d(data->seed, p2d);
818                         if(a > surface_y_f)
819                                 surface_y_f = a;
820                 }*/
821
822                 // Convert to integer
823                 s16 surface_y = (s16)surface_y_f;
824
825                 // Log it
826                 if(surface_y > stone_surface_max_y)
827                         stone_surface_max_y = surface_y;
828
829                 BiomeType bt = get_biome(data->seed, p2d);
830                 /*
831                         Fill ground with stone
832                 */
833                 {
834                         // Use fast index incrementing
835                         v3s16 em = vmanip.m_area.getExtent();
836                         u32 i = vmanip.m_area.index(v3s16(p2d.X, node_min.Y, p2d.Y));
837                         for(s16 y=node_min.Y; y<=node_max.Y; y++)
838                         {
839                                 if(vmanip.m_data[i].getContent() == CONTENT_IGNORE){
840                                         if(y <= surface_y){
841                                                 if(y > WATER_LEVEL && bt == BT_DESERT)
842                                                         vmanip.m_data[i] = n_desert_stone;
843                                                 else
844                                                         vmanip.m_data[i] = n_stone;
845                                         } else if(y <= WATER_LEVEL){
846                                                 vmanip.m_data[i] = MapNode(c_water_source);
847                                         } else {
848                                                 vmanip.m_data[i] = MapNode(c_air);
849                                         }
850                                 }
851                                 vmanip.m_area.add_y(em, i, 1);
852                         }
853                 }
854         }
855 #endif
856
857         }//timer1
858
859         // Limit dirt flow area by 1 because mud is flown into neighbors.
860         assert(central_area_size.X == central_area_size.Z);
861         s16 mudflow_minpos = 0-max_spread_amount+1;
862         s16 mudflow_maxpos = central_area_size.X+max_spread_amount-2;
863
864         /*
865                 Loop this part, it will make stuff look older and newer nicely
866         */
867
868         const u32 age_loops = 2;
869         for(u32 i_age=0; i_age<age_loops; i_age++)
870         { // Aging loop
871         /******************************
872                 BEGINNING OF AGING LOOP
873         ******************************/
874
875 #if 1
876         {
877         // 24ms @cs=8
878         //TimeTaker timer1("caves");
879
880         /*
881                 Make caves (this code is relatively horrible)
882         */
883         double cave_amount = 6.0 + 6.0 * noise2d_perlin(
884                         0.5+(double)node_min.X/250, 0.5+(double)node_min.Y/250,
885                         data->seed+34329, 3, 0.50);
886         cave_amount = MYMAX(0.0, cave_amount);
887         u32 caves_count = cave_amount * volume_nodes / 50000;
888         u32 bruises_count = 1;
889         PseudoRandom ps(blockseed+21343);
890         PseudoRandom ps2(blockseed+1032);
891         if(ps.range(1, 6) == 1)
892                 bruises_count = ps.range(0, ps.range(0, 2));
893         if(get_biome(data->seed, v2s16(node_min.X, node_min.Y)) == BT_DESERT){
894                 caves_count /= 3;
895                 bruises_count /= 3;
896         }
897         for(u32 jj=0; jj<caves_count+bruises_count; jj++)
898         {
899                 bool large_cave = (jj >= caves_count);
900                 s16 min_tunnel_diameter = 2;
901                 s16 max_tunnel_diameter = ps.range(2,6);
902                 int dswitchint = ps.range(1,14);
903                 u16 tunnel_routepoints = 0;
904                 int part_max_length_rs = 0;
905                 if(large_cave){
906                         part_max_length_rs = ps.range(2,4);
907                         tunnel_routepoints = ps.range(5, ps.range(15,30));
908                         min_tunnel_diameter = 5;
909                         max_tunnel_diameter = ps.range(7, ps.range(8,24));
910                 } else {
911                         part_max_length_rs = ps.range(2,9);
912                         tunnel_routepoints = ps.range(10, ps.range(15,30));
913                 }
914                 bool large_cave_is_flat = (ps.range(0,1) == 0);
915
916                 v3f main_direction(0,0,0);
917
918                 // Allowed route area size in nodes
919                 v3s16 ar = central_area_size;
920
921                 // Area starting point in nodes
922                 v3s16 of = node_min;
923
924                 // Allow a bit more
925                 //(this should be more than the maximum radius of the tunnel)
926                 //s16 insure = 5; // Didn't work with max_d = 20
927                 s16 insure = 10;
928                 s16 more = max_spread_amount - max_tunnel_diameter/2 - insure;
929                 ar += v3s16(1,0,1) * more * 2;
930                 of -= v3s16(1,0,1) * more;
931
932                 s16 route_y_min = 0;
933                 // Allow half a diameter + 7 over stone surface
934                 s16 route_y_max = -of.Y + stone_surface_max_y + max_tunnel_diameter/2 + 7;
935
936                 /*// If caves, don't go through surface too often
937                 if(large_cave == false)
938                         route_y_max -= ps.range(0, max_tunnel_diameter*2);*/
939
940                 // Limit maximum to area
941                 route_y_max = rangelim(route_y_max, 0, ar.Y-1);
942
943                 if(large_cave)
944                 {
945                         /*// Minimum is at y=0
946                         route_y_min = -of.Y - 0;*/
947                         // Minimum is at y=max_tunnel_diameter/4
948                         //route_y_min = -of.Y + max_tunnel_diameter/4;
949                         //s16 min = -of.Y + max_tunnel_diameter/4;
950                         //s16 min = -of.Y + 0;
951                         s16 min = 0;
952                         if(node_min.Y < WATER_LEVEL && node_max.Y > WATER_LEVEL)
953                         {
954                                 min = WATER_LEVEL - max_tunnel_diameter/3 - of.Y;
955                                 route_y_max = WATER_LEVEL + max_tunnel_diameter/3 - of.Y;
956                         }
957                         route_y_min = ps.range(min, min + max_tunnel_diameter);
958                         route_y_min = rangelim(route_y_min, 0, route_y_max);
959                 }
960
961                 /*dstream<<"route_y_min = "<<route_y_min
962                                 <<", route_y_max = "<<route_y_max<<std::endl;*/
963
964                 s16 route_start_y_min = route_y_min;
965                 s16 route_start_y_max = route_y_max;
966
967                 // Start every 4th cave from surface when applicable
968                 /*bool coming_from_surface = false;
969                 if(node_min.Y <= 0 && node_max.Y >= 0){
970                         coming_from_surface = (jj % 4 == 0 && large_cave == false);
971                         if(coming_from_surface)
972                                 route_start_y_min = -of.Y + stone_surface_max_y + 10;
973                 }*/
974
975                 route_start_y_min = rangelim(route_start_y_min, 0, ar.Y-1);
976                 route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y-1);
977
978                 // Randomize starting position
979                 v3f orp(
980                         (float)(ps.next()%ar.X)+0.5,
981                         (float)(ps.range(route_start_y_min, route_start_y_max))+0.5,
982                         (float)(ps.next()%ar.Z)+0.5
983                 );
984
985                 v3s16 startp(orp.X, orp.Y, orp.Z);
986                 startp += of;
987
988                 MapNode airnode(CONTENT_AIR);
989                 MapNode waternode(c_water_source);
990                 MapNode lavanode(c_lava_source);
991
992                 /*
993                         Generate some tunnel starting from orp
994                 */
995
996                 for(u16 j=0; j<tunnel_routepoints; j++)
997                 {
998                         if(j%dswitchint==0 && large_cave == false)
999                         {
1000                                 main_direction = v3f(
1001                                         ((float)(ps.next()%20)-(float)10)/10,
1002                                         ((float)(ps.next()%20)-(float)10)/30,
1003                                         ((float)(ps.next()%20)-(float)10)/10
1004                                 );
1005                                 main_direction *= (float)ps.range(0, 10)/10;
1006                         }
1007
1008                         // Randomize size
1009                         s16 min_d = min_tunnel_diameter;
1010                         s16 max_d = max_tunnel_diameter;
1011                         s16 rs = ps.range(min_d, max_d);
1012
1013                         // Every second section is rough
1014                         bool randomize_xz = (ps2.range(1,2) == 1);
1015
1016                         v3s16 maxlen;
1017                         if(large_cave)
1018                         {
1019                                 maxlen = v3s16(
1020                                         rs*part_max_length_rs,
1021                                         rs*part_max_length_rs/2,
1022                                         rs*part_max_length_rs
1023                                 );
1024                         }
1025                         else
1026                         {
1027                                 maxlen = v3s16(
1028                                         rs*part_max_length_rs,
1029                                         ps.range(1, rs*part_max_length_rs),
1030                                         rs*part_max_length_rs
1031                                 );
1032                         }
1033
1034                         v3f vec;
1035
1036                         vec = v3f(
1037                                 (float)(ps.next()%(maxlen.X*1))-(float)maxlen.X/2,
1038                                 (float)(ps.next()%(maxlen.Y*1))-(float)maxlen.Y/2,
1039                                 (float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2
1040                         );
1041
1042                         // Jump downward sometimes
1043                         if(!large_cave && ps.range(0,12) == 0)
1044                         {
1045                                 vec = v3f(
1046                                         (float)(ps.next()%(maxlen.X*1))-(float)maxlen.X/2,
1047                                         (float)(ps.next()%(maxlen.Y*2))-(float)maxlen.Y*2/2,
1048                                         (float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2
1049                                 );
1050                         }
1051
1052                         /*if(large_cave){
1053                                 v3f p = orp + vec;
1054                                 s16 h = find_ground_level_clever(vmanip,
1055                                                 v2s16(p.X, p.Z), ndef);
1056                                 route_y_min = h - rs/3;
1057                                 route_y_max = h + rs;
1058                         }*/
1059
1060                         vec += main_direction;
1061
1062                         v3f rp = orp + vec;
1063                         if(rp.X < 0)
1064                                 rp.X = 0;
1065                         else if(rp.X >= ar.X)
1066                                 rp.X = ar.X-1;
1067                         if(rp.Y < route_y_min)
1068                                 rp.Y = route_y_min;
1069                         else if(rp.Y >= route_y_max)
1070                                 rp.Y = route_y_max-1;
1071                         if(rp.Z < 0)
1072                                 rp.Z = 0;
1073                         else if(rp.Z >= ar.Z)
1074                                 rp.Z = ar.Z-1;
1075                         vec = rp - orp;
1076
1077                         for(float f=0; f<1.0; f+=1.0/vec.getLength())
1078                         {
1079                                 v3f fp = orp + vec * f;
1080                                 fp.X += 0.1*ps.range(-10,10);
1081                                 fp.Z += 0.1*ps.range(-10,10);
1082                                 v3s16 cp(fp.X, fp.Y, fp.Z);
1083
1084                                 s16 d0 = -rs/2;
1085                                 s16 d1 = d0 + rs;
1086                                 if(randomize_xz){
1087                                         d0 += ps.range(-1,1);
1088                                         d1 += ps.range(-1,1);
1089                                 }
1090                                 for(s16 z0=d0; z0<=d1; z0++)
1091                                 {
1092                                         s16 si = rs/2 - MYMAX(0, abs(z0)-rs/7-1);
1093                                         for(s16 x0=-si-ps.range(0,1); x0<=si-1+ps.range(0,1); x0++)
1094                                         {
1095                                                 s16 maxabsxz = MYMAX(abs(x0), abs(z0));
1096                                                 s16 si2 = rs/2 - MYMAX(0, maxabsxz-rs/7-1);
1097                                                 for(s16 y0=-si2; y0<=si2; y0++)
1098                                                 {
1099                                                         /*// Make better floors in small caves
1100                                                         if(y0 <= -rs/2 && rs<=7)
1101                                                                 continue;*/
1102                                                         if(large_cave_is_flat){
1103                                                                 // Make large caves not so tall
1104                                                                 if(rs > 7 && abs(y0) >= rs/3)
1105                                                                         continue;
1106                                                         }
1107
1108                                                         s16 z = cp.Z + z0;
1109                                                         s16 y = cp.Y + y0;
1110                                                         s16 x = cp.X + x0;
1111                                                         v3s16 p(x,y,z);
1112                                                         p += of;
1113
1114                                                         if(vmanip.m_area.contains(p) == false)
1115                                                                 continue;
1116
1117                                                         u32 i = vmanip.m_area.index(p);
1118
1119                                                         if(large_cave)
1120                                                         {
1121                                                                 if(full_node_min.Y < WATER_LEVEL &&
1122                                                                         full_node_max.Y > WATER_LEVEL){
1123                                                                         if(p.Y <= WATER_LEVEL)
1124                                                                                 vmanip.m_data[i] = waternode;
1125                                                                         else
1126                                                                                 vmanip.m_data[i] = airnode;
1127                                                                 } else if(full_node_max.Y < WATER_LEVEL){
1128                                                                         if(p.Y < startp.Y - 2)
1129                                                                                 vmanip.m_data[i] = lavanode;
1130                                                                         else
1131                                                                                 vmanip.m_data[i] = airnode;
1132                                                                 } else {
1133                                                                         vmanip.m_data[i] = airnode;
1134                                                                 }
1135                                                         } else {
1136                                                                 // Don't replace air or water or lava or ignore
1137                                                                 if(vmanip.m_data[i].getContent() == CONTENT_IGNORE ||
1138                                                                 vmanip.m_data[i].getContent() == CONTENT_AIR ||
1139                                                                 vmanip.m_data[i].getContent() == c_water_source ||
1140                                                                 vmanip.m_data[i].getContent() == c_lava_source)
1141                                                                         continue;
1142
1143                                                                 vmanip.m_data[i] = airnode;
1144
1145                                                                 // Set tunnel flag
1146                                                                 vmanip.m_flags[i] |= VMANIP_FLAG_CAVE;
1147                                                         }
1148                                                 }
1149                                         }
1150                                 }
1151                         }
1152
1153                         orp = rp;
1154                 }
1155
1156         }
1157
1158         }//timer1
1159 #endif
1160
1161 #if 1
1162         {
1163         // 15ms @cs=8
1164         TimeTaker timer1("add mud");
1165
1166         /*
1167                 Add mud to the central chunk
1168         */
1169
1170         for(s16 x=node_min.X; x<=node_max.X; x++)
1171         for(s16 z=node_min.Z; z<=node_max.Z; z++)
1172         {
1173                 // Node position in 2d
1174                 v2s16 p2d = v2s16(x,z);
1175
1176                 // Randomize mud amount
1177                 s16 mud_add_amount = get_mud_add_amount(data->seed, p2d) / 2.0 + 0.5;
1178
1179                 // Find ground level
1180                 s16 surface_y = find_stone_level(vmanip, p2d, ndef);
1181                 // Handle area not found
1182                 if(surface_y == vmanip.m_area.MinEdge.Y - 1)
1183                         continue;
1184
1185                 MapNode addnode(c_dirt);
1186                 BiomeType bt = get_biome(data->seed, p2d);
1187
1188                 if(bt == BT_DESERT)
1189                         addnode = MapNode(c_desert_sand);
1190
1191                 if(bt == BT_DESERT && surface_y + mud_add_amount <= WATER_LEVEL+1){
1192                         addnode = MapNode(c_sand);
1193                 } else if(mud_add_amount <= 0){
1194                         mud_add_amount = 1 - mud_add_amount;
1195                         addnode = MapNode(c_gravel);
1196                 } else if(bt == BT_NORMAL && get_have_beach(data->seed, p2d) &&
1197                                 surface_y + mud_add_amount <= WATER_LEVEL+2){
1198                         addnode = MapNode(c_sand);
1199                 }
1200
1201                 if(bt == BT_DESERT){
1202                         if(surface_y > 20){
1203                                 mud_add_amount = MYMAX(0, mud_add_amount - (surface_y - 20)/5);
1204                         }
1205                 }
1206
1207                 /*
1208                         If topmost node is grass, change it to mud.
1209                         It might be if it was flown to there from a neighboring
1210                         chunk and then converted.
1211                 */
1212                 {
1213                         u32 i = vmanip.m_area.index(v3s16(p2d.X, surface_y, p2d.Y));
1214                         MapNode *n = &vmanip.m_data[i];
1215                         if(n->getContent() == c_dirt_with_grass)
1216                                 *n = MapNode(c_dirt);
1217                 }
1218
1219                 /*
1220                         Add mud on ground
1221                 */
1222                 {
1223                         s16 mudcount = 0;
1224                         v3s16 em = vmanip.m_area.getExtent();
1225                         s16 y_start = surface_y+1;
1226                         u32 i = vmanip.m_area.index(v3s16(p2d.X, y_start, p2d.Y));
1227                         for(s16 y=y_start; y<=node_max.Y; y++)
1228                         {
1229                                 if(mudcount >= mud_add_amount)
1230                                         break;
1231
1232                                 MapNode &n = vmanip.m_data[i];
1233                                 n = addnode;
1234                                 mudcount++;
1235
1236                                 vmanip.m_area.add_y(em, i, 1);
1237                         }
1238                 }
1239
1240         }
1241
1242         }//timer1
1243 #endif
1244
1245         /*
1246                 Add blobs of dirt and gravel underground
1247         */
1248         if(get_biome(data->seed, v2s16(node_min.X, node_min.Y)) == BT_NORMAL)
1249         {
1250         PseudoRandom pr(blockseed+983);
1251         for(int i=0; i<volume_nodes/10/10/10; i++)
1252         {
1253                 bool only_fill_cave = (myrand_range(0,1) != 0);
1254                 v3s16 size(
1255                         pr.range(1, 8),
1256                         pr.range(1, 8),
1257                         pr.range(1, 8)
1258                 );
1259                 v3s16 p0(
1260                         pr.range(node_min.X, node_max.X)-size.X/2,
1261                         pr.range(node_min.Y, node_max.Y)-size.Y/2,
1262                         pr.range(node_min.Z, node_max.Z)-size.Z/2
1263                 );
1264                 MapNode n1;
1265                 if(p0.Y > -32 && pr.range(0,1) == 0)
1266                         n1 = MapNode(c_dirt);
1267                 else
1268                         n1 = MapNode(c_gravel);
1269                 for(int x1=0; x1<size.X; x1++)
1270                 for(int y1=0; y1<size.Y; y1++)
1271                 for(int z1=0; z1<size.Z; z1++)
1272                 {
1273                         v3s16 p = p0 + v3s16(x1,y1,z1);
1274                         u32 i = vmanip.m_area.index(p);
1275                         if(!vmanip.m_area.contains(i))
1276                                 continue;
1277                         // Cancel if not stone and not cave air
1278                         if(vmanip.m_data[i].getContent() != c_stone &&
1279                                         !(vmanip.m_flags[i] & VMANIP_FLAG_CAVE))
1280                                 continue;
1281                         if(only_fill_cave && !(vmanip.m_flags[i] & VMANIP_FLAG_CAVE))
1282                                 continue;
1283                         vmanip.m_data[i] = n1;
1284                 }
1285         }
1286         }
1287
1288 #if 1
1289         {
1290         // 340ms @cs=8
1291         TimeTaker timer1("flow mud");
1292
1293         /*
1294                 Flow mud away from steep edges
1295         */
1296
1297         // Iterate a few times
1298         for(s16 k=0; k<3; k++)
1299         {
1300
1301         for(s16 x=mudflow_minpos; x<=mudflow_maxpos; x++)
1302         for(s16 z=mudflow_minpos; z<=mudflow_maxpos; z++)
1303         {
1304                 // Invert coordinates every 2nd iteration
1305                 if(k%2 == 0)
1306                 {
1307                         x = mudflow_maxpos - (x-mudflow_minpos);
1308                         z = mudflow_maxpos - (z-mudflow_minpos);
1309                 }
1310
1311                 // Node position in 2d
1312                 v2s16 p2d = v2s16(node_min.X, node_min.Z) + v2s16(x,z);
1313
1314                 v3s16 em = vmanip.m_area.getExtent();
1315                 u32 i = vmanip.m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y));
1316                 s16 y=node_max.Y;
1317
1318                 while(y >= node_min.Y)
1319                 {
1320
1321                 for(;; y--)
1322                 {
1323                         MapNode *n = NULL;
1324                         // Find mud
1325                         for(; y>=node_min.Y; y--)
1326                         {
1327                                 n = &vmanip.m_data[i];
1328                                 //if(content_walkable(n->d))
1329                                 //      break;
1330                                 if(n->getContent() == c_dirt ||
1331                                                 n->getContent() == c_dirt_with_grass ||
1332                                                 n->getContent() == c_gravel)
1333                                         break;
1334
1335                                 vmanip.m_area.add_y(em, i, -1);
1336                         }
1337
1338                         // Stop if out of area
1339                         //if(vmanip.m_area.contains(i) == false)
1340                         if(y < node_min.Y)
1341                                 break;
1342
1343                         /*// If not mud, do nothing to it
1344                         MapNode *n = &vmanip.m_data[i];
1345                         if(n->d != CONTENT_MUD && n->d != CONTENT_GRASS)
1346                                 continue;*/
1347
1348                         if(n->getContent() == c_dirt ||
1349                                         n->getContent() == c_dirt_with_grass)
1350                         {
1351                                 // Make it exactly mud
1352                                 n->setContent(c_dirt);
1353
1354                                 /*
1355                                         Don't flow it if the stuff under it is not mud
1356                                 */
1357                                 {
1358                                         u32 i2 = i;
1359                                         vmanip.m_area.add_y(em, i2, -1);
1360                                         // Cancel if out of area
1361                                         if(vmanip.m_area.contains(i2) == false)
1362                                                 continue;
1363                                         MapNode *n2 = &vmanip.m_data[i2];
1364                                         if(n2->getContent() != c_dirt &&
1365                                                         n2->getContent() != c_dirt_with_grass)
1366                                                 continue;
1367                                 }
1368                         }
1369
1370                         /*s16 recurse_count = 0;
1371         mudflow_recurse:*/
1372
1373                         v3s16 dirs4[4] = {
1374                                 v3s16(0,0,1), // back
1375                                 v3s16(1,0,0), // right
1376                                 v3s16(0,0,-1), // front
1377                                 v3s16(-1,0,0), // left
1378                         };
1379
1380                         // Theck that upper is air or doesn't exist.
1381                         // Cancel dropping if upper keeps it in place
1382                         u32 i3 = i;
1383                         vmanip.m_area.add_y(em, i3, 1);
1384                         if(vmanip.m_area.contains(i3) == true
1385                                         && ndef->get(vmanip.m_data[i3]).walkable)
1386                         {
1387                                 continue;
1388                         }
1389
1390                         // Drop mud on side
1391
1392                         for(u32 di=0; di<4; di++)
1393                         {
1394                                 v3s16 dirp = dirs4[di];
1395                                 u32 i2 = i;
1396                                 // Move to side
1397                                 vmanip.m_area.add_p(em, i2, dirp);
1398                                 // Fail if out of area
1399                                 if(vmanip.m_area.contains(i2) == false)
1400                                         continue;
1401                                 // Check that side is air
1402                                 MapNode *n2 = &vmanip.m_data[i2];
1403                                 if(ndef->get(*n2).walkable)
1404                                         continue;
1405                                 // Check that under side is air
1406                                 vmanip.m_area.add_y(em, i2, -1);
1407                                 if(vmanip.m_area.contains(i2) == false)
1408                                         continue;
1409                                 n2 = &vmanip.m_data[i2];
1410                                 if(ndef->get(*n2).walkable)
1411                                         continue;
1412                                 /*// Check that under that is air (need a drop of 2)
1413                                 vmanip.m_area.add_y(em, i2, -1);
1414                                 if(vmanip.m_area.contains(i2) == false)
1415                                         continue;
1416                                 n2 = &vmanip.m_data[i2];
1417                                 if(content_walkable(n2->d))
1418                                         continue;*/
1419                                 // Loop further down until not air
1420                                 bool dropped_to_unknown = false;
1421                                 do{
1422                                         vmanip.m_area.add_y(em, i2, -1);
1423                                         n2 = &vmanip.m_data[i2];
1424                                         // if out of known area
1425                                         if(vmanip.m_area.contains(i2) == false
1426                                                         || n2->getContent() == CONTENT_IGNORE){
1427                                                 dropped_to_unknown = true;
1428                                                 break;
1429                                         }
1430                                 }while(ndef->get(*n2).walkable == false);
1431                                 // Loop one up so that we're in air
1432                                 vmanip.m_area.add_y(em, i2, 1);
1433                                 n2 = &vmanip.m_data[i2];
1434
1435                                 bool old_is_water = (n->getContent() == c_water_source);
1436                                 // Move mud to new place
1437                                 if(!dropped_to_unknown) {
1438                                         *n2 = *n;
1439                                         // Set old place to be air (or water)
1440                                         if(old_is_water)
1441                                                 *n = MapNode(c_water_source);
1442                                         else
1443                                                 *n = MapNode(CONTENT_AIR);
1444                                 }
1445
1446                                 // Done
1447                                 break;
1448                         }
1449                 }
1450                 }
1451         }
1452
1453         }
1454
1455         }//timer1
1456 #endif
1457
1458         } // Aging loop
1459         /***********************
1460                 END OF AGING LOOP
1461         ************************/
1462
1463         /*
1464                 Add top and bottom side of water to transforming_liquid queue
1465         */
1466
1467         for(s16 x=full_node_min.X; x<=full_node_max.X; x++)
1468         for(s16 z=full_node_min.Z; z<=full_node_max.Z; z++)
1469         {
1470                 // Node position
1471                 v2s16 p2d(x,z);
1472                 {
1473                         bool water_found = false;
1474                         // Use fast index incrementing
1475                         v3s16 em = vmanip.m_area.getExtent();
1476                         u32 i = vmanip.m_area.index(v3s16(p2d.X, full_node_max.Y, p2d.Y));
1477                         for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--)
1478                         {
1479                                 if(y == full_node_max.Y){
1480                                         water_found =
1481                                                 (vmanip.m_data[i].getContent() == c_water_source ||
1482                                                 vmanip.m_data[i].getContent() == c_lava_source);
1483                                 }
1484                                 else if(water_found == false)
1485                                 {
1486                                         if(vmanip.m_data[i].getContent() == c_water_source ||
1487                                                         vmanip.m_data[i].getContent() == c_lava_source)
1488                                         {
1489                                                 v3s16 p = v3s16(p2d.X, y, p2d.Y);
1490                                                 data->transforming_liquid.push_back(p);
1491                                                 water_found = true;
1492                                         }
1493                                 }
1494                                 else
1495                                 {
1496                                         // This can be done because water_found can only
1497                                         // turn to true and end up here after going through
1498                                         // a single block.
1499                                         if(vmanip.m_data[i+1].getContent() != c_water_source ||
1500                                                         vmanip.m_data[i+1].getContent() != c_lava_source)
1501                                         {
1502                                                 v3s16 p = v3s16(p2d.X, y+1, p2d.Y);
1503                                                 data->transforming_liquid.push_back(p);
1504                                                 water_found = false;
1505                                         }
1506                                 }
1507
1508                                 vmanip.m_area.add_y(em, i, -1);
1509                         }
1510                 }
1511         }
1512
1513         /*
1514                 Grow grass
1515         */
1516
1517         for(s16 x=full_node_min.X; x<=full_node_max.X; x++)
1518         for(s16 z=full_node_min.Z; z<=full_node_max.Z; z++)
1519         {
1520                 // Node position in 2d
1521                 v2s16 p2d = v2s16(x,z);
1522
1523                 /*
1524                         Find the lowest surface to which enough light ends up
1525                         to make grass grow.
1526
1527                         Basically just wait until not air and not leaves.
1528                 */
1529                 s16 surface_y = 0;
1530                 {
1531                         v3s16 em = vmanip.m_area.getExtent();
1532                         u32 i = vmanip.m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y));
1533                         s16 y;
1534                         // Go to ground level
1535                         for(y=node_max.Y; y>=full_node_min.Y; y--)
1536                         {
1537                                 MapNode &n = vmanip.m_data[i];
1538                                 if(ndef->get(n).param_type != CPT_LIGHT
1539                                                 || ndef->get(n).liquid_type != LIQUID_NONE)
1540                                         break;
1541                                 vmanip.m_area.add_y(em, i, -1);
1542                         }
1543                         if(y >= full_node_min.Y)
1544                                 surface_y = y;
1545                         else
1546                                 surface_y = full_node_min.Y;
1547                 }
1548
1549                 u32 i = vmanip.m_area.index(p2d.X, surface_y, p2d.Y);
1550                 MapNode *n = &vmanip.m_data[i];
1551                 if(n->getContent() == c_dirt){
1552                         // Well yeah, this can't be overground...
1553                         if(surface_y < WATER_LEVEL - 20)
1554                                 continue;
1555                         n->setContent(c_dirt_with_grass);
1556                 }
1557         }
1558
1559         /*
1560                 Generate some trees
1561         */
1562         assert(central_area_size.X == central_area_size.Z);
1563         {
1564                 PseudoRandom ps (blockseed);
1565                 // Divide area into parts
1566                 s16 div = 8;
1567                 s16 sidelen = central_area_size.X / div;
1568                 double area = sidelen * sidelen;
1569                 for(s16 x0=0; x0<div; x0++)
1570                 for(s16 z0=0; z0<div; z0++)
1571                 {
1572                         // Center position of part of division
1573                         v2s16 p2d_center(
1574                                 node_min.X + sidelen/2 + sidelen*x0,
1575                                 node_min.Z + sidelen/2 + sidelen*z0
1576                         );
1577                         // Minimum edge of part of division
1578                         v2s16 p2d_min(
1579                                 node_min.X + sidelen*x0,
1580                                 node_min.Z + sidelen*z0
1581                         );
1582                         // Maximum edge of part of division
1583                         v2s16 p2d_max(
1584                                 node_min.X + sidelen + sidelen*x0 - 1,
1585                                 node_min.Z + sidelen + sidelen*z0 - 1
1586                         );
1587                         // Amount of trees
1588                         u32 tree_count = area * tree_amount_2d(data->seed, p2d_center);
1589                         // Put trees in random places on part of division
1590                         for(u32 i=0; i<tree_count; i++)
1591                         {
1592                                 s16 x = ps.range(p2d_min.X, p2d_max.X);
1593                                 s16 z = ps.range(p2d_min.Y, p2d_max.Y);
1594                                 s16 y = find_ground_level(vmanip, v2s16(x,z), ndef);
1595                                 // Don't make a tree under water level
1596                                 if(y < WATER_LEVEL)
1597                                         continue;
1598                                 // Don't make a tree so high that it doesn't fit
1599                                 if(y > node_max.Y - 6)
1600                                         continue;
1601                                 v3s16 p(x,y,z);
1602                                 /*
1603                                         Trees grow only on mud and grass
1604                                 */
1605                                 {
1606                                         u32 i = vmanip.m_area.index(v3s16(p));
1607                                         MapNode *n = &vmanip.m_data[i];
1608                                         if(n->getContent() != c_dirt
1609                                                         && n->getContent() != c_dirt_with_grass)
1610                                                 continue;
1611                                 }
1612                                 p.Y++;
1613                                 // Make a tree
1614                                 treegen::make_tree(vmanip, p, false, ndef, ps.next());
1615                         }
1616                 }
1617         }
1618
1619 #if 0
1620         /*
1621                 Make base ground level
1622         */
1623
1624         for(s16 x=node_min.X; x<=node_max.X; x++)
1625         for(s16 z=node_min.Z; z<=node_max.Z; z++)
1626         {
1627                 // Node position
1628                 v2s16 p2d(x,z);
1629                 {
1630                         // Use fast index incrementing
1631                         v3s16 em = vmanip.m_area.getExtent();
1632                         u32 i = vmanip.m_area.index(v3s16(p2d.X, node_min.Y, p2d.Y));
1633                         for(s16 y=node_min.Y; y<=node_max.Y; y++)
1634                         {
1635                                 // Only modify places that have no content
1636                                 if(vmanip.m_data[i].getContent() == CONTENT_IGNORE)
1637                                 {
1638                                         // First priority: make air and water.
1639                                         // This avoids caves inside water.
1640                                         if(all_is_ground_except_caves == false
1641                                                         && val_is_ground(noisebuf_ground.get(x,y,z),
1642                                                         v3s16(x,y,z), data->seed) == false)
1643                                         {
1644                                                 if(y <= WATER_LEVEL)
1645                                                         vmanip.m_data[i] = n_water_source;
1646                                                 else
1647                                                         vmanip.m_data[i] = n_air;
1648                                         }
1649                                         else if(noisebuf_cave.get(x,y,z) > CAVE_NOISE_THRESHOLD)
1650                                                 vmanip.m_data[i] = n_air;
1651                                         else
1652                                                 vmanip.m_data[i] = n_stone;
1653                                 }
1654
1655                                 vmanip->m_area.add_y(em, i, 1);
1656                         }
1657                 }
1658         }
1659
1660         /*
1661                 Add mud and sand and others underground (in place of stone)
1662         */
1663
1664         for(s16 x=node_min.X; x<=node_max.X; x++)
1665         for(s16 z=node_min.Z; z<=node_max.Z; z++)
1666         {
1667                 // Node position
1668                 v2s16 p2d(x,z);
1669                 {
1670                         // Use fast index incrementing
1671                         v3s16 em = vmanip.m_area.getExtent();
1672                         u32 i = vmanip.m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y));
1673                         for(s16 y=node_max.Y; y>=node_min.Y; y--)
1674                         {
1675                                 if(vmanip.m_data[i].getContent() == c_stone)
1676                                 {
1677                                         if(noisebuf_ground_crumbleness.get(x,y,z) > 1.3)
1678                                         {
1679                                                 if(noisebuf_ground_wetness.get(x,y,z) > 0.0)
1680                                                         vmanip.m_data[i] = n_dirt;
1681                                                 else
1682                                                         vmanip.m_data[i] = n_sand;
1683                                         }
1684                                         else if(noisebuf_ground_crumbleness.get(x,y,z) > 0.7)
1685                                         {
1686                                                 if(noisebuf_ground_wetness.get(x,y,z) < -0.6)
1687                                                         vmanip.m_data[i] = n_gravel;
1688                                         }
1689                                         else if(noisebuf_ground_crumbleness.get(x,y,z) <
1690                                                         -3.0 + MYMIN(0.1 * sqrt((float)MYMAX(0, -y)), 1.5))
1691                                         {
1692                                                 vmanip.m_data[i] = n_lava_source;
1693                                                 for(s16 x1=-1; x1<=1; x1++)
1694                                                 for(s16 y1=-1; y1<=1; y1++)
1695                                                 for(s16 z1=-1; z1<=1; z1++)
1696                                                         data->transforming_liquid.push_back(
1697                                                                         v3s16(p2d.X+x1, y+y1, p2d.Y+z1));
1698                                         }
1699                                 }
1700
1701                                 vmanip->m_area.add_y(em, i, -1);
1702                         }
1703                 }
1704         }
1705
1706         /*
1707                 Add dungeons
1708         */
1709
1710         //if(node_min.Y < approx_groundlevel)
1711         //if(myrand() % 3 == 0)
1712         //if(myrand() % 3 == 0 && node_min.Y < approx_groundlevel)
1713         //if(myrand() % 100 == 0 && node_min.Y < approx_groundlevel)
1714         //float dungeon_rarity = g_settings.getFloat("dungeon_rarity");
1715         float dungeon_rarity = 0.02;
1716         if(((noise3d(blockpos.X,blockpos.Y,blockpos.Z,data->seed)+1.0)/2.0)
1717                         < dungeon_rarity
1718                         && node_min.Y < approx_groundlevel)
1719         {
1720                 // Dungeon generator doesn't modify places which have this set
1721                 vmanip->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE
1722                                 | VMANIP_FLAG_DUNGEON_PRESERVE);
1723
1724                 // Set all air and water to be untouchable to make dungeons open
1725                 // to caves and open air
1726                 for(s16 x=full_node_min.X; x<=full_node_max.X; x++)
1727                 for(s16 z=full_node_min.Z; z<=full_node_max.Z; z++)
1728                 {
1729                         // Node position
1730                         v2s16 p2d(x,z);
1731                         {
1732                                 // Use fast index incrementing
1733                                 v3s16 em = vmanip.m_area.getExtent();
1734                                 u32 i = vmanip.m_area.index(v3s16(p2d.X, full_node_max.Y, p2d.Y));
1735                                 for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--)
1736                                 {
1737                                         if(vmanip.m_data[i].getContent() == CONTENT_AIR)
1738                                                 vmanip.m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
1739                                         else if(vmanip.m_data[i].getContent() == c_water_source)
1740                                                 vmanip.m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
1741                                         vmanip->m_area.add_y(em, i, -1);
1742                                 }
1743                         }
1744                 }
1745
1746                 PseudoRandom random(blockseed+2);
1747
1748                 // Add it
1749                 make_dungeon1(vmanip, random, ndef);
1750
1751                 // Convert some cobble to mossy cobble
1752                 for(s16 x=full_node_min.X; x<=full_node_max.X; x++)
1753                 for(s16 z=full_node_min.Z; z<=full_node_max.Z; z++)
1754                 {
1755                         // Node position
1756                         v2s16 p2d(x,z);
1757                         {
1758                                 // Use fast index incrementing
1759                                 v3s16 em = vmanip.m_area.getExtent();
1760                                 u32 i = vmanip.m_area.index(v3s16(p2d.X, full_node_max.Y, p2d.Y));
1761                                 for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--)
1762                                 {
1763                                         // (noisebuf not used because it doesn't contain the
1764                                         //  full area)
1765                                         double wetness = noise3d_param(
1766                                                         get_ground_wetness_params(data->seed), x,y,z);
1767                                         double d = noise3d_perlin((float)x/2.5,
1768                                                         (float)y/2.5,(float)z/2.5,
1769                                                         blockseed, 2, 1.4);
1770                                         if(vmanip.m_data[i].getContent() == c_cobble)
1771                                         {
1772                                                 if(d < wetness/3.0)
1773                                                 {
1774                                                         vmanip.m_data[i].setContent(c_mossycobble);
1775                                                 }
1776                                         }
1777                                         /*else if(vmanip.m_flags[i] & VMANIP_FLAG_DUNGEON_INSIDE)
1778                                         {
1779                                                 if(wetness > 1.2)
1780                                                         vmanip.m_data[i].setContent(c_dirt);
1781                                         }*/
1782                                         vmanip->m_area.add_y(em, i, -1);
1783                                 }
1784                         }
1785                 }
1786         }
1787
1788         /*
1789                 Add NC
1790         */
1791         {
1792                 PseudoRandom ncrandom(blockseed+9324342);
1793                 if(ncrandom.range(0, 1000) == 0 && blockpos.Y <= -3)
1794                 {
1795                         make_nc(vmanip, ncrandom, ndef);
1796                 }
1797         }
1798
1799         /*
1800                 Add top and bottom side of water to transforming_liquid queue
1801         */
1802
1803         for(s16 x=node_min.X; x<=node_max.X; x++)
1804         for(s16 z=node_min.Z; z<=node_max.Z; z++)
1805         {
1806                 // Node position
1807                 v2s16 p2d(x,z);
1808                 {
1809                         bool water_found = false;
1810                         // Use fast index incrementing
1811                         v3s16 em = vmanip.m_area.getExtent();
1812                         u32 i = vmanip.m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y));
1813                         for(s16 y=node_max.Y; y>=node_min.Y; y--)
1814                         {
1815                                 if(water_found == false)
1816                                 {
1817                                         if(vmanip.m_data[i].getContent() == c_water_source)
1818                                         {
1819                                                 v3s16 p = v3s16(p2d.X, y, p2d.Y);
1820                                                 data->transforming_liquid.push_back(p);
1821                                                 water_found = true;
1822                                         }
1823                                 }
1824                                 else
1825                                 {
1826                                         // This can be done because water_found can only
1827                                         // turn to true and end up here after going through
1828                                         // a single block.
1829                                         if(vmanip.m_data[i+1].getContent() != c_water_source)
1830                                         {
1831                                                 v3s16 p = v3s16(p2d.X, y+1, p2d.Y);
1832                                                 data->transforming_liquid.push_back(p);
1833                                                 water_found = false;
1834                                         }
1835                                 }
1836
1837                                 vmanip->m_area.add_y(em, i, -1);
1838                         }
1839                 }
1840         }
1841
1842         /*
1843                 If close to ground level
1844         */
1845
1846         //if(abs(approx_ground_depth) < 30)
1847         if(minimum_ground_depth < 5 && maximum_ground_depth > -5)
1848         {
1849                 /*
1850                         Add grass and mud
1851                 */
1852
1853                 for(s16 x=node_min.X; x<=node_max.X; x++)
1854                 for(s16 z=node_min.Z; z<=node_max.Z; z++)
1855                 {
1856                         // Node position
1857                         v2s16 p2d(x,z);
1858                         {
1859                                 bool possibly_have_sand = get_have_beach(data->seed, p2d);
1860                                 bool have_sand = false;
1861                                 u32 current_depth = 0;
1862                                 bool air_detected = false;
1863                                 bool water_detected = false;
1864                                 bool have_clay = false;
1865
1866                                 // Use fast index incrementing
1867                                 s16 start_y = node_max.Y+2;
1868                                 v3s16 em = vmanip.m_area.getExtent();
1869                                 u32 i = vmanip.m_area.index(v3s16(p2d.X, start_y, p2d.Y));
1870                                 for(s16 y=start_y; y>=node_min.Y-3; y--)
1871                                 {
1872                                         if(vmanip.m_data[i].getContent() == c_water_source)
1873                                                 water_detected = true;
1874                                         if(vmanip.m_data[i].getContent() == CONTENT_AIR)
1875                                                 air_detected = true;
1876
1877                                         if((vmanip.m_data[i].getContent() == c_stone
1878                                                         || vmanip.m_data[i].getContent() == c_dirt_with_grass
1879                                                         || vmanip.m_data[i].getContent() == c_dirt
1880                                                         || vmanip.m_data[i].getContent() == c_sand
1881                                                         || vmanip.m_data[i].getContent() == c_gravel
1882                                                         ) && (air_detected || water_detected))
1883                                         {
1884                                                 if(current_depth == 0 && y <= WATER_LEVEL+2
1885                                                                 && possibly_have_sand)
1886                                                         have_sand = true;
1887
1888                                                 if(current_depth < 4)
1889                                                 {
1890                                                         if(have_sand)
1891                                                         {
1892                                                                 vmanip.m_data[i] = MapNode(c_sand);
1893                                                         }
1894                                                         #if 1
1895                                                         else if(current_depth==0 && !water_detected
1896                                                                         && y >= WATER_LEVEL && air_detected)
1897                                                                 vmanip.m_data[i] = MapNode(c_dirt_with_grass);
1898                                                         #endif
1899                                                         else
1900                                                                 vmanip.m_data[i] = MapNode(c_dirt);
1901                                                 }
1902                                                 else
1903                                                 {
1904                                                         if(vmanip.m_data[i].getContent() == c_dirt
1905                                                                 || vmanip.m_data[i].getContent() == c_dirt_with_grass)
1906                                                                 vmanip.m_data[i] = MapNode(c_stone);
1907                                                 }
1908
1909                                                 current_depth++;
1910
1911                                                 if(current_depth >= 8)
1912                                                         break;
1913                                         }
1914                                         else if(current_depth != 0)
1915                                                 break;
1916
1917                                         vmanip->m_area.add_y(em, i, -1);
1918                                 }
1919                         }
1920                 }
1921
1922                 /*
1923                         Calculate some stuff
1924                 */
1925
1926                 float surface_humidity = surface_humidity_2d(data->seed, p2d_center);
1927                 bool is_jungle = surface_humidity > 0.75;
1928                 // Amount of trees
1929                 u32 tree_count = gen_area_nodes * tree_amount_2d(data->seed, p2d_center);
1930                 if(is_jungle)
1931                         tree_count *= 5;
1932
1933                 /*
1934                         Add trees
1935                 */
1936                 PseudoRandom treerandom(blockseed);
1937                 // Put trees in random places on part of division
1938                 for(u32 i=0; i<tree_count; i++)
1939                 {
1940                         s16 x = treerandom.range(node_min.X, node_max.X);
1941                         s16 z = treerandom.range(node_min.Z, node_max.Z);
1942                         //s16 y = find_ground_level(vmanip, v2s16(x,z));
1943                         s16 y = find_ground_level_from_noise(data->seed, v2s16(x,z), 4);
1944                         // Don't make a tree under water level
1945                         if(y < WATER_LEVEL)
1946                                 continue;
1947                         // Make sure tree fits (only trees whose starting point is
1948                         // at this block are added)
1949                         if(y < node_min.Y || y > node_max.Y)
1950                                 continue;
1951                         /*
1952                                 Find exact ground level
1953                         */
1954                         v3s16 p(x,y+6,z);
1955                         bool found = false;
1956                         for(; p.Y >= y-6; p.Y--)
1957                         {
1958                                 u32 i = vmanip->m_area.index(p);
1959                                 MapNode *n = &vmanip->m_data[i];
1960                                 if(n->getContent() != CONTENT_AIR && n->getContent() != c_water_source && n->getContent() != CONTENT_IGNORE)
1961                                 {
1962                                         found = true;
1963                                         break;
1964                                 }
1965                         }
1966                         // If not found, handle next one
1967                         if(found == false)
1968                                 continue;
1969
1970                         {
1971                                 u32 i = vmanip->m_area.index(p);
1972                                 MapNode *n = &vmanip->m_data[i];
1973
1974                                 if(n->getContent() != c_dirt && n->getContent() != c_dirt_with_grass && n->getContent() != c_sand)
1975                                                 continue;
1976
1977                                 // Papyrus grows only on mud and in water
1978                                 if(n->getContent() == c_dirt && y <= WATER_LEVEL)
1979                                 {
1980                                         p.Y++;
1981                                         make_papyrus(vmanip, p, ndef);
1982                                 }
1983                                 // Trees grow only on mud and grass, on land
1984                                 else if((n->getContent() == c_dirt || n->getContent() == c_dirt_with_grass) && y > WATER_LEVEL + 2)
1985                                 {
1986                                         p.Y++;
1987                                         //if(surface_humidity_2d(data->seed, v2s16(x, y)) < 0.5)
1988                                         if(is_jungle == false)
1989                                         {
1990                                                 bool is_apple_tree;
1991                                                 if(myrand_range(0,4) != 0)
1992                                                         is_apple_tree = false;
1993                                                 else
1994                                                         is_apple_tree = noise2d_perlin(
1995                                                                         0.5+(float)p.X/100, 0.5+(float)p.Z/100,
1996                                                                         data->seed+342902, 3, 0.45) > 0.2;
1997                                                 make_tree(vmanip, p, is_apple_tree, ndef);
1998                                         }
1999                                         else
2000                                                 make_jungletree(vmanip, p, ndef);
2001                                 }
2002                                 // Cactii grow only on sand, on land
2003                                 else if(n->getContent() == c_sand && y > WATER_LEVEL + 2)
2004                                 {
2005                                         p.Y++;
2006                                         make_cactus(vmanip, p, ndef);
2007                                 }
2008                         }
2009                 }
2010
2011                 /*
2012                         Add jungle grass
2013                 */
2014                 if(is_jungle)
2015                 {
2016                         PseudoRandom grassrandom(blockseed);
2017                         for(u32 i=0; i<surface_humidity*5*tree_count; i++)
2018                         {
2019                                 s16 x = grassrandom.range(node_min.X, node_max.X);
2020                                 s16 z = grassrandom.range(node_min.Z, node_max.Z);
2021                                 s16 y = find_ground_level_from_noise(data->seed, v2s16(x,z), 4);
2022                                 if(y < WATER_LEVEL)
2023                                         continue;
2024                                 if(y < node_min.Y || y > node_max.Y)
2025                                         continue;
2026                                 /*
2027                                         Find exact ground level
2028                                 */
2029                                 v3s16 p(x,y+6,z);
2030                                 bool found = false;
2031                                 for(; p.Y >= y-6; p.Y--)
2032                                 {
2033                                         u32 i = vmanip->m_area.index(p);
2034                                         MapNode *n = &vmanip->m_data[i];
2035                                         if(data->nodedef->get(*n).is_ground_content)
2036                                         {
2037                                                 found = true;
2038                                                 break;
2039                                         }
2040                                 }
2041                                 // If not found, handle next one
2042                                 if(found == false)
2043                                         continue;
2044                                 p.Y++;
2045                                 if(vmanip.m_area.contains(p) == false)
2046                                         continue;
2047                                 if(vmanip.m_data[vmanip.m_area.index(p)].getContent() != CONTENT_AIR)
2048                                         continue;
2049                                 /*p.Y--;
2050                                 if(vmanip.m_area.contains(p))
2051                                         vmanip.m_data[vmanip.m_area.index(p)] = c_dirt;
2052                                 p.Y++;*/
2053                                 if(vmanip.m_area.contains(p))
2054                                         vmanip.m_data[vmanip.m_area.index(p)] = c_junglegrass;
2055                         }
2056                 }
2057
2058 #if 0
2059                 /*
2060                         Add some kind of random stones
2061                 */
2062
2063                 u32 random_stone_count = gen_area_nodes *
2064                                 randomstone_amount_2d(data->seed, p2d_center);
2065                 // Put in random places on part of division
2066                 for(u32 i=0; i<random_stone_count; i++)
2067                 {
2068                         s16 x = myrand_range(node_min.X, node_max.X);
2069                         s16 z = myrand_range(node_min.Z, node_max.Z);
2070                         s16 y = find_ground_level_from_noise(data->seed, v2s16(x,z), 1);
2071                         // Don't add under water level
2072                         /*if(y < WATER_LEVEL)
2073                                 continue;*/
2074                         // Don't add if doesn't belong to this block
2075                         if(y < node_min.Y || y > node_max.Y)
2076                                 continue;
2077                         v3s16 p(x,y,z);
2078                         // Filter placement
2079                         /*{
2080                                 u32 i = vmanip->m_area.index(v3s16(p));
2081                                 MapNode *n = &vmanip->m_data[i];
2082                                 if(n->getContent() != c_dirt && n->getContent() != c_dirt_with_grass)
2083                                         continue;
2084                         }*/
2085                         // Will be placed one higher
2086                         p.Y++;
2087                         // Add it
2088                         make_randomstone(vmanip, p);
2089                 }
2090 #endif
2091
2092 #if 0
2093                 /*
2094                         Add larger stones
2095                 */
2096
2097                 u32 large_stone_count = gen_area_nodes *
2098                                 largestone_amount_2d(data->seed, p2d_center);
2099                 //u32 large_stone_count = 1;
2100                 // Put in random places on part of division
2101                 for(u32 i=0; i<large_stone_count; i++)
2102                 {
2103                         s16 x = myrand_range(node_min.X, node_max.X);
2104                         s16 z = myrand_range(node_min.Z, node_max.Z);
2105                         s16 y = find_ground_level_from_noise(data->seed, v2s16(x,z), 1);
2106                         // Don't add under water level
2107                         /*if(y < WATER_LEVEL)
2108                                 continue;*/
2109                         // Don't add if doesn't belong to this block
2110                         if(y < node_min.Y || y > node_max.Y)
2111                                 continue;
2112                         v3s16 p(x,y,z);
2113                         // Filter placement
2114                         /*{
2115                                 u32 i = vmanip->m_area.index(v3s16(p));
2116                                 MapNode *n = &vmanip->m_data[i];
2117                                 if(n->getContent() != c_dirt && n->getContent() != c_dirt_with_grass)
2118                                         continue;
2119                         }*/
2120                         // Will be placed one lower
2121                         p.Y--;
2122                         // Add it
2123                         make_largestone(vmanip, p);
2124                 }
2125 #endif
2126         }
2127
2128         /*
2129                 Add minerals
2130         */
2131
2132         {
2133                 PseudoRandom mineralrandom(blockseed);
2134
2135                 /*
2136                         Add meseblocks
2137                 */
2138                 for(s16 i=0; i<approx_ground_depth/4; i++)
2139                 {
2140                         if(mineralrandom.next()%50 == 0)
2141                         {
2142                                 s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
2143                                 s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
2144                                 s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
2145                                 for(u16 i=0; i<27; i++)
2146                                 {
2147                                         v3s16 p = v3s16(x,y,z) + g_27dirs[i];
2148                                         u32 vi = vmanip.m_area.index(p);
2149                                         if(vmanip.m_data[vi].getContent() == c_stone)
2150                                                 if(mineralrandom.next()%8 == 0)
2151                                                         vmanip.m_data[vi] = MapNode(c_mese);
2152                                 }
2153
2154                         }
2155                 }
2156                 /*
2157                         Add others
2158                 */
2159                 {
2160                         u16 a = mineralrandom.range(0,15);
2161                         a = a*a*a;
2162                         u16 amount = 20 * a/1000;
2163                         for(s16 i=0; i<amount; i++)
2164                         {
2165                                 s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
2166                                 s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
2167                                 s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
2168
2169                                 u8 base_content = c_stone;
2170                                 MapNode new_content(CONTENT_IGNORE);
2171                                 u32 sparseness = 6;
2172
2173                                 if(noisebuf_ground_crumbleness.get(x,y+5,z) < -0.1)
2174                                 {
2175                                         new_content = MapNode(c_stone_with_coal);
2176                                 }
2177                                 else
2178                                 {
2179                                         if(noisebuf_ground_wetness.get(x,y+5,z) > 0.0)
2180                                                 new_content = MapNode(c_stone_with_iron);
2181                                         /*if(noisebuf_ground_wetness.get(x,y,z) > 0.0)
2182                                                 vmanip.m_data[i] = MapNode(c_dirt);
2183                                         else
2184                                                 vmanip.m_data[i] = MapNode(c_sand);*/
2185                                 }
2186                                 /*else if(noisebuf_ground_crumbleness.get(x,y,z) > 0.1)
2187                                 {
2188                                 }*/
2189
2190                                 if(new_content.getContent() != CONTENT_IGNORE)
2191                                 {
2192                                         for(u16 i=0; i<27; i++)
2193                                         {
2194                                                 v3s16 p = v3s16(x,y,z) + g_27dirs[i];
2195                                                 u32 vi = vmanip.m_area.index(p);
2196                                                 if(vmanip.m_data[vi].getContent() == base_content)
2197                                                 {
2198                                                         if(mineralrandom.next()%sparseness == 0)
2199                                                                 vmanip.m_data[vi] = new_content;
2200                                                 }
2201                                         }
2202                                 }
2203                         }
2204                 }
2205                 /*
2206                         Add coal
2207                 */
2208                 //for(s16 i=0; i < MYMAX(0, 50 - abs(node_min.Y+8 - (-30))); i++)
2209                 //for(s16 i=0; i<50; i++)
2210                 u16 coal_amount = 30;
2211                 u16 coal_rareness = 60 / coal_amount;
2212                 if(coal_rareness == 0)
2213                         coal_rareness = 1;
2214                 if(mineralrandom.next()%coal_rareness == 0)
2215                 {
2216                         u16 a = mineralrandom.next() % 16;
2217                         u16 amount = coal_amount * a*a*a / 1000;
2218                         for(s16 i=0; i<amount; i++)
2219                         {
2220                                 s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
2221                                 s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
2222                                 s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
2223                                 for(u16 i=0; i<27; i++)
2224                                 {
2225                                         v3s16 p = v3s16(x,y,z) + g_27dirs[i];
2226                                         u32 vi = vmanip.m_area.index(p);
2227                                         if(vmanip.m_data[vi].getContent() == c_stone)
2228                                                 if(mineralrandom.next()%8 == 0)
2229                                                         vmanip.m_data[vi] = MapNode(c_stone_with_coal);
2230                                 }
2231                         }
2232                 }
2233                 /*
2234                         Add iron
2235                 */
2236                 u16 iron_amount = 8;
2237                 u16 iron_rareness = 60 / iron_amount;
2238                 if(iron_rareness == 0)
2239                         iron_rareness = 1;
2240                 if(mineralrandom.next()%iron_rareness == 0)
2241                 {
2242                         u16 a = mineralrandom.next() % 16;
2243                         u16 amount = iron_amount * a*a*a / 1000;
2244                         for(s16 i=0; i<amount; i++)
2245                         {
2246                                 s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
2247                                 s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
2248                                 s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
2249                                 for(u16 i=0; i<27; i++)
2250                                 {
2251                                         v3s16 p = v3s16(x,y,z) + g_27dirs[i];
2252                                         u32 vi = vmanip.m_area.index(p);
2253                                         if(vmanip.m_data[vi].getContent() == c_stone)
2254                                                 if(mineralrandom.next()%8 == 0)
2255                                                         vmanip.m_data[vi] = MapNode(c_stone_with_iron);
2256                                 }
2257                         }
2258                 }
2259         }
2260 #endif
2261
2262         /*
2263                 Calculate lighting
2264         */
2265         {
2266         ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update",
2267                         SPT_AVG);
2268         //VoxelArea a(node_min, node_max);
2269         VoxelArea a(node_min-v3s16(1,0,1)*MAP_BLOCKSIZE,
2270                         node_max+v3s16(1,0,1)*MAP_BLOCKSIZE);
2271         /*VoxelArea a(node_min-v3s16(1,0,1)*MAP_BLOCKSIZE/2,
2272                         node_max+v3s16(1,0,1)*MAP_BLOCKSIZE/2);*/
2273         enum LightBank banks[2] = {LIGHTBANK_DAY, LIGHTBANK_NIGHT};
2274         for(int i=0; i<2; i++)
2275         {
2276                 enum LightBank bank = banks[i];
2277
2278                 core::map<v3s16, bool> light_sources;
2279                 core::map<v3s16, u8> unlight_from;
2280
2281                 voxalgo::clearLightAndCollectSources(vmanip, a, bank, ndef,
2282                                 light_sources, unlight_from);
2283
2284                 bool inexistent_top_provides_sunlight = !block_is_underground;
2285                 voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
2286                                 vmanip, a, inexistent_top_provides_sunlight,
2287                                 light_sources, ndef);
2288                 // TODO: Do stuff according to bottom_sunlight_valid
2289
2290                 vmanip.unspreadLight(bank, unlight_from, light_sources, ndef);
2291
2292                 vmanip.spreadLight(bank, light_sources, ndef);
2293         }
2294         }
2295 }
2296
2297 #endif ///BIG COMMENT
2298