3 Copyright (C) 2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
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.
21 #include "lua_api/l_vmanip.h"
22 #include "lua_api/l_internal.h"
23 #include "common/c_content.h"
24 #include "common/c_converter.h"
26 #include "environment.h"
31 #include "voxelalgorithms.h"
34 int LuaVoxelManip::gc_object(lua_State *L)
36 LuaVoxelManip *o = *(LuaVoxelManip **)(lua_touserdata(L, 1));
42 int LuaVoxelManip::l_read_from_map(lua_State *L)
46 LuaVoxelManip *o = checkobject(L, 1);
49 v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 2));
50 v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 3));
51 sortBoxVerticies(bp1, bp2);
53 vm->initialEmerge(bp1, bp2);
55 push_v3s16(L, vm->m_area.MinEdge);
56 push_v3s16(L, vm->m_area.MaxEdge);
61 int LuaVoxelManip::l_get_data(lua_State *L)
65 LuaVoxelManip *o = checkobject(L, 1);
66 bool use_buffer = lua_istable(L, 2);
70 u32 volume = vm->m_area.getVolume();
77 for (u32 i = 0; i != volume; i++) {
78 lua_Integer cid = vm->m_data[i].getContent();
79 lua_pushinteger(L, cid);
80 lua_rawseti(L, -2, i + 1);
86 int LuaVoxelManip::l_set_data(lua_State *L)
90 LuaVoxelManip *o = checkobject(L, 1);
93 if (!lua_istable(L, 2))
96 u32 volume = vm->m_area.getVolume();
97 for (u32 i = 0; i != volume; i++) {
98 lua_rawgeti(L, 2, i + 1);
99 content_t c = lua_tointeger(L, -1);
101 vm->m_data[i].setContent(c);
109 int LuaVoxelManip::l_write_to_map(lua_State *L)
113 LuaVoxelManip *o = checkobject(L, 1);
114 bool update_light = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : true;
116 ServerMap *map = &(env->getServerMap());
117 if (o->is_mapgen_vm || !update_light) {
118 o->vm->blitBackAll(&(o->modified_blocks));
120 voxalgo::blit_back_with_light(map, o->vm,
121 &(o->modified_blocks));
125 event.type = MEET_OTHER;
126 for (std::map<v3s16, MapBlock *>::iterator it = o->modified_blocks.begin();
127 it != o->modified_blocks.end(); ++it)
128 event.modified_blocks.insert(it->first);
130 map->dispatchEvent(&event);
132 o->modified_blocks.clear();
136 int LuaVoxelManip::l_get_node_at(lua_State *L)
138 NO_MAP_LOCK_REQUIRED;
140 INodeDefManager *ndef = getServer(L)->getNodeDefManager();
142 LuaVoxelManip *o = checkobject(L, 1);
143 v3s16 pos = check_v3s16(L, 2);
145 pushnode(L, o->vm->getNodeNoExNoEmerge(pos), ndef);
149 int LuaVoxelManip::l_set_node_at(lua_State *L)
151 NO_MAP_LOCK_REQUIRED;
153 INodeDefManager *ndef = getServer(L)->getNodeDefManager();
155 LuaVoxelManip *o = checkobject(L, 1);
156 v3s16 pos = check_v3s16(L, 2);
157 MapNode n = readnode(L, 3, ndef);
159 o->vm->setNodeNoEmerge(pos, n);
164 int LuaVoxelManip::l_update_liquids(lua_State *L)
168 LuaVoxelManip *o = checkobject(L, 1);
170 Map *map = &(env->getMap());
171 INodeDefManager *ndef = getServer(L)->getNodeDefManager();
172 MMVManip *vm = o->vm;
178 mg.updateLiquid(&map->m_transforming_liquid,
179 vm->m_area.MinEdge, vm->m_area.MaxEdge);
184 int LuaVoxelManip::l_calc_lighting(lua_State *L)
186 NO_MAP_LOCK_REQUIRED;
188 LuaVoxelManip *o = checkobject(L, 1);
189 if (!o->is_mapgen_vm)
192 INodeDefManager *ndef = getServer(L)->getNodeDefManager();
193 EmergeManager *emerge = getServer(L)->getEmergeManager();
194 MMVManip *vm = o->vm;
196 v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE;
197 v3s16 fpmin = vm->m_area.MinEdge;
198 v3s16 fpmax = vm->m_area.MaxEdge;
199 v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) : fpmin + yblock;
200 v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) : fpmax - yblock;
201 bool propagate_shadow = lua_isboolean(L, 4) ? lua_toboolean(L, 4) : true;
203 sortBoxVerticies(pmin, pmax);
204 if (!vm->m_area.contains(VoxelArea(pmin, pmax)))
205 throw LuaError("Specified voxel area out of VoxelManipulator bounds");
210 mg.water_level = emerge->mgparams->water_level;
212 mg.calcLighting(pmin, pmax, fpmin, fpmax, propagate_shadow);
217 int LuaVoxelManip::l_set_lighting(lua_State *L)
219 NO_MAP_LOCK_REQUIRED;
221 LuaVoxelManip *o = checkobject(L, 1);
222 if (!o->is_mapgen_vm)
225 if (!lua_istable(L, 2))
229 light = (getintfield_default(L, 2, "day", 0) & 0x0F);
230 light |= (getintfield_default(L, 2, "night", 0) & 0x0F) << 4;
232 MMVManip *vm = o->vm;
234 v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE;
235 v3s16 pmin = lua_istable(L, 3) ? check_v3s16(L, 3) : vm->m_area.MinEdge + yblock;
236 v3s16 pmax = lua_istable(L, 4) ? check_v3s16(L, 4) : vm->m_area.MaxEdge - yblock;
238 sortBoxVerticies(pmin, pmax);
239 if (!vm->m_area.contains(VoxelArea(pmin, pmax)))
240 throw LuaError("Specified voxel area out of VoxelManipulator bounds");
245 mg.setLighting(light, pmin, pmax);
250 int LuaVoxelManip::l_get_light_data(lua_State *L)
252 NO_MAP_LOCK_REQUIRED;
254 LuaVoxelManip *o = checkobject(L, 1);
255 MMVManip *vm = o->vm;
257 u32 volume = vm->m_area.getVolume();
260 for (u32 i = 0; i != volume; i++) {
261 lua_Integer light = vm->m_data[i].param1;
262 lua_pushinteger(L, light);
263 lua_rawseti(L, -2, i + 1);
269 int LuaVoxelManip::l_set_light_data(lua_State *L)
271 NO_MAP_LOCK_REQUIRED;
273 LuaVoxelManip *o = checkobject(L, 1);
274 MMVManip *vm = o->vm;
276 if (!lua_istable(L, 2))
279 u32 volume = vm->m_area.getVolume();
280 for (u32 i = 0; i != volume; i++) {
281 lua_rawgeti(L, 2, i + 1);
282 u8 light = lua_tointeger(L, -1);
284 vm->m_data[i].param1 = light;
292 int LuaVoxelManip::l_get_param2_data(lua_State *L)
294 NO_MAP_LOCK_REQUIRED;
296 LuaVoxelManip *o = checkobject(L, 1);
297 bool use_buffer = lua_istable(L, 2);
299 MMVManip *vm = o->vm;
301 u32 volume = vm->m_area.getVolume();
308 for (u32 i = 0; i != volume; i++) {
309 lua_Integer param2 = vm->m_data[i].param2;
310 lua_pushinteger(L, param2);
311 lua_rawseti(L, -2, i + 1);
317 int LuaVoxelManip::l_set_param2_data(lua_State *L)
319 NO_MAP_LOCK_REQUIRED;
321 LuaVoxelManip *o = checkobject(L, 1);
322 MMVManip *vm = o->vm;
324 if (!lua_istable(L, 2))
327 u32 volume = vm->m_area.getVolume();
328 for (u32 i = 0; i != volume; i++) {
329 lua_rawgeti(L, 2, i + 1);
330 u8 param2 = lua_tointeger(L, -1);
332 vm->m_data[i].param2 = param2;
340 int LuaVoxelManip::l_update_map(lua_State *L)
345 int LuaVoxelManip::l_was_modified(lua_State *L)
347 NO_MAP_LOCK_REQUIRED;
349 LuaVoxelManip *o = checkobject(L, 1);
350 MMVManip *vm = o->vm;
352 lua_pushboolean(L, vm->m_is_dirty);
357 int LuaVoxelManip::l_get_emerged_area(lua_State *L)
359 NO_MAP_LOCK_REQUIRED;
361 LuaVoxelManip *o = checkobject(L, 1);
363 push_v3s16(L, o->vm->m_area.MinEdge);
364 push_v3s16(L, o->vm->m_area.MaxEdge);
369 LuaVoxelManip::LuaVoxelManip(MMVManip *mmvm, bool is_mg_vm) :
370 is_mapgen_vm(is_mg_vm),
375 LuaVoxelManip::LuaVoxelManip(Map *map) : vm(new MMVManip(map))
379 LuaVoxelManip::LuaVoxelManip(Map *map, v3s16 p1, v3s16 p2)
381 vm = new MMVManip(map);
383 v3s16 bp1 = getNodeBlockPos(p1);
384 v3s16 bp2 = getNodeBlockPos(p2);
385 sortBoxVerticies(bp1, bp2);
386 vm->initialEmerge(bp1, bp2);
389 LuaVoxelManip::~LuaVoxelManip()
396 // Creates an LuaVoxelManip and leaves it on top of stack
397 int LuaVoxelManip::create_object(lua_State *L)
401 Map *map = &(env->getMap());
402 LuaVoxelManip *o = (lua_istable(L, 1) && lua_istable(L, 2)) ?
403 new LuaVoxelManip(map, check_v3s16(L, 1), check_v3s16(L, 2)) :
404 new LuaVoxelManip(map);
406 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
407 luaL_getmetatable(L, className);
408 lua_setmetatable(L, -2);
412 LuaVoxelManip *LuaVoxelManip::checkobject(lua_State *L, int narg)
414 NO_MAP_LOCK_REQUIRED;
416 luaL_checktype(L, narg, LUA_TUSERDATA);
418 void *ud = luaL_checkudata(L, narg, className);
420 luaL_typerror(L, narg, className);
422 return *(LuaVoxelManip **)ud; // unbox pointer
425 void LuaVoxelManip::Register(lua_State *L)
428 int methodtable = lua_gettop(L);
429 luaL_newmetatable(L, className);
430 int metatable = lua_gettop(L);
432 lua_pushliteral(L, "__metatable");
433 lua_pushvalue(L, methodtable);
434 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
436 lua_pushliteral(L, "__index");
437 lua_pushvalue(L, methodtable);
438 lua_settable(L, metatable);
440 lua_pushliteral(L, "__gc");
441 lua_pushcfunction(L, gc_object);
442 lua_settable(L, metatable);
444 lua_pop(L, 1); // drop metatable
446 luaL_openlib(L, 0, methods, 0); // fill methodtable
447 lua_pop(L, 1); // drop methodtable
449 // Can be created from Lua (VoxelManip())
450 lua_register(L, className, create_object);
453 const char LuaVoxelManip::className[] = "VoxelManip";
454 const luaL_Reg LuaVoxelManip::methods[] = {
455 luamethod(LuaVoxelManip, read_from_map),
456 luamethod(LuaVoxelManip, get_data),
457 luamethod(LuaVoxelManip, set_data),
458 luamethod(LuaVoxelManip, get_node_at),
459 luamethod(LuaVoxelManip, set_node_at),
460 luamethod(LuaVoxelManip, write_to_map),
461 luamethod(LuaVoxelManip, update_map),
462 luamethod(LuaVoxelManip, update_liquids),
463 luamethod(LuaVoxelManip, calc_lighting),
464 luamethod(LuaVoxelManip, set_lighting),
465 luamethod(LuaVoxelManip, get_light_data),
466 luamethod(LuaVoxelManip, set_light_data),
467 luamethod(LuaVoxelManip, get_param2_data),
468 luamethod(LuaVoxelManip, set_param2_data),
469 luamethod(LuaVoxelManip, was_modified),
470 luamethod(LuaVoxelManip, get_emerged_area),