]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_noise.cpp
script: Put getGuiEngine() inside a client-only #ifdef
[dragonfireclient.git] / src / script / lua_api / l_noise.cpp
1 /*
2 Minetest
3 Copyright (C) 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 "lua_api/l_noise.h"
21 #include "lua_api/l_internal.h"
22 #include "common/c_converter.h"
23 #include "common/c_content.h"
24 #include "log.h"
25 #include "porting.h"
26 #include "util/numeric.h"
27
28 ///////////////////////////////////////
29 /*
30   LuaPerlinNoise
31 */
32
33 LuaPerlinNoise::LuaPerlinNoise(NoiseParams *params) :
34         np(*params)
35 {
36 }
37
38
39 int LuaPerlinNoise::l_get_2d(lua_State *L)
40 {
41         NO_MAP_LOCK_REQUIRED;
42         LuaPerlinNoise *o = checkobject(L, 1);
43         v2f p = readParam<v2f>(L, 2);
44         lua_Number val = NoisePerlin2D(&o->np, p.X, p.Y, 0);
45         lua_pushnumber(L, val);
46         return 1;
47 }
48
49
50 int LuaPerlinNoise::l_get_3d(lua_State *L)
51 {
52         NO_MAP_LOCK_REQUIRED;
53         LuaPerlinNoise *o = checkobject(L, 1);
54         v3f p = check_v3f(L, 2);
55         lua_Number val = NoisePerlin3D(&o->np, p.X, p.Y, p.Z, 0);
56         lua_pushnumber(L, val);
57         return 1;
58 }
59
60
61 int LuaPerlinNoise::create_object(lua_State *L)
62 {
63         NO_MAP_LOCK_REQUIRED;
64
65         NoiseParams params;
66
67         if (lua_istable(L, 1)) {
68                 read_noiseparams(L, 1, &params);
69         } else {
70                 params.seed    = luaL_checkint(L, 1);
71                 params.octaves = luaL_checkint(L, 2);
72                 params.persist = readParam<float>(L, 3);
73                 params.spread  = v3f(1, 1, 1) * readParam<float>(L, 4);
74         }
75
76         LuaPerlinNoise *o = new LuaPerlinNoise(&params);
77
78         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
79         luaL_getmetatable(L, className);
80         lua_setmetatable(L, -2);
81         return 1;
82 }
83
84
85 int LuaPerlinNoise::gc_object(lua_State *L)
86 {
87         LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
88         delete o;
89         return 0;
90 }
91
92
93 LuaPerlinNoise *LuaPerlinNoise::checkobject(lua_State *L, int narg)
94 {
95         NO_MAP_LOCK_REQUIRED;
96         luaL_checktype(L, narg, LUA_TUSERDATA);
97         void *ud = luaL_checkudata(L, narg, className);
98         if (!ud)
99                 luaL_typerror(L, narg, className);
100         return *(LuaPerlinNoise **)ud;
101 }
102
103
104 void LuaPerlinNoise::Register(lua_State *L)
105 {
106         lua_newtable(L);
107         int methodtable = lua_gettop(L);
108         luaL_newmetatable(L, className);
109         int metatable = lua_gettop(L);
110
111         lua_pushliteral(L, "__metatable");
112         lua_pushvalue(L, methodtable);
113         lua_settable(L, metatable);
114
115         lua_pushliteral(L, "__index");
116         lua_pushvalue(L, methodtable);
117         lua_settable(L, metatable);
118
119         lua_pushliteral(L, "__gc");
120         lua_pushcfunction(L, gc_object);
121         lua_settable(L, metatable);
122
123         lua_pop(L, 1);
124
125         markAliasDeprecated(methods);
126         luaL_openlib(L, 0, methods, 0);
127         lua_pop(L, 1);
128
129         lua_register(L, className, create_object);
130 }
131
132
133 const char LuaPerlinNoise::className[] = "PerlinNoise";
134 luaL_Reg LuaPerlinNoise::methods[] = {
135         luamethod_aliased(LuaPerlinNoise, get_2d, get2d),
136         luamethod_aliased(LuaPerlinNoise, get_3d, get3d),
137         {0,0}
138 };
139
140 ///////////////////////////////////////
141 /*
142   LuaPerlinNoiseMap
143 */
144
145 LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, s32 seed, v3s16 size)
146 {
147         m_is3d = size.Z > 1;
148         np = *params;
149         try {
150                 noise = new Noise(&np, seed, size.X, size.Y, size.Z);
151         } catch (InvalidNoiseParamsException &e) {
152                 throw LuaError(e.what());
153         }
154 }
155
156
157 LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
158 {
159         delete noise;
160 }
161
162
163 int LuaPerlinNoiseMap::l_get_2d_map(lua_State *L)
164 {
165         NO_MAP_LOCK_REQUIRED;
166         size_t i = 0;
167
168         LuaPerlinNoiseMap *o = checkobject(L, 1);
169         v2f p = readParam<v2f>(L, 2);
170
171         Noise *n = o->noise;
172         n->perlinMap2D(p.X, p.Y);
173
174         lua_createtable(L, n->sy, 0);
175         for (u32 y = 0; y != n->sy; y++) {
176                 lua_createtable(L, n->sx, 0);
177                 for (u32 x = 0; x != n->sx; x++) {
178                         lua_pushnumber(L, n->result[i++]);
179                         lua_rawseti(L, -2, x + 1);
180                 }
181                 lua_rawseti(L, -2, y + 1);
182         }
183         return 1;
184 }
185
186
187 int LuaPerlinNoiseMap::l_get_2d_map_flat(lua_State *L)
188 {
189         NO_MAP_LOCK_REQUIRED;
190
191         LuaPerlinNoiseMap *o = checkobject(L, 1);
192         v2f p = readParam<v2f>(L, 2);
193         bool use_buffer = lua_istable(L, 3);
194
195         Noise *n = o->noise;
196         n->perlinMap2D(p.X, p.Y);
197
198         size_t maplen = n->sx * n->sy;
199
200         if (use_buffer)
201                 lua_pushvalue(L, 3);
202         else
203                 lua_createtable(L, maplen, 0);
204
205         for (size_t i = 0; i != maplen; i++) {
206                 lua_pushnumber(L, n->result[i]);
207                 lua_rawseti(L, -2, i + 1);
208         }
209         return 1;
210 }
211
212
213 int LuaPerlinNoiseMap::l_get_3d_map(lua_State *L)
214 {
215         NO_MAP_LOCK_REQUIRED;
216         size_t i = 0;
217
218         LuaPerlinNoiseMap *o = checkobject(L, 1);
219         v3f p = check_v3f(L, 2);
220
221         if (!o->m_is3d)
222                 return 0;
223
224         Noise *n = o->noise;
225         n->perlinMap3D(p.X, p.Y, p.Z);
226
227         lua_createtable(L, n->sz, 0);
228         for (u32 z = 0; z != n->sz; z++) {
229                 lua_createtable(L, n->sy, 0);
230                 for (u32 y = 0; y != n->sy; y++) {
231                         lua_createtable(L, n->sx, 0);
232                         for (u32 x = 0; x != n->sx; x++) {
233                                 lua_pushnumber(L, n->result[i++]);
234                                 lua_rawseti(L, -2, x + 1);
235                         }
236                         lua_rawseti(L, -2, y + 1);
237                 }
238                 lua_rawseti(L, -2, z + 1);
239         }
240         return 1;
241 }
242
243
244 int LuaPerlinNoiseMap::l_get_3d_map_flat(lua_State *L)
245 {
246         NO_MAP_LOCK_REQUIRED;
247
248         LuaPerlinNoiseMap *o = checkobject(L, 1);
249         v3f p                = check_v3f(L, 2);
250         bool use_buffer      = lua_istable(L, 3);
251
252         if (!o->m_is3d)
253                 return 0;
254
255         Noise *n = o->noise;
256         n->perlinMap3D(p.X, p.Y, p.Z);
257
258         size_t maplen = n->sx * n->sy * n->sz;
259
260         if (use_buffer)
261                 lua_pushvalue(L, 3);
262         else
263                 lua_createtable(L, maplen, 0);
264
265         for (size_t i = 0; i != maplen; i++) {
266                 lua_pushnumber(L, n->result[i]);
267                 lua_rawseti(L, -2, i + 1);
268         }
269         return 1;
270 }
271
272
273 int LuaPerlinNoiseMap::l_calc_2d_map(lua_State *L)
274 {
275         NO_MAP_LOCK_REQUIRED;
276
277         LuaPerlinNoiseMap *o = checkobject(L, 1);
278         v2f p = readParam<v2f>(L, 2);
279
280         Noise *n = o->noise;
281         n->perlinMap2D(p.X, p.Y);
282
283         return 0;
284 }
285
286 int LuaPerlinNoiseMap::l_calc_3d_map(lua_State *L)
287 {
288         NO_MAP_LOCK_REQUIRED;
289
290         LuaPerlinNoiseMap *o = checkobject(L, 1);
291         v3f p                = check_v3f(L, 2);
292
293         if (!o->m_is3d)
294                 return 0;
295
296         Noise *n = o->noise;
297         n->perlinMap3D(p.X, p.Y, p.Z);
298
299         return 0;
300 }
301
302
303 int LuaPerlinNoiseMap::l_get_map_slice(lua_State *L)
304 {
305         NO_MAP_LOCK_REQUIRED;
306
307         LuaPerlinNoiseMap *o = checkobject(L, 1);
308         v3s16 slice_offset   = read_v3s16(L, 2);
309         v3s16 slice_size     = read_v3s16(L, 3);
310         bool use_buffer      = lua_istable(L, 4);
311
312         Noise *n = o->noise;
313
314         if (use_buffer)
315                 lua_pushvalue(L, 4);
316         else
317                 lua_newtable(L);
318
319         write_array_slice_float(L, lua_gettop(L), n->result,
320                 v3u16(n->sx, n->sy, n->sz),
321                 v3u16(slice_offset.X, slice_offset.Y, slice_offset.Z),
322                 v3u16(slice_size.X, slice_size.Y, slice_size.Z));
323
324         return 1;
325 }
326
327
328 int LuaPerlinNoiseMap::create_object(lua_State *L)
329 {
330         NoiseParams np;
331         if (!read_noiseparams(L, 1, &np))
332                 return 0;
333         v3s16 size = read_v3s16(L, 2);
334
335         LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(&np, 0, size);
336         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
337         luaL_getmetatable(L, className);
338         lua_setmetatable(L, -2);
339         return 1;
340 }
341
342
343 int LuaPerlinNoiseMap::gc_object(lua_State *L)
344 {
345         LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
346         delete o;
347         return 0;
348 }
349
350
351 LuaPerlinNoiseMap *LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
352 {
353         luaL_checktype(L, narg, LUA_TUSERDATA);
354
355         void *ud = luaL_checkudata(L, narg, className);
356         if (!ud)
357                 luaL_typerror(L, narg, className);
358
359         return *(LuaPerlinNoiseMap **)ud;
360 }
361
362
363 void LuaPerlinNoiseMap::Register(lua_State *L)
364 {
365         lua_newtable(L);
366         int methodtable = lua_gettop(L);
367         luaL_newmetatable(L, className);
368         int metatable = lua_gettop(L);
369
370         lua_pushliteral(L, "__metatable");
371         lua_pushvalue(L, methodtable);
372         lua_settable(L, metatable);
373
374         lua_pushliteral(L, "__index");
375         lua_pushvalue(L, methodtable);
376         lua_settable(L, metatable);
377
378         lua_pushliteral(L, "__gc");
379         lua_pushcfunction(L, gc_object);
380         lua_settable(L, metatable);
381
382         lua_pop(L, 1);
383
384         markAliasDeprecated(methods);
385         luaL_openlib(L, 0, methods, 0);
386         lua_pop(L, 1);
387
388         lua_register(L, className, create_object);
389 }
390
391
392 const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
393 luaL_Reg LuaPerlinNoiseMap::methods[] = {
394         luamethod_aliased(LuaPerlinNoiseMap, get_2d_map,      get2dMap),
395         luamethod_aliased(LuaPerlinNoiseMap, get_2d_map_flat, get2dMap_flat),
396         luamethod_aliased(LuaPerlinNoiseMap, calc_2d_map,     calc2dMap),
397         luamethod_aliased(LuaPerlinNoiseMap, get_3d_map,      get3dMap),
398         luamethod_aliased(LuaPerlinNoiseMap, get_3d_map_flat, get3dMap_flat),
399         luamethod_aliased(LuaPerlinNoiseMap, calc_3d_map,     calc3dMap),
400         luamethod_aliased(LuaPerlinNoiseMap, get_map_slice,   getMapSlice),
401         {0,0}
402 };
403
404 ///////////////////////////////////////
405 /*
406         LuaPseudoRandom
407 */
408
409 int LuaPseudoRandom::l_next(lua_State *L)
410 {
411         NO_MAP_LOCK_REQUIRED;
412
413         LuaPseudoRandom *o = checkobject(L, 1);
414         int min = 0;
415         int max = 32767;
416         lua_settop(L, 3);
417         if (lua_isnumber(L, 2))
418                 min = luaL_checkinteger(L, 2);
419         if (lua_isnumber(L, 3))
420                 max = luaL_checkinteger(L, 3);
421         if (max < min) {
422                 errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
423                 throw LuaError("PseudoRandom.next(): max < min");
424         }
425         if(max - min != 32767 && max - min > 32767/5)
426                 throw LuaError("PseudoRandom.next() max-min is not 32767"
427                                 " and is > 32768/5. This is disallowed due to"
428                                 " the bad random distribution the"
429                                 " implementation would otherwise make.");
430         PseudoRandom &pseudo = o->m_pseudo;
431         int val = pseudo.next();
432         val = (val % (max-min+1)) + min;
433         lua_pushinteger(L, val);
434         return 1;
435 }
436
437
438 int LuaPseudoRandom::create_object(lua_State *L)
439 {
440         NO_MAP_LOCK_REQUIRED;
441
442         u64 seed = luaL_checknumber(L, 1);
443         LuaPseudoRandom *o = new LuaPseudoRandom(seed);
444         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
445         luaL_getmetatable(L, className);
446         lua_setmetatable(L, -2);
447         return 1;
448 }
449
450
451 int LuaPseudoRandom::gc_object(lua_State *L)
452 {
453         LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
454         delete o;
455         return 0;
456 }
457
458
459 LuaPseudoRandom *LuaPseudoRandom::checkobject(lua_State *L, int narg)
460 {
461         luaL_checktype(L, narg, LUA_TUSERDATA);
462         void *ud = luaL_checkudata(L, narg, className);
463         if (!ud)
464                 luaL_typerror(L, narg, className);
465         return *(LuaPseudoRandom **)ud;
466 }
467
468
469 void LuaPseudoRandom::Register(lua_State *L)
470 {
471         lua_newtable(L);
472         int methodtable = lua_gettop(L);
473         luaL_newmetatable(L, className);
474         int metatable = lua_gettop(L);
475
476         lua_pushliteral(L, "__metatable");
477         lua_pushvalue(L, methodtable);
478         lua_settable(L, metatable);
479
480         lua_pushliteral(L, "__index");
481         lua_pushvalue(L, methodtable);
482         lua_settable(L, metatable);
483
484         lua_pushliteral(L, "__gc");
485         lua_pushcfunction(L, gc_object);
486         lua_settable(L, metatable);
487
488         lua_pop(L, 1);
489
490         luaL_openlib(L, 0, methods, 0);
491         lua_pop(L, 1);
492
493         lua_register(L, className, create_object);
494 }
495
496
497 const char LuaPseudoRandom::className[] = "PseudoRandom";
498 const luaL_Reg LuaPseudoRandom::methods[] = {
499         luamethod(LuaPseudoRandom, next),
500         {0,0}
501 };
502
503 ///////////////////////////////////////
504 /*
505         LuaPcgRandom
506 */
507
508 int LuaPcgRandom::l_next(lua_State *L)
509 {
510         NO_MAP_LOCK_REQUIRED;
511
512         LuaPcgRandom *o = checkobject(L, 1);
513         u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
514         u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
515
516         lua_pushinteger(L, o->m_rnd.range(min, max));
517         return 1;
518 }
519
520
521 int LuaPcgRandom::l_rand_normal_dist(lua_State *L)
522 {
523         NO_MAP_LOCK_REQUIRED;
524
525         LuaPcgRandom *o = checkobject(L, 1);
526         u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
527         u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
528         int num_trials = lua_isnumber(L, 4) ? lua_tointeger(L, 4) : 6;
529
530         lua_pushinteger(L, o->m_rnd.randNormalDist(min, max, num_trials));
531         return 1;
532 }
533
534
535 int LuaPcgRandom::create_object(lua_State *L)
536 {
537         NO_MAP_LOCK_REQUIRED;
538
539         u64 seed = luaL_checknumber(L, 1);
540         LuaPcgRandom *o = lua_isnumber(L, 2) ?
541                 new LuaPcgRandom(seed, lua_tointeger(L, 2)) :
542                 new LuaPcgRandom(seed);
543         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
544         luaL_getmetatable(L, className);
545         lua_setmetatable(L, -2);
546         return 1;
547 }
548
549
550 int LuaPcgRandom::gc_object(lua_State *L)
551 {
552         LuaPcgRandom *o = *(LuaPcgRandom **)(lua_touserdata(L, 1));
553         delete o;
554         return 0;
555 }
556
557
558 LuaPcgRandom *LuaPcgRandom::checkobject(lua_State *L, int narg)
559 {
560         luaL_checktype(L, narg, LUA_TUSERDATA);
561         void *ud = luaL_checkudata(L, narg, className);
562         if (!ud)
563                 luaL_typerror(L, narg, className);
564         return *(LuaPcgRandom **)ud;
565 }
566
567
568 void LuaPcgRandom::Register(lua_State *L)
569 {
570         lua_newtable(L);
571         int methodtable = lua_gettop(L);
572         luaL_newmetatable(L, className);
573         int metatable = lua_gettop(L);
574
575         lua_pushliteral(L, "__metatable");
576         lua_pushvalue(L, methodtable);
577         lua_settable(L, metatable);
578
579         lua_pushliteral(L, "__index");
580         lua_pushvalue(L, methodtable);
581         lua_settable(L, metatable);
582
583         lua_pushliteral(L, "__gc");
584         lua_pushcfunction(L, gc_object);
585         lua_settable(L, metatable);
586
587         lua_pop(L, 1);
588
589         luaL_openlib(L, 0, methods, 0);
590         lua_pop(L, 1);
591
592         lua_register(L, className, create_object);
593 }
594
595
596 const char LuaPcgRandom::className[] = "PcgRandom";
597 const luaL_Reg LuaPcgRandom::methods[] = {
598         luamethod(LuaPcgRandom, next),
599         luamethod(LuaPcgRandom, rand_normal_dist),
600         {0,0}
601 };
602
603 ///////////////////////////////////////
604 /*
605         LuaSecureRandom
606 */
607
608 bool LuaSecureRandom::fillRandBuf()
609 {
610         return porting::secure_rand_fill_buf(m_rand_buf, RAND_BUF_SIZE);
611 }
612
613 int LuaSecureRandom::l_next_bytes(lua_State *L)
614 {
615         NO_MAP_LOCK_REQUIRED;
616
617         LuaSecureRandom *o = checkobject(L, 1);
618         u32 count = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : 1;
619
620         // Limit count
621         count = MYMIN(RAND_BUF_SIZE, count);
622
623         // Find out whether we can pass directly from our array, or have to do some gluing
624         size_t count_remaining = RAND_BUF_SIZE - o->m_rand_idx;
625         if (count_remaining >= count) {
626                 lua_pushlstring(L, o->m_rand_buf + o->m_rand_idx, count);
627                 o->m_rand_idx += count;
628         } else {
629                 char output_buf[RAND_BUF_SIZE];
630
631                 // Copy over with what we have left from our current buffer
632                 memcpy(output_buf, o->m_rand_buf + o->m_rand_idx, count_remaining);
633
634                 // Refill buffer and copy over the remainder of what was requested
635                 o->fillRandBuf();
636                 memcpy(output_buf + count_remaining, o->m_rand_buf, count - count_remaining);
637
638                 // Update index
639                 o->m_rand_idx = count - count_remaining;
640
641                 lua_pushlstring(L, output_buf, count);
642         }
643
644         return 1;
645 }
646
647
648 int LuaSecureRandom::create_object(lua_State *L)
649 {
650         LuaSecureRandom *o = new LuaSecureRandom();
651
652         // Fail and return nil if we can't securely fill the buffer
653         if (!o->fillRandBuf()) {
654                 delete o;
655                 return 0;
656         }
657
658         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
659         luaL_getmetatable(L, className);
660         lua_setmetatable(L, -2);
661         return 1;
662 }
663
664
665 int LuaSecureRandom::gc_object(lua_State *L)
666 {
667         LuaSecureRandom *o = *(LuaSecureRandom **)(lua_touserdata(L, 1));
668         delete o;
669         return 0;
670 }
671
672
673 LuaSecureRandom *LuaSecureRandom::checkobject(lua_State *L, int narg)
674 {
675         luaL_checktype(L, narg, LUA_TUSERDATA);
676         void *ud = luaL_checkudata(L, narg, className);
677         if (!ud)
678                 luaL_typerror(L, narg, className);
679         return *(LuaSecureRandom **)ud;
680 }
681
682
683 void LuaSecureRandom::Register(lua_State *L)
684 {
685         lua_newtable(L);
686         int methodtable = lua_gettop(L);
687         luaL_newmetatable(L, className);
688         int metatable = lua_gettop(L);
689
690         lua_pushliteral(L, "__metatable");
691         lua_pushvalue(L, methodtable);
692         lua_settable(L, metatable);
693
694         lua_pushliteral(L, "__index");
695         lua_pushvalue(L, methodtable);
696         lua_settable(L, metatable);
697
698         lua_pushliteral(L, "__gc");
699         lua_pushcfunction(L, gc_object);
700         lua_settable(L, metatable);
701
702         lua_pop(L, 1);
703
704         luaL_openlib(L, 0, methods, 0);
705         lua_pop(L, 1);
706
707         lua_register(L, className, create_object);
708 }
709
710 const char LuaSecureRandom::className[] = "SecureRandom";
711 const luaL_Reg LuaSecureRandom::methods[] = {
712         luamethod(LuaSecureRandom, next_bytes),
713         {0,0}
714 };