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 event.setModifiedBlocks(modified_blocks);
132 map->dispatchEvent(event);
137 int LuaVoxelManip::l_get_node_at(lua_State *L)
139 NO_MAP_LOCK_REQUIRED;
141 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
142 v3s16 pos = check_v3s16(L, 2);
144 pushnode(L, o->vm->getNodeNoExNoEmerge(pos));
148 int LuaVoxelManip::l_set_node_at(lua_State *L)
150 NO_MAP_LOCK_REQUIRED;
152 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
153 v3s16 pos = check_v3s16(L, 2);
154 MapNode n = readnode(L, 3);
156 o->vm->setNodeNoEmerge(pos, n);
161 int LuaVoxelManip::l_update_liquids(lua_State *L)
165 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
167 ServerMap *map = &(env->getServerMap());
168 const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
169 MMVManip *vm = o->vm;
175 mg.updateLiquid(&map->m_transforming_liquid,
176 vm->m_area.MinEdge, vm->m_area.MaxEdge);
181 int LuaVoxelManip::l_calc_lighting(lua_State *L)
183 NO_MAP_LOCK_REQUIRED;
185 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
186 if (!o->is_mapgen_vm) {
187 warningstream << "VoxelManip:calc_lighting called for a non-mapgen "
188 "VoxelManip object" << std::endl;
192 const NodeDefManager *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) || readParam<bool>(L, 4);
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<LuaVoxelManip>(L, 1);
222 if (!o->is_mapgen_vm) {
223 warningstream << "VoxelManip:set_lighting called for a non-mapgen "
224 "VoxelManip object" << std::endl;
228 if (!lua_istable(L, 2))
229 throw LuaError("VoxelManip:set_lighting called with missing parameter");
232 light = (getintfield_default(L, 2, "day", 0) & 0x0F);
233 light |= (getintfield_default(L, 2, "night", 0) & 0x0F) << 4;
235 MMVManip *vm = o->vm;
237 v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE;
238 v3s16 pmin = lua_istable(L, 3) ? check_v3s16(L, 3) : vm->m_area.MinEdge + yblock;
239 v3s16 pmax = lua_istable(L, 4) ? check_v3s16(L, 4) : vm->m_area.MaxEdge - yblock;
241 sortBoxVerticies(pmin, pmax);
242 if (!vm->m_area.contains(VoxelArea(pmin, pmax)))
243 throw LuaError("Specified voxel area out of VoxelManipulator bounds");
248 mg.setLighting(light, pmin, pmax);
253 int LuaVoxelManip::l_get_light_data(lua_State *L)
255 NO_MAP_LOCK_REQUIRED;
257 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
258 bool use_buffer = lua_istable(L, 2);
260 MMVManip *vm = o->vm;
262 u32 volume = vm->m_area.getVolume();
267 lua_createtable(L, volume, 0);
269 for (u32 i = 0; i != volume; i++) {
270 lua_Integer light = vm->m_data[i].param1;
271 lua_pushinteger(L, light);
272 lua_rawseti(L, -2, i + 1);
278 int LuaVoxelManip::l_set_light_data(lua_State *L)
280 NO_MAP_LOCK_REQUIRED;
282 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
283 MMVManip *vm = o->vm;
285 if (!lua_istable(L, 2))
286 throw LuaError("VoxelManip:set_light_data called with missing "
289 u32 volume = vm->m_area.getVolume();
290 for (u32 i = 0; i != volume; i++) {
291 lua_rawgeti(L, 2, i + 1);
292 u8 light = lua_tointeger(L, -1);
294 vm->m_data[i].param1 = light;
302 int LuaVoxelManip::l_get_param2_data(lua_State *L)
304 NO_MAP_LOCK_REQUIRED;
306 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
307 bool use_buffer = lua_istable(L, 2);
309 MMVManip *vm = o->vm;
311 u32 volume = vm->m_area.getVolume();
316 lua_createtable(L, volume, 0);
318 for (u32 i = 0; i != volume; i++) {
319 lua_Integer param2 = vm->m_data[i].param2;
320 lua_pushinteger(L, param2);
321 lua_rawseti(L, -2, i + 1);
327 int LuaVoxelManip::l_set_param2_data(lua_State *L)
329 NO_MAP_LOCK_REQUIRED;
331 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
332 MMVManip *vm = o->vm;
334 if (!lua_istable(L, 2))
335 throw LuaError("VoxelManip:set_param2_data called with missing "
338 u32 volume = vm->m_area.getVolume();
339 for (u32 i = 0; i != volume; i++) {
340 lua_rawgeti(L, 2, i + 1);
341 u8 param2 = lua_tointeger(L, -1);
343 vm->m_data[i].param2 = param2;
351 int LuaVoxelManip::l_update_map(lua_State *L)
356 int LuaVoxelManip::l_was_modified(lua_State *L)
358 NO_MAP_LOCK_REQUIRED;
360 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
361 MMVManip *vm = o->vm;
363 lua_pushboolean(L, vm->m_is_dirty);
368 int LuaVoxelManip::l_get_emerged_area(lua_State *L)
370 NO_MAP_LOCK_REQUIRED;
372 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
374 push_v3s16(L, o->vm->m_area.MinEdge);
375 push_v3s16(L, o->vm->m_area.MaxEdge);
380 LuaVoxelManip::LuaVoxelManip(MMVManip *mmvm, bool is_mg_vm) :
381 is_mapgen_vm(is_mg_vm),
386 LuaVoxelManip::LuaVoxelManip(Map *map) : vm(new MMVManip(map))
390 LuaVoxelManip::LuaVoxelManip(Map *map, v3s16 p1, v3s16 p2)
392 vm = new MMVManip(map);
394 v3s16 bp1 = getNodeBlockPos(p1);
395 v3s16 bp2 = getNodeBlockPos(p2);
396 sortBoxVerticies(bp1, bp2);
397 vm->initialEmerge(bp1, bp2);
400 LuaVoxelManip::~LuaVoxelManip()
407 // Creates an LuaVoxelManip and leaves it on top of stack
408 int LuaVoxelManip::create_object(lua_State *L)
412 Map *map = &(env->getMap());
413 LuaVoxelManip *o = (lua_istable(L, 1) && lua_istable(L, 2)) ?
414 new LuaVoxelManip(map, check_v3s16(L, 1), check_v3s16(L, 2)) :
415 new LuaVoxelManip(map);
417 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
418 luaL_getmetatable(L, className);
419 lua_setmetatable(L, -2);
423 void *LuaVoxelManip::packIn(lua_State *L, int idx)
425 LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, idx);
428 throw LuaError("nope");
429 return o->vm->clone();
432 void LuaVoxelManip::packOut(lua_State *L, void *ptr)
434 MMVManip *vm = reinterpret_cast<MMVManip*>(ptr);
440 // Associate vmanip with map if the Lua env has one
441 Environment *env = getEnv(L);
443 vm->reparent(&(env->getMap()));
445 LuaVoxelManip *o = new LuaVoxelManip(vm, false);
446 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
447 luaL_getmetatable(L, className);
448 lua_setmetatable(L, -2);
451 void LuaVoxelManip::Register(lua_State *L)
453 static const luaL_Reg metamethods[] = {
457 registerClass(L, className, methods, metamethods);
459 // Can be created from Lua (VoxelManip())
460 lua_register(L, className, create_object);
462 script_register_packer(L, className, packIn, packOut);
465 const char LuaVoxelManip::className[] = "VoxelManip";
466 const luaL_Reg LuaVoxelManip::methods[] = {
467 luamethod(LuaVoxelManip, read_from_map),
468 luamethod(LuaVoxelManip, get_data),
469 luamethod(LuaVoxelManip, set_data),
470 luamethod(LuaVoxelManip, get_node_at),
471 luamethod(LuaVoxelManip, set_node_at),
472 luamethod(LuaVoxelManip, write_to_map),
473 luamethod(LuaVoxelManip, update_map),
474 luamethod(LuaVoxelManip, update_liquids),
475 luamethod(LuaVoxelManip, calc_lighting),
476 luamethod(LuaVoxelManip, set_lighting),
477 luamethod(LuaVoxelManip, get_light_data),
478 luamethod(LuaVoxelManip, set_light_data),
479 luamethod(LuaVoxelManip, get_param2_data),
480 luamethod(LuaVoxelManip, set_param2_data),
481 luamethod(LuaVoxelManip, was_modified),
482 luamethod(LuaVoxelManip, get_emerged_area),