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"
25 #include "common/c_packer.h"
27 #include "environment.h"
31 #include "mapgen/mapgen.h"
32 #include "voxelalgorithms.h"
35 int LuaVoxelManip::gc_object(lua_State *L)
37 LuaVoxelManip *o = *(LuaVoxelManip **)(lua_touserdata(L, 1));
43 int LuaVoxelManip::l_read_from_map(lua_State *L)
47 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
52 v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 2));
53 v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 3));
54 sortBoxVerticies(bp1, bp2);
56 vm->initialEmerge(bp1, bp2);
58 push_v3s16(L, vm->m_area.MinEdge);
59 push_v3s16(L, vm->m_area.MaxEdge);
64 int LuaVoxelManip::l_get_data(lua_State *L)
68 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
69 bool use_buffer = lua_istable(L, 2);
73 u32 volume = vm->m_area.getVolume();
78 lua_createtable(L, volume, 0);
80 for (u32 i = 0; i != volume; i++) {
81 lua_Integer cid = vm->m_data[i].getContent();
82 lua_pushinteger(L, cid);
83 lua_rawseti(L, -2, i + 1);
89 int LuaVoxelManip::l_set_data(lua_State *L)
93 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
96 if (!lua_istable(L, 2))
97 throw LuaError("VoxelManip:set_data called with missing parameter");
99 u32 volume = vm->m_area.getVolume();
100 for (u32 i = 0; i != volume; i++) {
101 lua_rawgeti(L, 2, i + 1);
102 content_t c = lua_tointeger(L, -1);
104 vm->m_data[i].setContent(c);
112 int LuaVoxelManip::l_write_to_map(lua_State *L)
116 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
117 bool update_light = !lua_isboolean(L, 2) || readParam<bool>(L, 2);
120 ServerMap *map = &(env->getServerMap());
122 std::map<v3s16, MapBlock*> modified_blocks;
123 if (o->is_mapgen_vm || !update_light) {
124 o->vm->blitBackAll(&modified_blocks);
126 voxalgo::blit_back_with_light(map, o->vm, &modified_blocks);
130 event.type = MEET_OTHER;
131 for (const auto &it : modified_blocks)
132 event.modified_blocks.insert(it.first);
133 map->dispatchEvent(event);
138 int LuaVoxelManip::l_get_node_at(lua_State *L)
140 NO_MAP_LOCK_REQUIRED;
142 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
143 v3s16 pos = check_v3s16(L, 2);
145 pushnode(L, o->vm->getNodeNoExNoEmerge(pos));
149 int LuaVoxelManip::l_set_node_at(lua_State *L)
151 NO_MAP_LOCK_REQUIRED;
153 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
154 v3s16 pos = check_v3s16(L, 2);
155 MapNode n = readnode(L, 3);
157 o->vm->setNodeNoEmerge(pos, n);
162 int LuaVoxelManip::l_update_liquids(lua_State *L)
166 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
168 ServerMap *map = &(env->getServerMap());
169 const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
170 MMVManip *vm = o->vm;
176 mg.updateLiquid(&map->m_transforming_liquid,
177 vm->m_area.MinEdge, vm->m_area.MaxEdge);
182 int LuaVoxelManip::l_calc_lighting(lua_State *L)
184 NO_MAP_LOCK_REQUIRED;
186 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
187 if (!o->is_mapgen_vm) {
188 warningstream << "VoxelManip:calc_lighting called for a non-mapgen "
189 "VoxelManip object" << std::endl;
193 const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
194 EmergeManager *emerge = getServer(L)->getEmergeManager();
195 MMVManip *vm = o->vm;
197 v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE;
198 v3s16 fpmin = vm->m_area.MinEdge;
199 v3s16 fpmax = vm->m_area.MaxEdge;
200 v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) : fpmin + yblock;
201 v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) : fpmax - yblock;
202 bool propagate_shadow = !lua_isboolean(L, 4) || readParam<bool>(L, 4);
204 sortBoxVerticies(pmin, pmax);
205 if (!vm->m_area.contains(VoxelArea(pmin, pmax)))
206 throw LuaError("Specified voxel area out of VoxelManipulator bounds");
211 mg.water_level = emerge->mgparams->water_level;
213 mg.calcLighting(pmin, pmax, fpmin, fpmax, propagate_shadow);
218 int LuaVoxelManip::l_set_lighting(lua_State *L)
220 NO_MAP_LOCK_REQUIRED;
222 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
223 if (!o->is_mapgen_vm) {
224 warningstream << "VoxelManip:set_lighting called for a non-mapgen "
225 "VoxelManip object" << std::endl;
229 if (!lua_istable(L, 2))
230 throw LuaError("VoxelManip:set_lighting called with missing parameter");
233 light = (getintfield_default(L, 2, "day", 0) & 0x0F);
234 light |= (getintfield_default(L, 2, "night", 0) & 0x0F) << 4;
236 MMVManip *vm = o->vm;
238 v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE;
239 v3s16 pmin = lua_istable(L, 3) ? check_v3s16(L, 3) : vm->m_area.MinEdge + yblock;
240 v3s16 pmax = lua_istable(L, 4) ? check_v3s16(L, 4) : vm->m_area.MaxEdge - yblock;
242 sortBoxVerticies(pmin, pmax);
243 if (!vm->m_area.contains(VoxelArea(pmin, pmax)))
244 throw LuaError("Specified voxel area out of VoxelManipulator bounds");
249 mg.setLighting(light, pmin, pmax);
254 int LuaVoxelManip::l_get_light_data(lua_State *L)
256 NO_MAP_LOCK_REQUIRED;
258 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
259 bool use_buffer = lua_istable(L, 2);
261 MMVManip *vm = o->vm;
263 u32 volume = vm->m_area.getVolume();
268 lua_createtable(L, volume, 0);
270 for (u32 i = 0; i != volume; i++) {
271 lua_Integer light = vm->m_data[i].param1;
272 lua_pushinteger(L, light);
273 lua_rawseti(L, -2, i + 1);
279 int LuaVoxelManip::l_set_light_data(lua_State *L)
281 NO_MAP_LOCK_REQUIRED;
283 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
284 MMVManip *vm = o->vm;
286 if (!lua_istable(L, 2))
287 throw LuaError("VoxelManip:set_light_data called with missing "
290 u32 volume = vm->m_area.getVolume();
291 for (u32 i = 0; i != volume; i++) {
292 lua_rawgeti(L, 2, i + 1);
293 u8 light = lua_tointeger(L, -1);
295 vm->m_data[i].param1 = light;
303 int LuaVoxelManip::l_get_param2_data(lua_State *L)
305 NO_MAP_LOCK_REQUIRED;
307 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
308 bool use_buffer = lua_istable(L, 2);
310 MMVManip *vm = o->vm;
312 u32 volume = vm->m_area.getVolume();
317 lua_createtable(L, volume, 0);
319 for (u32 i = 0; i != volume; i++) {
320 lua_Integer param2 = vm->m_data[i].param2;
321 lua_pushinteger(L, param2);
322 lua_rawseti(L, -2, i + 1);
328 int LuaVoxelManip::l_set_param2_data(lua_State *L)
330 NO_MAP_LOCK_REQUIRED;
332 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
333 MMVManip *vm = o->vm;
335 if (!lua_istable(L, 2))
336 throw LuaError("VoxelManip:set_param2_data called with missing "
339 u32 volume = vm->m_area.getVolume();
340 for (u32 i = 0; i != volume; i++) {
341 lua_rawgeti(L, 2, i + 1);
342 u8 param2 = lua_tointeger(L, -1);
344 vm->m_data[i].param2 = param2;
352 int LuaVoxelManip::l_update_map(lua_State *L)
357 int LuaVoxelManip::l_was_modified(lua_State *L)
359 NO_MAP_LOCK_REQUIRED;
361 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
362 MMVManip *vm = o->vm;
364 lua_pushboolean(L, vm->m_is_dirty);
369 int LuaVoxelManip::l_get_emerged_area(lua_State *L)
371 NO_MAP_LOCK_REQUIRED;
373 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
375 push_v3s16(L, o->vm->m_area.MinEdge);
376 push_v3s16(L, o->vm->m_area.MaxEdge);
381 LuaVoxelManip::LuaVoxelManip(MMVManip *mmvm, bool is_mg_vm) :
382 is_mapgen_vm(is_mg_vm),
387 LuaVoxelManip::LuaVoxelManip(Map *map) : vm(new MMVManip(map))
391 LuaVoxelManip::LuaVoxelManip(Map *map, v3s16 p1, v3s16 p2)
393 vm = new MMVManip(map);
395 v3s16 bp1 = getNodeBlockPos(p1);
396 v3s16 bp2 = getNodeBlockPos(p2);
397 sortBoxVerticies(bp1, bp2);
398 vm->initialEmerge(bp1, bp2);
401 LuaVoxelManip::~LuaVoxelManip()
408 // Creates an LuaVoxelManip and leaves it on top of stack
409 int LuaVoxelManip::create_object(lua_State *L)
413 Map *map = &(env->getMap());
414 LuaVoxelManip *o = (lua_istable(L, 1) && lua_istable(L, 2)) ?
415 new LuaVoxelManip(map, check_v3s16(L, 1), check_v3s16(L, 2)) :
416 new LuaVoxelManip(map);
418 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
419 luaL_getmetatable(L, className);
420 lua_setmetatable(L, -2);
424 void *LuaVoxelManip::packIn(lua_State *L, int idx)
426 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, idx);
429 throw LuaError("nope");
430 return o->vm->clone();
433 void LuaVoxelManip::packOut(lua_State *L, void *ptr)
435 MMVManip *vm = reinterpret_cast<MMVManip*>(ptr);
441 // Associate vmanip with map if the Lua env has one
442 Environment *env = getEnv(L);
444 vm->reparent(&(env->getMap()));
446 LuaVoxelManip *o = new LuaVoxelManip(vm, false);
447 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
448 luaL_getmetatable(L, className);
449 lua_setmetatable(L, -2);
452 void LuaVoxelManip::Register(lua_State *L)
454 static const luaL_Reg metamethods[] = {
458 registerClass(L, className, methods, metamethods);
460 // Can be created from Lua (VoxelManip())
461 lua_register(L, className, create_object);
463 script_register_packer(L, className, packIn, packOut);
466 const char LuaVoxelManip::className[] = "VoxelManip";
467 const luaL_Reg LuaVoxelManip::methods[] = {
468 luamethod(LuaVoxelManip, read_from_map),
469 luamethod(LuaVoxelManip, get_data),
470 luamethod(LuaVoxelManip, set_data),
471 luamethod(LuaVoxelManip, get_node_at),
472 luamethod(LuaVoxelManip, set_node_at),
473 luamethod(LuaVoxelManip, write_to_map),
474 luamethod(LuaVoxelManip, update_map),
475 luamethod(LuaVoxelManip, update_liquids),
476 luamethod(LuaVoxelManip, calc_lighting),
477 luamethod(LuaVoxelManip, set_lighting),
478 luamethod(LuaVoxelManip, get_light_data),
479 luamethod(LuaVoxelManip, set_light_data),
480 luamethod(LuaVoxelManip, get_param2_data),
481 luamethod(LuaVoxelManip, set_param2_data),
482 luamethod(LuaVoxelManip, was_modified),
483 luamethod(LuaVoxelManip, get_emerged_area),