]> git.lizzy.rs Git - dragonfireclient.git/blob - src/mapgen_indev.cpp
Add ObjectRef.hud_set_hotbar_itemcount and add TOCLIENT_HUD_SET_PARAM
[dragonfireclient.git] / src / mapgen_indev.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_indev.h"
21 #include "constants.h"
22 #include "map.h"
23 #include "main.h"
24 #include "util/numeric.h"
25 #include "log.h"
26
27 /////////////////// Mapgen Indev perlin noise (default values - not used, from config or defaultsettings)
28
29 NoiseIndevParams nparams_indev_def;
30
31 /*
32 NoiseIndevParams nparams_indev_def_terrain_base;
33 //      (-AVERAGE_MUD_AMOUNT, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6, 1);
34 NoiseIndevParams nparams_indev_def_terrain_higher;
35 //      (20.0, 16.0, v3f(500.0, 500.0, 500.0), 85039, 5, 0.6, 1);
36 NoiseIndevParams nparams_indev_def_steepness;
37 //      (0.85, 0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7, 1);
38 NoiseIndevParams nparams_indev_def_mud;
39 //      (AVERAGE_MUD_AMOUNT, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55, 1);
40 NoiseIndevParams nparams_indev_def_float_islands;
41 //      (1, 10.0, v3f(500.0, 500.0, 500.0), 32451, 5, 0.6, 1);
42 NoiseIndevParams nparams_indev_def_biome;
43 */
44
45 ///////////////////////////////////////////////////////////////////////////////
46
47 void NoiseIndev::init(NoiseIndevParams *np, int seed, int sx, int sy, int sz) {
48         Noise::init((NoiseParams*)np, seed, sx, sy, sz);
49         this->npindev   = np;
50 }
51
52 NoiseIndev::NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy) : Noise(np, seed, sx, sy) {
53         init(np, seed, sx, sy, 1);
54 }
55
56 NoiseIndev::NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy, int sz) : Noise(np, seed, sx, sy, sz) {
57         init(np, seed, sx, sy, sz);
58 }
59
60 float farscale(float scale, float z) {
61         return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 1 - (fabs(z))                     ) / (MAP_GENERATION_LIMIT * 1) ) * (scale - 1) );
62 }
63
64 float farscale(float scale, float x, float z) {
65         return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 2 - (fabs(x) + fabs(z))           ) / (MAP_GENERATION_LIMIT * 2) ) * (scale - 1) );
66 }
67
68 float farscale(float scale, float x, float y, float z) {
69         return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 3 - (fabs(x) + fabs(y) + fabs(z)) ) / (MAP_GENERATION_LIMIT * 3) ) * (scale - 1) );
70 }
71
72 void NoiseIndev::transformNoiseMapFarScale(float xx, float yy, float zz) {
73         int i = 0;
74         for (int z = 0; z != sz; z++) {
75                 for (int y = 0; y != sy; y++) {
76                         for (int x = 0; x != sx; x++) {
77                                 result[i] = result[i] * npindev->scale * farscale(npindev->farscale, xx, yy, zz) + npindev->offset;
78                                 i++;
79                         }
80                 }
81         }
82 }
83
84 MapgenIndev::MapgenIndev(int mapgenid, MapgenIndevParams *params, EmergeManager *emerge) 
85         : MapgenV6(mapgenid, params, emerge)
86 {
87         noiseindev_terrain_base    = new NoiseIndev(&params->npindev_terrain_base,   seed, csize.X, csize.Z);
88         noiseindev_terrain_higher  = new NoiseIndev(&params->npindev_terrain_higher, seed, csize.X, csize.Z);
89         noiseindev_steepness       = new NoiseIndev(&params->npindev_steepness,      seed, csize.X, csize.Z);
90         noiseindev_mud             = new NoiseIndev(&params->npindev_mud,            seed, csize.X, csize.Z);
91         noiseindev_float_islands1  = new NoiseIndev(&params->npindev_float_islands1, seed, csize.X, csize.Y, csize.Z);
92         noiseindev_float_islands2  = new NoiseIndev(&params->npindev_float_islands2, seed, csize.X, csize.Y, csize.Z);
93         noiseindev_float_islands3  = new NoiseIndev(&params->npindev_float_islands3, seed, csize.X, csize.Z);
94         noiseindev_biome           = new NoiseIndev(&params->npindev_biome,          seed, csize.X, csize.Z);
95 }
96
97 MapgenIndev::~MapgenIndev() {
98         delete noiseindev_terrain_base;
99         delete noiseindev_terrain_higher;
100         delete noiseindev_steepness;
101         //delete noise_height_select;
102         //delete noise_trees;
103         delete noiseindev_mud;
104         //delete noise_beach;
105         delete noiseindev_float_islands1;
106         delete noiseindev_float_islands2;
107         delete noiseindev_float_islands3;
108         delete noiseindev_biome;
109 }
110
111 void MapgenIndev::calculateNoise() {
112         int x = node_min.X;
113         int y = node_min.Y;
114         int z = node_min.Z;
115         // Need to adjust for the original implementation's +.5 offset...
116         if (!(flags & MG_FLAT)) {
117                 noiseindev_terrain_base->perlinMap2D(
118                         x + 0.5 * noiseindev_terrain_base->npindev->spread.X * farscale(noiseindev_terrain_base->npindev->farspread, x, z),
119                         z + 0.5 * noiseindev_terrain_base->npindev->spread.Z * farscale(noiseindev_terrain_base->npindev->farspread, x, z));
120                 noiseindev_terrain_base->transformNoiseMapFarScale(x, y, z);
121
122                 noiseindev_terrain_higher->perlinMap2D(
123                         x + 0.5 * noiseindev_terrain_higher->npindev->spread.X * farscale(noiseindev_terrain_higher->npindev->farspread, x, z),
124                         z + 0.5 * noiseindev_terrain_higher->npindev->spread.Z * farscale(noiseindev_terrain_higher->npindev->farspread, x, z));
125                 noiseindev_terrain_higher->transformNoiseMapFarScale(x, y, z);
126
127                 noiseindev_steepness->perlinMap2D(
128                         x + 0.5 * noiseindev_steepness->npindev->spread.X * farscale(noiseindev_steepness->npindev->farspread, x, z),
129                         z + 0.5 * noiseindev_steepness->npindev->spread.Z * farscale(noiseindev_steepness->npindev->farspread, x, z));
130                 noiseindev_steepness->transformNoiseMapFarScale(x, y, z);
131
132                 noise_height_select->perlinMap2D(
133                         x + 0.5 * noise_height_select->np->spread.X,
134                         z + 0.5 * noise_height_select->np->spread.Z);
135
136                 noiseindev_float_islands1->perlinMap3D(
137                         x + 0.33 * noiseindev_float_islands1->npindev->spread.X * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z),
138                         y + 0.33 * noiseindev_float_islands1->npindev->spread.Y * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z),
139                         z + 0.33 * noiseindev_float_islands1->npindev->spread.Z * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z)
140                 );
141                 noiseindev_float_islands1->transformNoiseMapFarScale(x, y, z);
142
143                 noiseindev_float_islands2->perlinMap3D(
144                         x + 0.33 * noiseindev_float_islands2->npindev->spread.X * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z),
145                         y + 0.33 * noiseindev_float_islands2->npindev->spread.Y * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z),
146                         z + 0.33 * noiseindev_float_islands2->npindev->spread.Z * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z)
147                 );
148                 noiseindev_float_islands2->transformNoiseMapFarScale(x, y, z);
149
150                 noiseindev_float_islands3->perlinMap2D(
151                         x + 0.5 * noiseindev_float_islands3->npindev->spread.X * farscale(noiseindev_float_islands3->npindev->farspread, x, z),
152                         z + 0.5 * noiseindev_float_islands3->npindev->spread.Z * farscale(noiseindev_float_islands3->npindev->farspread, x, z));
153                 noiseindev_float_islands3->transformNoiseMapFarScale(x, y, z);
154
155                 noiseindev_mud->perlinMap2D(
156                         x + 0.5 * noiseindev_mud->npindev->spread.X * farscale(noiseindev_mud->npindev->farspread, x, y, z),
157                         z + 0.5 * noiseindev_mud->npindev->spread.Z * farscale(noiseindev_mud->npindev->farspread, x, y, z));
158                 noiseindev_mud->transformNoiseMapFarScale(x, y, z);
159         }
160         noise_beach->perlinMap2D(
161                 x + 0.2 * noise_beach->np->spread.X,
162                 z + 0.7 * noise_beach->np->spread.Z);
163
164         noise_biome->perlinMap2D(
165                 x + 0.6 * noiseindev_biome->npindev->spread.X * farscale(noiseindev_biome->npindev->farspread, x, z),
166                 z + 0.2 * noiseindev_biome->npindev->spread.Z * farscale(noiseindev_biome->npindev->farspread, x, z));
167 }
168
169 bool MapgenIndevParams::readParams(Settings *settings) {
170         freq_desert = settings->getFloat("mgv6_freq_desert");
171         freq_beach  = settings->getFloat("mgv6_freq_beach");
172
173         bool success = 
174                 settings->getNoiseIndevParams("mgindev_np_terrain_base",   npindev_terrain_base)   &&
175                 settings->getNoiseIndevParams("mgindev_np_terrain_higher", npindev_terrain_higher) &&
176                 settings->getNoiseIndevParams("mgindev_np_steepness",      npindev_steepness)      &&
177                 settings->getNoiseParams("mgv6_np_height_select",          np_height_select)       &&
178                 settings->getNoiseParams("mgv6_np_trees",                  np_trees)               &&
179                 settings->getNoiseIndevParams("mgindev_np_mud",            npindev_mud)            &&
180                 settings->getNoiseParams("mgv6_np_beach",                  np_beach)               &&
181                 settings->getNoiseIndevParams("mgindev_np_biome",          npindev_biome)          &&
182                 settings->getNoiseParams("mgv6_np_cave",                   np_cave)                &&
183                 settings->getNoiseIndevParams("mgindev_np_float_islands1", npindev_float_islands1) &&
184                 settings->getNoiseIndevParams("mgindev_np_float_islands2", npindev_float_islands2) &&
185                 settings->getNoiseIndevParams("mgindev_np_float_islands3", npindev_float_islands3);
186         return success;
187 }
188
189 void MapgenIndevParams::writeParams(Settings *settings) {
190         settings->setFloat("mgv6_freq_desert", freq_desert);
191         settings->setFloat("mgv6_freq_beach",  freq_beach);
192
193         settings->setNoiseIndevParams("mgindev_np_terrain_base",   npindev_terrain_base);
194         settings->setNoiseIndevParams("mgindev_np_terrain_higher", npindev_terrain_higher);
195         settings->setNoiseIndevParams("mgindev_np_steepness",      npindev_steepness);
196         settings->setNoiseParams("mgv6_np_height_select",          np_height_select);
197         settings->setNoiseParams("mgv6_np_trees",                  np_trees);
198         settings->setNoiseIndevParams("mgindev_np_mud",            npindev_mud);
199         settings->setNoiseParams("mgv6_np_beach",                  np_beach);
200         settings->setNoiseIndevParams("mgindev_np_biome",          npindev_biome);
201         settings->setNoiseParams("mgv6_np_cave",                   np_cave);
202         settings->setNoiseIndevParams("mgindev_np_float_islands1", npindev_float_islands1);
203         settings->setNoiseIndevParams("mgindev_np_float_islands2", npindev_float_islands2);
204         settings->setNoiseIndevParams("mgindev_np_float_islands3", npindev_float_islands3);
205 }
206
207
208 float MapgenIndev::baseTerrainLevelFromNoise(v2s16 p) {
209         if (flags & MG_FLAT)
210                 return water_level;
211                 
212         float terrain_base   = NoisePerlin2DPosOffset(noiseindev_terrain_base->npindev,
213                                                         p.X, 0.5, p.Y, 0.5, seed);
214         float terrain_higher = NoisePerlin2DPosOffset(noiseindev_terrain_higher->npindev,
215                                                         p.X, 0.5, p.Y, 0.5, seed);
216         float steepness      = NoisePerlin2DPosOffset(noiseindev_steepness->npindev,
217                                                         p.X, 0.5, p.Y, 0.5, seed);
218         float height_select  = NoisePerlin2DNoTxfmPosOffset(noise_height_select->np,
219                                                         p.X, 0.5, p.Y, 0.5, seed);
220
221         return baseTerrainLevel(terrain_base, terrain_higher,
222                                                         steepness,    height_select);
223 }
224
225 float MapgenIndev::baseTerrainLevelFromMap(int index) {
226         if (flags & MG_FLAT)
227                 return water_level;
228         
229         float terrain_base   = noiseindev_terrain_base->result[index];
230         float terrain_higher = noiseindev_terrain_higher->result[index];
231         float steepness      = noiseindev_steepness->result[index];
232         float height_select  = noise_height_select->result[index];
233         
234         return baseTerrainLevel(terrain_base, terrain_higher,
235                                                         steepness,    height_select);
236 }
237
238 float MapgenIndev::getMudAmount(int index) {
239         if (flags & MG_FLAT)
240                 return AVERAGE_MUD_AMOUNT;
241                 
242         /*return ((float)AVERAGE_MUD_AMOUNT + 2.0 * noise2d_perlin(
243                         0.5+(float)p.X/200, 0.5+(float)p.Y/200,
244                         seed+91013, 3, 0.55));*/
245         
246         return noiseindev_mud->result[index];
247 }
248
249 void MapgenIndev::generateCaves(int max_stone_y) {
250         float cave_amount = NoisePerlin2D(np_cave, node_min.X, node_min.Y, seed);
251         int volume_nodes = (node_max.X - node_min.X + 1) *
252                                            (node_max.Y - node_min.Y + 1) * MAP_BLOCKSIZE;
253         cave_amount = MYMAX(0.0, cave_amount);
254         u32 caves_count = cave_amount * volume_nodes / 50000;
255         u32 bruises_count = 1;
256         PseudoRandom ps(blockseed + 21343);
257         PseudoRandom ps2(blockseed + 1032);
258         
259         if (ps.range(1, 6) == 1)
260                 bruises_count = ps.range(0, ps.range(0, 2));
261         
262         if (getBiome(v2s16(node_min.X, node_min.Z)) == BT_DESERT) {
263                 caves_count   /= 3;
264                 bruises_count /= 3;
265         }
266         
267         for (u32 i = 0; i < caves_count + bruises_count; i++) {
268                 bool large_cave = (i >= caves_count);
269                 CaveIndev cave(this, &ps, &ps2, node_min, large_cave);
270
271                 cave.makeCave(node_min, node_max, max_stone_y);
272         }
273 }
274
275 CaveIndev::CaveIndev(MapgenIndev *mg, PseudoRandom *ps, PseudoRandom *ps2,
276                                 v3s16 node_min, bool is_large_cave) {
277         this->vm = mg->vm;
278         this->water_level = mg->water_level;
279         this->large_cave = is_large_cave;
280         this->ps  = ps;
281         this->ps2 = ps2;
282         this->c_water_source = mg->c_water_source;
283         this->c_lava_source  = mg->c_lava_source;
284
285         min_tunnel_diameter = 2;
286         max_tunnel_diameter = ps->range(2,6);
287         dswitchint = ps->range(1,14);
288         flooded = large_cave && ps->range(0,4);
289         if (large_cave) {
290                 part_max_length_rs = ps->range(2,4);
291                 float scale = farscale(0.2, node_min.X, node_min.Y, node_min.Z);
292                 if (node_min.Y < -100 && !ps->range(0, scale * 30)) { //huge
293                         flooded = !ps->range(0, 3);
294                         tunnel_routepoints = ps->range(5, 30);
295                         min_tunnel_diameter = 30;
296                         max_tunnel_diameter = ps->range(40, ps->range(80, 150));
297                 } else {
298                         tunnel_routepoints = ps->range(5, ps->range(15,30));
299                         min_tunnel_diameter = 5;
300                         max_tunnel_diameter = ps->range(7, ps->range(8,24));
301                 }
302         } else {
303                 part_max_length_rs = ps->range(2,9);
304                 tunnel_routepoints = ps->range(10, ps->range(15,30));
305         }
306         large_cave_is_flat = (ps->range(0,1) == 0);
307 }
308
309 /*
310 // version with one perlin3d. use with good params like
311 settings->setDefault("mgindev_np_float_islands1",  "-9.5, 10,  (20,  50,  50 ), 45123, 5, 0.6,  1.5, 5");
312 void MapgenIndev::generateFloatIslands(int min_y) {
313         if (node_min.Y < min_y) return;
314         v3s16 p0(node_min.X, node_min.Y, node_min.Z);
315         MapNode n1(c_stone), n2(c_desert_stone);
316         int xl = node_max.X - node_min.X;
317         int yl = node_max.Y - node_min.Y;
318         int zl = node_max.Z - node_min.Z;
319         u32 index = 0;
320         for (int x1 = 0; x1 <= xl; x1++)
321         {
322                 //int x = x1 + node_min.Y;
323                 for (int z1 = 0; z1 <= zl; z1++)
324                 {
325                         //int z = z1 + node_min.Z;
326                         for (int y1 = 0; y1 <= yl; y1++, index++)
327                         {
328                                 //int y = y1 + node_min.Y;
329                                 float noise = noiseindev_float_islands1->result[index];
330                                 //dstream << " y1="<<y1<< " x1="<<x1<<" z1="<<z1<< " noise="<<noise << std::endl;
331                                 if (noise > 0 ) {
332                                         v3s16 p = p0 + v3s16(x1, y1, z1);
333                                         u32 i = vm->m_area.index(p);
334                                         if (!vm->m_area.contains(i))
335                                                 continue;
336                                         // Cancel if not  air
337                                         if (vm->m_data[i].getContent() != CONTENT_AIR)
338                                                 continue;
339                                         vm->m_data[i] = noise > 1 ? n1 : n2;
340                                 }
341                         }
342                 }
343         }
344 }
345 */
346
347 void MapgenIndev::generateFloatIslands(int min_y) {
348         if (node_min.Y < min_y) return;
349         PseudoRandom pr(blockseed + 985);
350         // originally from http://forum.minetest.net/viewtopic.php?id=4776
351         float RAR = 0.8 * farscale(0.4, node_min.Y); // 0.4; // Island rarity in chunk layer. -0.4 = thick layer with holes, 0 = 50%, 0.4 = desert rarity, 0.7 = very rare.
352         float AMPY = 24; // 24; // Amplitude of island centre y variation.
353         float TGRAD = 24; // 24; // Noise gradient to create top surface. Tallness of island top.
354         float BGRAD = 24; // 24; // Noise gradient to create bottom surface. Tallness of island bottom.
355
356         v3s16 p0(node_min.X, node_min.Y, node_min.Z);
357         MapNode n1(c_stone);
358
359         float xl = node_max.X - node_min.X;
360         float yl = node_max.Y - node_min.Y;
361         float zl = node_max.Z - node_min.Z;
362         float midy = node_min.Y + yl * 0.5;
363         u32 index = 0, index2d = 0;
364         for (int x1 = 0; x1 <= xl; ++x1)
365         {
366                 for (int z1 = 0; z1 <= zl; ++z1, ++index2d)
367                 {
368                         float noise3 = noiseindev_float_islands3->result[index2d];
369                         float pmidy = midy + noise3 / 1.5 * AMPY;
370                         for (int y1 = 0; y1 <= yl; ++y1, ++index)
371                         {
372                                 int y = y1 + node_min.Y;
373                                 float noise1 = noiseindev_float_islands1->result[index];
374                                 float offset = y > pmidy ? (y - pmidy) / TGRAD : (pmidy - y) / BGRAD;
375                                 float noise1off = noise1 - offset - RAR;
376                                 if (noise1off > 0 && noise1off < 0.7) {
377                                         float noise2 = noiseindev_float_islands2->result[index];
378                                         if (noise2 - noise1off > -0.7){
379                                                 v3s16 p = p0 + v3s16(x1, y1, z1);
380                                                 u32 i = vm->m_area.index(p);
381                                                 if (!vm->m_area.contains(i))
382                                                         continue;
383                                                 // Cancel if not  air
384                                                 if (vm->m_data[i].getContent() != CONTENT_AIR)
385                                                         continue;
386                                                 vm->m_data[i] = n1;
387                                         }
388                                 }
389                         }
390                 }
391         }
392 }
393
394 void MapgenIndev::generateExperimental() {
395         int float_islands = g_settings->getS16("mgindev_float_islands");
396         if (float_islands)
397                 generateFloatIslands(float_islands);
398 }