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 LuaPerlinNoise::~LuaPerlinNoise()
44 int LuaPerlinNoise::l_get2d(lua_State *L)
47 LuaPerlinNoise *o = checkobject(L, 1);
48 v2f p = check_v2f(L, 2);
49 lua_Number val = NoisePerlin2D(&o->np, p.X, p.Y, 0);
50 lua_pushnumber(L, val);
55 int LuaPerlinNoise::l_get3d(lua_State *L)
58 LuaPerlinNoise *o = checkobject(L, 1);
59 v3f p = check_v3f(L, 2);
60 lua_Number val = NoisePerlin3D(&o->np, p.X, p.Y, p.Z, 0);
61 lua_pushnumber(L, val);
66 int LuaPerlinNoise::create_object(lua_State *L)
72 if (lua_istable(L, 1)) {
73 read_noiseparams(L, 1, ¶ms);
75 params.seed = luaL_checkint(L, 1);
76 params.octaves = luaL_checkint(L, 2);
77 params.persist = luaL_checknumber(L, 3);
78 params.spread = v3f(1, 1, 1) * luaL_checknumber(L, 4);
81 LuaPerlinNoise *o = new LuaPerlinNoise(¶ms);
83 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
84 luaL_getmetatable(L, className);
85 lua_setmetatable(L, -2);
90 int LuaPerlinNoise::gc_object(lua_State *L)
92 LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
98 LuaPerlinNoise *LuaPerlinNoise::checkobject(lua_State *L, int narg)
100 NO_MAP_LOCK_REQUIRED;
101 luaL_checktype(L, narg, LUA_TUSERDATA);
102 void *ud = luaL_checkudata(L, narg, className);
104 luaL_typerror(L, narg, className);
105 return *(LuaPerlinNoise **)ud;
109 void LuaPerlinNoise::Register(lua_State *L)
112 int methodtable = lua_gettop(L);
113 luaL_newmetatable(L, className);
114 int metatable = lua_gettop(L);
116 lua_pushliteral(L, "__metatable");
117 lua_pushvalue(L, methodtable);
118 lua_settable(L, metatable);
120 lua_pushliteral(L, "__index");
121 lua_pushvalue(L, methodtable);
122 lua_settable(L, metatable);
124 lua_pushliteral(L, "__gc");
125 lua_pushcfunction(L, gc_object);
126 lua_settable(L, metatable);
130 luaL_openlib(L, 0, methods, 0);
133 lua_register(L, className, create_object);
137 const char LuaPerlinNoise::className[] = "PerlinNoise";
138 const luaL_reg LuaPerlinNoise::methods[] = {
139 luamethod(LuaPerlinNoise, get2d),
140 luamethod(LuaPerlinNoise, get3d),
144 ///////////////////////////////////////
149 LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, s32 seed, v3s16 size)
154 noise = new Noise(&np, seed, size.X, size.Y, size.Z);
155 } catch (InvalidNoiseParamsException &e) {
156 throw LuaError(e.what());
161 LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
167 int LuaPerlinNoiseMap::l_get2dMap(lua_State *L)
169 NO_MAP_LOCK_REQUIRED;
172 LuaPerlinNoiseMap *o = checkobject(L, 1);
173 v2f p = check_v2f(L, 2);
176 n->perlinMap2D(p.X, p.Y);
179 for (u32 y = 0; y != n->sy; y++) {
181 for (u32 x = 0; x != n->sx; x++) {
182 lua_pushnumber(L, n->result[i++]);
183 lua_rawseti(L, -2, x + 1);
185 lua_rawseti(L, -2, y + 1);
191 int LuaPerlinNoiseMap::l_get2dMap_flat(lua_State *L)
193 NO_MAP_LOCK_REQUIRED;
195 LuaPerlinNoiseMap *o = checkobject(L, 1);
196 v2f p = check_v2f(L, 2);
197 bool use_buffer = lua_istable(L, 3);
200 n->perlinMap2D(p.X, p.Y);
202 size_t maplen = n->sx * n->sy;
209 for (size_t i = 0; i != maplen; i++) {
210 lua_pushnumber(L, n->result[i]);
211 lua_rawseti(L, -2, i + 1);
217 int LuaPerlinNoiseMap::l_get3dMap(lua_State *L)
219 NO_MAP_LOCK_REQUIRED;
222 LuaPerlinNoiseMap *o = checkobject(L, 1);
223 v3f p = check_v3f(L, 2);
229 n->perlinMap3D(p.X, p.Y, p.Z);
232 for (u32 z = 0; z != n->sz; z++) {
234 for (u32 y = 0; y != n->sy; y++) {
236 for (u32 x = 0; x != n->sx; x++) {
237 lua_pushnumber(L, n->result[i++]);
238 lua_rawseti(L, -2, x + 1);
240 lua_rawseti(L, -2, y + 1);
242 lua_rawseti(L, -2, z + 1);
248 int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L)
250 NO_MAP_LOCK_REQUIRED;
252 LuaPerlinNoiseMap *o = checkobject(L, 1);
253 v3f p = check_v3f(L, 2);
254 bool use_buffer = lua_istable(L, 3);
260 n->perlinMap3D(p.X, p.Y, p.Z);
262 size_t maplen = n->sx * n->sy * n->sz;
269 for (size_t i = 0; i != maplen; i++) {
270 lua_pushnumber(L, n->result[i]);
271 lua_rawseti(L, -2, i + 1);
277 int LuaPerlinNoiseMap::l_calc2dMap(lua_State *L)
279 NO_MAP_LOCK_REQUIRED;
281 LuaPerlinNoiseMap *o = checkobject(L, 1);
282 v2f p = check_v2f(L, 2);
285 n->perlinMap2D(p.X, p.Y);
290 int LuaPerlinNoiseMap::l_calc3dMap(lua_State *L)
292 NO_MAP_LOCK_REQUIRED;
294 LuaPerlinNoiseMap *o = checkobject(L, 1);
295 v3f p = check_v3f(L, 2);
301 n->perlinMap3D(p.X, p.Y, p.Z);
307 int LuaPerlinNoiseMap::l_getMapSlice(lua_State *L)
309 NO_MAP_LOCK_REQUIRED;
311 LuaPerlinNoiseMap *o = checkobject(L, 1);
312 v3s16 slice_offset = read_v3s16(L, 2);
313 v3s16 slice_size = read_v3s16(L, 3);
314 bool use_buffer = lua_istable(L, 4);
323 write_array_slice_float(L, lua_gettop(L), n->result,
324 v3u16(n->sx, n->sy, n->sz),
325 v3u16(slice_offset.X, slice_offset.Y, slice_offset.Z),
326 v3u16(slice_size.X, slice_size.Y, slice_size.Z));
332 int LuaPerlinNoiseMap::create_object(lua_State *L)
335 if (!read_noiseparams(L, 1, &np))
337 v3s16 size = read_v3s16(L, 2);
339 LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(&np, 0, size);
340 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
341 luaL_getmetatable(L, className);
342 lua_setmetatable(L, -2);
347 int LuaPerlinNoiseMap::gc_object(lua_State *L)
349 LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
355 LuaPerlinNoiseMap *LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
357 luaL_checktype(L, narg, LUA_TUSERDATA);
359 void *ud = luaL_checkudata(L, narg, className);
361 luaL_typerror(L, narg, className);
363 return *(LuaPerlinNoiseMap **)ud;
367 void LuaPerlinNoiseMap::Register(lua_State *L)
370 int methodtable = lua_gettop(L);
371 luaL_newmetatable(L, className);
372 int metatable = lua_gettop(L);
374 lua_pushliteral(L, "__metatable");
375 lua_pushvalue(L, methodtable);
376 lua_settable(L, metatable);
378 lua_pushliteral(L, "__index");
379 lua_pushvalue(L, methodtable);
380 lua_settable(L, metatable);
382 lua_pushliteral(L, "__gc");
383 lua_pushcfunction(L, gc_object);
384 lua_settable(L, metatable);
388 luaL_openlib(L, 0, methods, 0);
391 lua_register(L, className, create_object);
395 const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
396 const luaL_reg LuaPerlinNoiseMap::methods[] = {
397 luamethod(LuaPerlinNoiseMap, get2dMap),
398 luamethod(LuaPerlinNoiseMap, get2dMap_flat),
399 luamethod(LuaPerlinNoiseMap, calc2dMap),
400 luamethod(LuaPerlinNoiseMap, get3dMap),
401 luamethod(LuaPerlinNoiseMap, get3dMap_flat),
402 luamethod(LuaPerlinNoiseMap, calc3dMap),
403 luamethod(LuaPerlinNoiseMap, getMapSlice),
407 ///////////////////////////////////////
412 int LuaPseudoRandom::l_next(lua_State *L)
414 NO_MAP_LOCK_REQUIRED;
416 LuaPseudoRandom *o = checkobject(L, 1);
420 if (lua_isnumber(L, 2))
421 min = luaL_checkinteger(L, 2);
422 if (lua_isnumber(L, 3))
423 max = luaL_checkinteger(L, 3);
425 errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
426 throw LuaError("PseudoRandom.next(): max < min");
428 if(max - min != 32767 && max - min > 32767/5)
429 throw LuaError("PseudoRandom.next() max-min is not 32767"
430 " and is > 32768/5. This is disallowed due to"
431 " the bad random distribution the"
432 " implementation would otherwise make.");
433 PseudoRandom &pseudo = o->m_pseudo;
434 int val = pseudo.next();
435 val = (val % (max-min+1)) + min;
436 lua_pushinteger(L, val);
441 int LuaPseudoRandom::create_object(lua_State *L)
443 NO_MAP_LOCK_REQUIRED;
445 u64 seed = luaL_checknumber(L, 1);
446 LuaPseudoRandom *o = new LuaPseudoRandom(seed);
447 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
448 luaL_getmetatable(L, className);
449 lua_setmetatable(L, -2);
454 int LuaPseudoRandom::gc_object(lua_State *L)
456 LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
462 LuaPseudoRandom *LuaPseudoRandom::checkobject(lua_State *L, int narg)
464 luaL_checktype(L, narg, LUA_TUSERDATA);
465 void *ud = luaL_checkudata(L, narg, className);
467 luaL_typerror(L, narg, className);
468 return *(LuaPseudoRandom **)ud;
472 void LuaPseudoRandom::Register(lua_State *L)
475 int methodtable = lua_gettop(L);
476 luaL_newmetatable(L, className);
477 int metatable = lua_gettop(L);
479 lua_pushliteral(L, "__metatable");
480 lua_pushvalue(L, methodtable);
481 lua_settable(L, metatable);
483 lua_pushliteral(L, "__index");
484 lua_pushvalue(L, methodtable);
485 lua_settable(L, metatable);
487 lua_pushliteral(L, "__gc");
488 lua_pushcfunction(L, gc_object);
489 lua_settable(L, metatable);
493 luaL_openlib(L, 0, methods, 0);
496 lua_register(L, className, create_object);
500 const char LuaPseudoRandom::className[] = "PseudoRandom";
501 const luaL_reg LuaPseudoRandom::methods[] = {
502 luamethod(LuaPseudoRandom, next),
506 ///////////////////////////////////////
511 int LuaPcgRandom::l_next(lua_State *L)
513 NO_MAP_LOCK_REQUIRED;
515 LuaPcgRandom *o = checkobject(L, 1);
516 u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
517 u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
519 lua_pushinteger(L, o->m_rnd.range(min, max));
524 int LuaPcgRandom::l_rand_normal_dist(lua_State *L)
526 NO_MAP_LOCK_REQUIRED;
528 LuaPcgRandom *o = checkobject(L, 1);
529 u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
530 u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
531 int num_trials = lua_isnumber(L, 4) ? lua_tointeger(L, 4) : 6;
533 lua_pushinteger(L, o->m_rnd.randNormalDist(min, max, num_trials));
538 int LuaPcgRandom::create_object(lua_State *L)
540 NO_MAP_LOCK_REQUIRED;
542 u64 seed = luaL_checknumber(L, 1);
543 LuaPcgRandom *o = lua_isnumber(L, 2) ?
544 new LuaPcgRandom(seed, lua_tointeger(L, 2)) :
545 new LuaPcgRandom(seed);
546 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
547 luaL_getmetatable(L, className);
548 lua_setmetatable(L, -2);
553 int LuaPcgRandom::gc_object(lua_State *L)
555 LuaPcgRandom *o = *(LuaPcgRandom **)(lua_touserdata(L, 1));
561 LuaPcgRandom *LuaPcgRandom::checkobject(lua_State *L, int narg)
563 luaL_checktype(L, narg, LUA_TUSERDATA);
564 void *ud = luaL_checkudata(L, narg, className);
566 luaL_typerror(L, narg, className);
567 return *(LuaPcgRandom **)ud;
571 void LuaPcgRandom::Register(lua_State *L)
574 int methodtable = lua_gettop(L);
575 luaL_newmetatable(L, className);
576 int metatable = lua_gettop(L);
578 lua_pushliteral(L, "__metatable");
579 lua_pushvalue(L, methodtable);
580 lua_settable(L, metatable);
582 lua_pushliteral(L, "__index");
583 lua_pushvalue(L, methodtable);
584 lua_settable(L, metatable);
586 lua_pushliteral(L, "__gc");
587 lua_pushcfunction(L, gc_object);
588 lua_settable(L, metatable);
592 luaL_openlib(L, 0, methods, 0);
595 lua_register(L, className, create_object);
599 const char LuaPcgRandom::className[] = "PcgRandom";
600 const luaL_reg LuaPcgRandom::methods[] = {
601 luamethod(LuaPcgRandom, next),
602 luamethod(LuaPcgRandom, rand_normal_dist),
606 ///////////////////////////////////////
611 bool LuaSecureRandom::fillRandBuf()
613 return porting::secure_rand_fill_buf(m_rand_buf, RAND_BUF_SIZE);
616 int LuaSecureRandom::l_next_bytes(lua_State *L)
618 NO_MAP_LOCK_REQUIRED;
620 LuaSecureRandom *o = checkobject(L, 1);
621 u32 count = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : 1;
624 count = MYMIN(RAND_BUF_SIZE, count);
626 // Find out whether we can pass directly from our array, or have to do some gluing
627 size_t count_remaining = RAND_BUF_SIZE - o->m_rand_idx;
628 if (count_remaining >= count) {
629 lua_pushlstring(L, o->m_rand_buf + o->m_rand_idx, count);
630 o->m_rand_idx += count;
632 char output_buf[RAND_BUF_SIZE];
634 // Copy over with what we have left from our current buffer
635 memcpy(output_buf, o->m_rand_buf + o->m_rand_idx, count_remaining);
637 // Refill buffer and copy over the remainder of what was requested
639 memcpy(output_buf + count_remaining, o->m_rand_buf, count - count_remaining);
642 o->m_rand_idx = count - count_remaining;
644 lua_pushlstring(L, output_buf, count);
651 int LuaSecureRandom::create_object(lua_State *L)
653 LuaSecureRandom *o = new LuaSecureRandom();
655 // Fail and return nil if we can't securely fill the buffer
656 if (!o->fillRandBuf()) {
661 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
662 luaL_getmetatable(L, className);
663 lua_setmetatable(L, -2);
668 int LuaSecureRandom::gc_object(lua_State *L)
670 LuaSecureRandom *o = *(LuaSecureRandom **)(lua_touserdata(L, 1));
676 LuaSecureRandom *LuaSecureRandom::checkobject(lua_State *L, int narg)
678 luaL_checktype(L, narg, LUA_TUSERDATA);
679 void *ud = luaL_checkudata(L, narg, className);
681 luaL_typerror(L, narg, className);
682 return *(LuaSecureRandom **)ud;
686 void LuaSecureRandom::Register(lua_State *L)
689 int methodtable = lua_gettop(L);
690 luaL_newmetatable(L, className);
691 int metatable = lua_gettop(L);
693 lua_pushliteral(L, "__metatable");
694 lua_pushvalue(L, methodtable);
695 lua_settable(L, metatable);
697 lua_pushliteral(L, "__index");
698 lua_pushvalue(L, methodtable);
699 lua_settable(L, metatable);
701 lua_pushliteral(L, "__gc");
702 lua_pushcfunction(L, gc_object);
703 lua_settable(L, metatable);
707 luaL_openlib(L, 0, methods, 0);
710 lua_register(L, className, create_object);
713 const char LuaSecureRandom::className[] = "SecureRandom";
714 const luaL_reg LuaSecureRandom::methods[] = {
715 luamethod(LuaSecureRandom, next_bytes),