3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
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"
26 #include "util/numeric.h"
28 ///////////////////////////////////////
33 LuaPerlinNoise::LuaPerlinNoise(NoiseParams *params) :
39 int LuaPerlinNoise::l_get_2d(lua_State *L)
42 LuaPerlinNoise *o = checkobject(L, 1);
43 v2f p = check_v2f(L, 2);
44 lua_Number val = NoisePerlin2D(&o->np, p.X, p.Y, 0);
45 lua_pushnumber(L, val);
50 int LuaPerlinNoise::l_get_3d(lua_State *L)
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);
61 int LuaPerlinNoise::create_object(lua_State *L)
67 if (lua_istable(L, 1)) {
68 read_noiseparams(L, 1, ¶ms);
70 params.seed = luaL_checkint(L, 1);
71 params.octaves = luaL_checkint(L, 2);
72 params.persist = luaL_checknumber(L, 3);
73 params.spread = v3f(1, 1, 1) * luaL_checknumber(L, 4);
76 LuaPerlinNoise *o = new LuaPerlinNoise(¶ms);
78 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
79 luaL_getmetatable(L, className);
80 lua_setmetatable(L, -2);
85 int LuaPerlinNoise::gc_object(lua_State *L)
87 LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
93 LuaPerlinNoise *LuaPerlinNoise::checkobject(lua_State *L, int narg)
96 luaL_checktype(L, narg, LUA_TUSERDATA);
97 void *ud = luaL_checkudata(L, narg, className);
99 luaL_typerror(L, narg, className);
100 return *(LuaPerlinNoise **)ud;
104 void LuaPerlinNoise::Register(lua_State *L)
107 int methodtable = lua_gettop(L);
108 luaL_newmetatable(L, className);
109 int metatable = lua_gettop(L);
111 lua_pushliteral(L, "__metatable");
112 lua_pushvalue(L, methodtable);
113 lua_settable(L, metatable);
115 lua_pushliteral(L, "__index");
116 lua_pushvalue(L, methodtable);
117 lua_settable(L, metatable);
119 lua_pushliteral(L, "__gc");
120 lua_pushcfunction(L, gc_object);
121 lua_settable(L, metatable);
125 luaL_openlib(L, 0, methods, 0);
128 lua_register(L, className, create_object);
132 const char LuaPerlinNoise::className[] = "PerlinNoise";
133 const luaL_Reg LuaPerlinNoise::methods[] = {
134 luamethod_aliased(LuaPerlinNoise, get_2d, get2d),
135 luamethod_aliased(LuaPerlinNoise, get_3d, get3d),
139 ///////////////////////////////////////
144 LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, s32 seed, v3s16 size)
149 noise = new Noise(&np, seed, size.X, size.Y, size.Z);
150 } catch (InvalidNoiseParamsException &e) {
151 throw LuaError(e.what());
156 LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
162 int LuaPerlinNoiseMap::l_get_2d_map(lua_State *L)
164 NO_MAP_LOCK_REQUIRED;
167 LuaPerlinNoiseMap *o = checkobject(L, 1);
168 v2f p = check_v2f(L, 2);
171 n->perlinMap2D(p.X, p.Y);
174 for (u32 y = 0; y != n->sy; y++) {
176 for (u32 x = 0; x != n->sx; x++) {
177 lua_pushnumber(L, n->result[i++]);
178 lua_rawseti(L, -2, x + 1);
180 lua_rawseti(L, -2, y + 1);
186 int LuaPerlinNoiseMap::l_get_2d_map_flat(lua_State *L)
188 NO_MAP_LOCK_REQUIRED;
190 LuaPerlinNoiseMap *o = checkobject(L, 1);
191 v2f p = check_v2f(L, 2);
192 bool use_buffer = lua_istable(L, 3);
195 n->perlinMap2D(p.X, p.Y);
197 size_t maplen = n->sx * n->sy;
204 for (size_t i = 0; i != maplen; i++) {
205 lua_pushnumber(L, n->result[i]);
206 lua_rawseti(L, -2, i + 1);
212 int LuaPerlinNoiseMap::l_get_3d_map(lua_State *L)
214 NO_MAP_LOCK_REQUIRED;
217 LuaPerlinNoiseMap *o = checkobject(L, 1);
218 v3f p = check_v3f(L, 2);
224 n->perlinMap3D(p.X, p.Y, p.Z);
227 for (u32 z = 0; z != n->sz; z++) {
229 for (u32 y = 0; y != n->sy; y++) {
231 for (u32 x = 0; x != n->sx; x++) {
232 lua_pushnumber(L, n->result[i++]);
233 lua_rawseti(L, -2, x + 1);
235 lua_rawseti(L, -2, y + 1);
237 lua_rawseti(L, -2, z + 1);
243 int LuaPerlinNoiseMap::l_get_3d_map_flat(lua_State *L)
245 NO_MAP_LOCK_REQUIRED;
247 LuaPerlinNoiseMap *o = checkobject(L, 1);
248 v3f p = check_v3f(L, 2);
249 bool use_buffer = lua_istable(L, 3);
255 n->perlinMap3D(p.X, p.Y, p.Z);
257 size_t maplen = n->sx * n->sy * n->sz;
264 for (size_t i = 0; i != maplen; i++) {
265 lua_pushnumber(L, n->result[i]);
266 lua_rawseti(L, -2, i + 1);
272 int LuaPerlinNoiseMap::l_calc_2d_map(lua_State *L)
274 NO_MAP_LOCK_REQUIRED;
276 LuaPerlinNoiseMap *o = checkobject(L, 1);
277 v2f p = check_v2f(L, 2);
280 n->perlinMap2D(p.X, p.Y);
285 int LuaPerlinNoiseMap::l_calc_3d_map(lua_State *L)
287 NO_MAP_LOCK_REQUIRED;
289 LuaPerlinNoiseMap *o = checkobject(L, 1);
290 v3f p = check_v3f(L, 2);
296 n->perlinMap3D(p.X, p.Y, p.Z);
302 int LuaPerlinNoiseMap::l_get_map_slice(lua_State *L)
304 NO_MAP_LOCK_REQUIRED;
306 LuaPerlinNoiseMap *o = checkobject(L, 1);
307 v3s16 slice_offset = read_v3s16(L, 2);
308 v3s16 slice_size = read_v3s16(L, 3);
309 bool use_buffer = lua_istable(L, 4);
318 write_array_slice_float(L, lua_gettop(L), n->result,
319 v3u16(n->sx, n->sy, n->sz),
320 v3u16(slice_offset.X, slice_offset.Y, slice_offset.Z),
321 v3u16(slice_size.X, slice_size.Y, slice_size.Z));
327 int LuaPerlinNoiseMap::create_object(lua_State *L)
330 if (!read_noiseparams(L, 1, &np))
332 v3s16 size = read_v3s16(L, 2);
334 LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(&np, 0, size);
335 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
336 luaL_getmetatable(L, className);
337 lua_setmetatable(L, -2);
342 int LuaPerlinNoiseMap::gc_object(lua_State *L)
344 LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
350 LuaPerlinNoiseMap *LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
352 luaL_checktype(L, narg, LUA_TUSERDATA);
354 void *ud = luaL_checkudata(L, narg, className);
356 luaL_typerror(L, narg, className);
358 return *(LuaPerlinNoiseMap **)ud;
362 void LuaPerlinNoiseMap::Register(lua_State *L)
365 int methodtable = lua_gettop(L);
366 luaL_newmetatable(L, className);
367 int metatable = lua_gettop(L);
369 lua_pushliteral(L, "__metatable");
370 lua_pushvalue(L, methodtable);
371 lua_settable(L, metatable);
373 lua_pushliteral(L, "__index");
374 lua_pushvalue(L, methodtable);
375 lua_settable(L, metatable);
377 lua_pushliteral(L, "__gc");
378 lua_pushcfunction(L, gc_object);
379 lua_settable(L, metatable);
383 luaL_openlib(L, 0, methods, 0);
386 lua_register(L, className, create_object);
390 const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
391 const luaL_Reg LuaPerlinNoiseMap::methods[] = {
392 luamethod_aliased(LuaPerlinNoiseMap, get_2d_map, get2dMap),
393 luamethod_aliased(LuaPerlinNoiseMap, get_2d_map_flat, get2dMap_flat),
394 luamethod_aliased(LuaPerlinNoiseMap, calc_2d_map, calc2dMap),
395 luamethod_aliased(LuaPerlinNoiseMap, get_3d_map, get3dMap),
396 luamethod_aliased(LuaPerlinNoiseMap, get_3d_map_flat, get3dMap_flat),
397 luamethod_aliased(LuaPerlinNoiseMap, calc_3d_map, calc3dMap),
398 luamethod_aliased(LuaPerlinNoiseMap, get_map_slice, getMapSlice),
402 ///////////////////////////////////////
407 int LuaPseudoRandom::l_next(lua_State *L)
409 NO_MAP_LOCK_REQUIRED;
411 LuaPseudoRandom *o = checkobject(L, 1);
415 if (lua_isnumber(L, 2))
416 min = luaL_checkinteger(L, 2);
417 if (lua_isnumber(L, 3))
418 max = luaL_checkinteger(L, 3);
420 errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
421 throw LuaError("PseudoRandom.next(): max < min");
423 if(max - min != 32767 && max - min > 32767/5)
424 throw LuaError("PseudoRandom.next() max-min is not 32767"
425 " and is > 32768/5. This is disallowed due to"
426 " the bad random distribution the"
427 " implementation would otherwise make.");
428 PseudoRandom &pseudo = o->m_pseudo;
429 int val = pseudo.next();
430 val = (val % (max-min+1)) + min;
431 lua_pushinteger(L, val);
436 int LuaPseudoRandom::create_object(lua_State *L)
438 NO_MAP_LOCK_REQUIRED;
440 u64 seed = luaL_checknumber(L, 1);
441 LuaPseudoRandom *o = new LuaPseudoRandom(seed);
442 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
443 luaL_getmetatable(L, className);
444 lua_setmetatable(L, -2);
449 int LuaPseudoRandom::gc_object(lua_State *L)
451 LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
457 LuaPseudoRandom *LuaPseudoRandom::checkobject(lua_State *L, int narg)
459 luaL_checktype(L, narg, LUA_TUSERDATA);
460 void *ud = luaL_checkudata(L, narg, className);
462 luaL_typerror(L, narg, className);
463 return *(LuaPseudoRandom **)ud;
467 void LuaPseudoRandom::Register(lua_State *L)
470 int methodtable = lua_gettop(L);
471 luaL_newmetatable(L, className);
472 int metatable = lua_gettop(L);
474 lua_pushliteral(L, "__metatable");
475 lua_pushvalue(L, methodtable);
476 lua_settable(L, metatable);
478 lua_pushliteral(L, "__index");
479 lua_pushvalue(L, methodtable);
480 lua_settable(L, metatable);
482 lua_pushliteral(L, "__gc");
483 lua_pushcfunction(L, gc_object);
484 lua_settable(L, metatable);
488 luaL_openlib(L, 0, methods, 0);
491 lua_register(L, className, create_object);
495 const char LuaPseudoRandom::className[] = "PseudoRandom";
496 const luaL_Reg LuaPseudoRandom::methods[] = {
497 luamethod(LuaPseudoRandom, next),
501 ///////////////////////////////////////
506 int LuaPcgRandom::l_next(lua_State *L)
508 NO_MAP_LOCK_REQUIRED;
510 LuaPcgRandom *o = checkobject(L, 1);
511 u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
512 u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
514 lua_pushinteger(L, o->m_rnd.range(min, max));
519 int LuaPcgRandom::l_rand_normal_dist(lua_State *L)
521 NO_MAP_LOCK_REQUIRED;
523 LuaPcgRandom *o = checkobject(L, 1);
524 u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
525 u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
526 int num_trials = lua_isnumber(L, 4) ? lua_tointeger(L, 4) : 6;
528 lua_pushinteger(L, o->m_rnd.randNormalDist(min, max, num_trials));
533 int LuaPcgRandom::create_object(lua_State *L)
535 NO_MAP_LOCK_REQUIRED;
537 u64 seed = luaL_checknumber(L, 1);
538 LuaPcgRandom *o = lua_isnumber(L, 2) ?
539 new LuaPcgRandom(seed, lua_tointeger(L, 2)) :
540 new LuaPcgRandom(seed);
541 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
542 luaL_getmetatable(L, className);
543 lua_setmetatable(L, -2);
548 int LuaPcgRandom::gc_object(lua_State *L)
550 LuaPcgRandom *o = *(LuaPcgRandom **)(lua_touserdata(L, 1));
556 LuaPcgRandom *LuaPcgRandom::checkobject(lua_State *L, int narg)
558 luaL_checktype(L, narg, LUA_TUSERDATA);
559 void *ud = luaL_checkudata(L, narg, className);
561 luaL_typerror(L, narg, className);
562 return *(LuaPcgRandom **)ud;
566 void LuaPcgRandom::Register(lua_State *L)
569 int methodtable = lua_gettop(L);
570 luaL_newmetatable(L, className);
571 int metatable = lua_gettop(L);
573 lua_pushliteral(L, "__metatable");
574 lua_pushvalue(L, methodtable);
575 lua_settable(L, metatable);
577 lua_pushliteral(L, "__index");
578 lua_pushvalue(L, methodtable);
579 lua_settable(L, metatable);
581 lua_pushliteral(L, "__gc");
582 lua_pushcfunction(L, gc_object);
583 lua_settable(L, metatable);
587 luaL_openlib(L, 0, methods, 0);
590 lua_register(L, className, create_object);
594 const char LuaPcgRandom::className[] = "PcgRandom";
595 const luaL_Reg LuaPcgRandom::methods[] = {
596 luamethod(LuaPcgRandom, next),
597 luamethod(LuaPcgRandom, rand_normal_dist),
601 ///////////////////////////////////////
606 bool LuaSecureRandom::fillRandBuf()
608 return porting::secure_rand_fill_buf(m_rand_buf, RAND_BUF_SIZE);
611 int LuaSecureRandom::l_next_bytes(lua_State *L)
613 NO_MAP_LOCK_REQUIRED;
615 LuaSecureRandom *o = checkobject(L, 1);
616 u32 count = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : 1;
619 count = MYMIN(RAND_BUF_SIZE, count);
621 // Find out whether we can pass directly from our array, or have to do some gluing
622 size_t count_remaining = RAND_BUF_SIZE - o->m_rand_idx;
623 if (count_remaining >= count) {
624 lua_pushlstring(L, o->m_rand_buf + o->m_rand_idx, count);
625 o->m_rand_idx += count;
627 char output_buf[RAND_BUF_SIZE];
629 // Copy over with what we have left from our current buffer
630 memcpy(output_buf, o->m_rand_buf + o->m_rand_idx, count_remaining);
632 // Refill buffer and copy over the remainder of what was requested
634 memcpy(output_buf + count_remaining, o->m_rand_buf, count - count_remaining);
637 o->m_rand_idx = count - count_remaining;
639 lua_pushlstring(L, output_buf, count);
646 int LuaSecureRandom::create_object(lua_State *L)
648 LuaSecureRandom *o = new LuaSecureRandom();
650 // Fail and return nil if we can't securely fill the buffer
651 if (!o->fillRandBuf()) {
656 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
657 luaL_getmetatable(L, className);
658 lua_setmetatable(L, -2);
663 int LuaSecureRandom::gc_object(lua_State *L)
665 LuaSecureRandom *o = *(LuaSecureRandom **)(lua_touserdata(L, 1));
671 LuaSecureRandom *LuaSecureRandom::checkobject(lua_State *L, int narg)
673 luaL_checktype(L, narg, LUA_TUSERDATA);
674 void *ud = luaL_checkudata(L, narg, className);
676 luaL_typerror(L, narg, className);
677 return *(LuaSecureRandom **)ud;
681 void LuaSecureRandom::Register(lua_State *L)
684 int methodtable = lua_gettop(L);
685 luaL_newmetatable(L, className);
686 int metatable = lua_gettop(L);
688 lua_pushliteral(L, "__metatable");
689 lua_pushvalue(L, methodtable);
690 lua_settable(L, metatable);
692 lua_pushliteral(L, "__index");
693 lua_pushvalue(L, methodtable);
694 lua_settable(L, metatable);
696 lua_pushliteral(L, "__gc");
697 lua_pushcfunction(L, gc_object);
698 lua_settable(L, metatable);
702 luaL_openlib(L, 0, methods, 0);
705 lua_register(L, className, create_object);
708 const char LuaSecureRandom::className[] = "SecureRandom";
709 const luaL_Reg LuaSecureRandom::methods[] = {
710 luamethod(LuaSecureRandom, next_bytes),