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 = readParam<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 = readParam<float>(L, 3);
73 params.spread = v3f(1, 1, 1) * readParam<float>(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 markAliasDeprecated(methods);
126 luaL_openlib(L, 0, methods, 0);
129 lua_register(L, className, create_object);
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),
140 ///////////////////////////////////////
145 LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, s32 seed, v3s16 size)
150 noise = new Noise(&np, seed, size.X, size.Y, size.Z);
151 } catch (InvalidNoiseParamsException &e) {
152 throw LuaError(e.what());
157 LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
163 int LuaPerlinNoiseMap::l_get_2d_map(lua_State *L)
165 NO_MAP_LOCK_REQUIRED;
168 LuaPerlinNoiseMap *o = checkobject(L, 1);
169 v2f p = readParam<v2f>(L, 2);
172 n->perlinMap2D(p.X, p.Y);
175 for (u32 y = 0; y != n->sy; y++) {
177 for (u32 x = 0; x != n->sx; x++) {
178 lua_pushnumber(L, n->result[i++]);
179 lua_rawseti(L, -2, x + 1);
181 lua_rawseti(L, -2, y + 1);
187 int LuaPerlinNoiseMap::l_get_2d_map_flat(lua_State *L)
189 NO_MAP_LOCK_REQUIRED;
191 LuaPerlinNoiseMap *o = checkobject(L, 1);
192 v2f p = readParam<v2f>(L, 2);
193 bool use_buffer = lua_istable(L, 3);
196 n->perlinMap2D(p.X, p.Y);
198 size_t maplen = n->sx * n->sy;
205 for (size_t i = 0; i != maplen; i++) {
206 lua_pushnumber(L, n->result[i]);
207 lua_rawseti(L, -2, i + 1);
213 int LuaPerlinNoiseMap::l_get_3d_map(lua_State *L)
215 NO_MAP_LOCK_REQUIRED;
218 LuaPerlinNoiseMap *o = checkobject(L, 1);
219 v3f p = check_v3f(L, 2);
225 n->perlinMap3D(p.X, p.Y, p.Z);
228 for (u32 z = 0; z != n->sz; z++) {
230 for (u32 y = 0; y != n->sy; y++) {
232 for (u32 x = 0; x != n->sx; x++) {
233 lua_pushnumber(L, n->result[i++]);
234 lua_rawseti(L, -2, x + 1);
236 lua_rawseti(L, -2, y + 1);
238 lua_rawseti(L, -2, z + 1);
244 int LuaPerlinNoiseMap::l_get_3d_map_flat(lua_State *L)
246 NO_MAP_LOCK_REQUIRED;
248 LuaPerlinNoiseMap *o = checkobject(L, 1);
249 v3f p = check_v3f(L, 2);
250 bool use_buffer = lua_istable(L, 3);
256 n->perlinMap3D(p.X, p.Y, p.Z);
258 size_t maplen = n->sx * n->sy * n->sz;
265 for (size_t i = 0; i != maplen; i++) {
266 lua_pushnumber(L, n->result[i]);
267 lua_rawseti(L, -2, i + 1);
273 int LuaPerlinNoiseMap::l_calc_2d_map(lua_State *L)
275 NO_MAP_LOCK_REQUIRED;
277 LuaPerlinNoiseMap *o = checkobject(L, 1);
278 v2f p = readParam<v2f>(L, 2);
281 n->perlinMap2D(p.X, p.Y);
286 int LuaPerlinNoiseMap::l_calc_3d_map(lua_State *L)
288 NO_MAP_LOCK_REQUIRED;
290 LuaPerlinNoiseMap *o = checkobject(L, 1);
291 v3f p = check_v3f(L, 2);
297 n->perlinMap3D(p.X, p.Y, p.Z);
303 int LuaPerlinNoiseMap::l_get_map_slice(lua_State *L)
305 NO_MAP_LOCK_REQUIRED;
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);
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));
328 int LuaPerlinNoiseMap::create_object(lua_State *L)
331 if (!read_noiseparams(L, 1, &np))
333 v3s16 size = read_v3s16(L, 2);
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);
343 int LuaPerlinNoiseMap::gc_object(lua_State *L)
345 LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
351 LuaPerlinNoiseMap *LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
353 luaL_checktype(L, narg, LUA_TUSERDATA);
355 void *ud = luaL_checkudata(L, narg, className);
357 luaL_typerror(L, narg, className);
359 return *(LuaPerlinNoiseMap **)ud;
363 void LuaPerlinNoiseMap::Register(lua_State *L)
366 int methodtable = lua_gettop(L);
367 luaL_newmetatable(L, className);
368 int metatable = lua_gettop(L);
370 lua_pushliteral(L, "__metatable");
371 lua_pushvalue(L, methodtable);
372 lua_settable(L, metatable);
374 lua_pushliteral(L, "__index");
375 lua_pushvalue(L, methodtable);
376 lua_settable(L, metatable);
378 lua_pushliteral(L, "__gc");
379 lua_pushcfunction(L, gc_object);
380 lua_settable(L, metatable);
384 markAliasDeprecated(methods);
385 luaL_openlib(L, 0, methods, 0);
388 lua_register(L, className, create_object);
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),
404 ///////////////////////////////////////
409 int LuaPseudoRandom::l_next(lua_State *L)
411 NO_MAP_LOCK_REQUIRED;
413 LuaPseudoRandom *o = checkobject(L, 1);
417 if (lua_isnumber(L, 2))
418 min = luaL_checkinteger(L, 2);
419 if (lua_isnumber(L, 3))
420 max = luaL_checkinteger(L, 3);
422 errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
423 throw LuaError("PseudoRandom.next(): max < min");
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);
438 int LuaPseudoRandom::create_object(lua_State *L)
440 NO_MAP_LOCK_REQUIRED;
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);
451 int LuaPseudoRandom::gc_object(lua_State *L)
453 LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
459 LuaPseudoRandom *LuaPseudoRandom::checkobject(lua_State *L, int narg)
461 luaL_checktype(L, narg, LUA_TUSERDATA);
462 void *ud = luaL_checkudata(L, narg, className);
464 luaL_typerror(L, narg, className);
465 return *(LuaPseudoRandom **)ud;
469 void LuaPseudoRandom::Register(lua_State *L)
472 int methodtable = lua_gettop(L);
473 luaL_newmetatable(L, className);
474 int metatable = lua_gettop(L);
476 lua_pushliteral(L, "__metatable");
477 lua_pushvalue(L, methodtable);
478 lua_settable(L, metatable);
480 lua_pushliteral(L, "__index");
481 lua_pushvalue(L, methodtable);
482 lua_settable(L, metatable);
484 lua_pushliteral(L, "__gc");
485 lua_pushcfunction(L, gc_object);
486 lua_settable(L, metatable);
490 luaL_openlib(L, 0, methods, 0);
493 lua_register(L, className, create_object);
497 const char LuaPseudoRandom::className[] = "PseudoRandom";
498 const luaL_Reg LuaPseudoRandom::methods[] = {
499 luamethod(LuaPseudoRandom, next),
503 ///////////////////////////////////////
508 int LuaPcgRandom::l_next(lua_State *L)
510 NO_MAP_LOCK_REQUIRED;
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;
516 lua_pushinteger(L, o->m_rnd.range(min, max));
521 int LuaPcgRandom::l_rand_normal_dist(lua_State *L)
523 NO_MAP_LOCK_REQUIRED;
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;
530 lua_pushinteger(L, o->m_rnd.randNormalDist(min, max, num_trials));
535 int LuaPcgRandom::create_object(lua_State *L)
537 NO_MAP_LOCK_REQUIRED;
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);
550 int LuaPcgRandom::gc_object(lua_State *L)
552 LuaPcgRandom *o = *(LuaPcgRandom **)(lua_touserdata(L, 1));
558 LuaPcgRandom *LuaPcgRandom::checkobject(lua_State *L, int narg)
560 luaL_checktype(L, narg, LUA_TUSERDATA);
561 void *ud = luaL_checkudata(L, narg, className);
563 luaL_typerror(L, narg, className);
564 return *(LuaPcgRandom **)ud;
568 void LuaPcgRandom::Register(lua_State *L)
571 int methodtable = lua_gettop(L);
572 luaL_newmetatable(L, className);
573 int metatable = lua_gettop(L);
575 lua_pushliteral(L, "__metatable");
576 lua_pushvalue(L, methodtable);
577 lua_settable(L, metatable);
579 lua_pushliteral(L, "__index");
580 lua_pushvalue(L, methodtable);
581 lua_settable(L, metatable);
583 lua_pushliteral(L, "__gc");
584 lua_pushcfunction(L, gc_object);
585 lua_settable(L, metatable);
589 luaL_openlib(L, 0, methods, 0);
592 lua_register(L, className, create_object);
596 const char LuaPcgRandom::className[] = "PcgRandom";
597 const luaL_Reg LuaPcgRandom::methods[] = {
598 luamethod(LuaPcgRandom, next),
599 luamethod(LuaPcgRandom, rand_normal_dist),
603 ///////////////////////////////////////
608 bool LuaSecureRandom::fillRandBuf()
610 return porting::secure_rand_fill_buf(m_rand_buf, RAND_BUF_SIZE);
613 int LuaSecureRandom::l_next_bytes(lua_State *L)
615 NO_MAP_LOCK_REQUIRED;
617 LuaSecureRandom *o = checkobject(L, 1);
618 u32 count = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : 1;
621 count = MYMIN(RAND_BUF_SIZE, count);
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;
629 char output_buf[RAND_BUF_SIZE];
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);
634 // Refill buffer and copy over the remainder of what was requested
636 memcpy(output_buf + count_remaining, o->m_rand_buf, count - count_remaining);
639 o->m_rand_idx = count - count_remaining;
641 lua_pushlstring(L, output_buf, count);
648 int LuaSecureRandom::create_object(lua_State *L)
650 LuaSecureRandom *o = new LuaSecureRandom();
652 // Fail and return nil if we can't securely fill the buffer
653 if (!o->fillRandBuf()) {
658 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
659 luaL_getmetatable(L, className);
660 lua_setmetatable(L, -2);
665 int LuaSecureRandom::gc_object(lua_State *L)
667 LuaSecureRandom *o = *(LuaSecureRandom **)(lua_touserdata(L, 1));
673 LuaSecureRandom *LuaSecureRandom::checkobject(lua_State *L, int narg)
675 luaL_checktype(L, narg, LUA_TUSERDATA);
676 void *ud = luaL_checkudata(L, narg, className);
678 luaL_typerror(L, narg, className);
679 return *(LuaSecureRandom **)ud;
683 void LuaSecureRandom::Register(lua_State *L)
686 int methodtable = lua_gettop(L);
687 luaL_newmetatable(L, className);
688 int metatable = lua_gettop(L);
690 lua_pushliteral(L, "__metatable");
691 lua_pushvalue(L, methodtable);
692 lua_settable(L, metatable);
694 lua_pushliteral(L, "__index");
695 lua_pushvalue(L, methodtable);
696 lua_settable(L, metatable);
698 lua_pushliteral(L, "__gc");
699 lua_pushcfunction(L, gc_object);
700 lua_settable(L, metatable);
704 luaL_openlib(L, 0, methods, 0);
707 lua_register(L, className, create_object);
710 const char LuaSecureRandom::className[] = "SecureRandom";
711 const luaL_Reg LuaSecureRandom::methods[] = {
712 luamethod(LuaSecureRandom, next_bytes),