X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fscript%2Flua_api%2Fl_vmanip.cpp;h=6187a47db2c2b238605702201e021c5d2d96a6cc;hb=e7659883cc6fca343785da2a1af3890ae273abbf;hp=6743f40f9c97911c0cbac2ea85d879e2b85ef39b;hpb=8aa930f28e69f3518831500022988ca2a4b6985d;p=minetest.git diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp index 6743f40f9..6187a47db 100644 --- a/src/script/lua_api/l_vmanip.cpp +++ b/src/script/lua_api/l_vmanip.cpp @@ -17,86 +17,161 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "lua_api/l_base.h" +#include #include "lua_api/l_vmanip.h" - -/////// - -#include "cpp_api/scriptapi.h" +#include "lua_api/l_internal.h" +#include "common/c_content.h" #include "common/c_converter.h" -#include "server.h" +#include "common/c_packer.h" #include "emerge.h" -#include "common/c_internal.h" +#include "environment.h" +#include "map.h" +#include "mapblock.h" +#include "server.h" +#include "mapgen/mapgen.h" +#include "voxelalgorithms.h" // garbage collector int LuaVoxelManip::gc_object(lua_State *L) { LuaVoxelManip *o = *(LuaVoxelManip **)(lua_touserdata(L, 1)); - if (o->do_gc) - delete o; - + delete o; + return 0; } -int LuaVoxelManip::l_read_chunk(lua_State *L) +int LuaVoxelManip::l_read_from_map(lua_State *L) { + MAP_LOCK_REQUIRED; + LuaVoxelManip *o = checkobject(L, 1); - - v3s16 bp1 = getNodeBlockPos(read_v3s16(L, 2)); - v3s16 bp2 = getNodeBlockPos(read_v3s16(L, 3)); + MMVManip *vm = o->vm; + if (vm->isOrphan()) + return 0; + + v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 2)); + v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 3)); sortBoxVerticies(bp1, bp2); - ManualMapVoxelManipulator *vm = o->vm; + vm->initialEmerge(bp1, bp2); - - v3s16 emerged_p1 = vm->m_area.MinEdge; - v3s16 emerged_p2 = vm->m_area.MaxEdge; - - int volume = vm->m_area.getVolume(); - - lua_newtable(L); - for (int i = 0; i != volume; i++) { - lua_Number cid = vm->m_data[i].getContent(); - lua_pushnumber(L, cid); + + push_v3s16(L, vm->m_area.MinEdge); + push_v3s16(L, vm->m_area.MaxEdge); + + return 2; +} + +int LuaVoxelManip::l_get_data(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + LuaVoxelManip *o = checkobject(L, 1); + bool use_buffer = lua_istable(L, 2); + + MMVManip *vm = o->vm; + + u32 volume = vm->m_area.getVolume(); + + if (use_buffer) + lua_pushvalue(L, 2); + else + lua_createtable(L, volume, 0); + + for (u32 i = 0; i != volume; i++) { + lua_Integer cid = vm->m_data[i].getContent(); + lua_pushinteger(L, cid); lua_rawseti(L, -2, i + 1); } - - push_v3s16(L, emerged_p1); - push_v3s16(L, emerged_p2); - - return 3; + + return 1; } -int LuaVoxelManip::l_write_chunk(lua_State *L) +int LuaVoxelManip::l_set_data(lua_State *L) { + NO_MAP_LOCK_REQUIRED; + LuaVoxelManip *o = checkobject(L, 1); + MMVManip *vm = o->vm; + if (!lua_istable(L, 2)) - return 0; - - ManualMapVoxelManipulator *vm = o->vm; - - int volume = vm->m_area.getVolume(); - for (int i = 0; i != volume; i++) { + throw LuaError("VoxelManip:set_data called with missing parameter"); + + u32 volume = vm->m_area.getVolume(); + for (u32 i = 0; i != volume; i++) { lua_rawgeti(L, 2, i + 1); - content_t c = lua_tonumber(L, -1); - + content_t c = lua_tointeger(L, -1); + vm->m_data[i].setContent(c); lua_pop(L, 1); } - vm->blitBackAll(&o->modified_blocks); - + return 0; +} + +int LuaVoxelManip::l_write_to_map(lua_State *L) +{ + MAP_LOCK_REQUIRED; + + LuaVoxelManip *o = checkobject(L, 1); + bool update_light = !lua_isboolean(L, 2) || readParam(L, 2); + + GET_ENV_PTR; + ServerMap *map = &(env->getServerMap()); + + std::map modified_blocks; + if (o->is_mapgen_vm || !update_light) { + o->vm->blitBackAll(&modified_blocks); + } else { + voxalgo::blit_back_with_light(map, o->vm, &modified_blocks); + } + + MapEditEvent event; + event.type = MEET_OTHER; + for (const auto &it : modified_blocks) + event.modified_blocks.insert(it.first); + map->dispatchEvent(event); + + return 0; +} + +int LuaVoxelManip::l_get_node_at(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + const NodeDefManager *ndef = getServer(L)->getNodeDefManager(); + + LuaVoxelManip *o = checkobject(L, 1); + v3s16 pos = check_v3s16(L, 2); + + pushnode(L, o->vm->getNodeNoExNoEmerge(pos), ndef); + return 1; +} + +int LuaVoxelManip::l_set_node_at(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + const NodeDefManager *ndef = getServer(L)->getNodeDefManager(); + + LuaVoxelManip *o = checkobject(L, 1); + v3s16 pos = check_v3s16(L, 2); + MapNode n = readnode(L, 3, ndef); + + o->vm->setNodeNoEmerge(pos, n); + return 0; } int LuaVoxelManip::l_update_liquids(lua_State *L) { + GET_ENV_PTR; + LuaVoxelManip *o = checkobject(L, 1); - - ManualMapVoxelManipulator *vm = o->vm; - INodeDefManager *ndef = STACK_TO_SERVER(L)->getNodeDefManager(); - Map *map = &(get_scriptapi(L)->getEnv()->getMap()); + + ServerMap *map = &(env->getServerMap()); + const NodeDefManager *ndef = getServer(L)->getNodeDefManager(); + MMVManip *vm = o->vm; Mapgen mg; mg.vm = vm; @@ -111,22 +186,35 @@ int LuaVoxelManip::l_update_liquids(lua_State *L) int LuaVoxelManip::l_calc_lighting(lua_State *L) { NO_MAP_LOCK_REQUIRED; - + LuaVoxelManip *o = checkobject(L, 1); - v3s16 p1 = read_v3s16(L, 2); - v3s16 p2 = read_v3s16(L, 3); - sortBoxVerticies(p1, p2); - - ManualMapVoxelManipulator *vm = o->vm; - INodeDefManager *ndef = STACK_TO_SERVER(L)->getNodeDefManager(); - EmergeManager *emerge = STACK_TO_SERVER(L)->getEmergeManager(); - + if (!o->is_mapgen_vm) { + warningstream << "VoxelManip:calc_lighting called for a non-mapgen " + "VoxelManip object" << std::endl; + return 0; + } + + const NodeDefManager *ndef = getServer(L)->getNodeDefManager(); + EmergeManager *emerge = getServer(L)->getEmergeManager(); + MMVManip *vm = o->vm; + + v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE; + v3s16 fpmin = vm->m_area.MinEdge; + v3s16 fpmax = vm->m_area.MaxEdge; + v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) : fpmin + yblock; + v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) : fpmax - yblock; + bool propagate_shadow = !lua_isboolean(L, 4) || readParam(L, 4); + + sortBoxVerticies(pmin, pmax); + if (!vm->m_area.contains(VoxelArea(pmin, pmax))) + throw LuaError("Specified voxel area out of VoxelManipulator bounds"); + Mapgen mg; mg.vm = vm; mg.ndef = ndef; - mg.water_level = emerge->params->water_level; - - mg.calcLighting(p1, p2); + mg.water_level = emerge->mgparams->water_level; + + mg.calcLighting(pmin, pmax, fpmin, fpmax, propagate_shadow); return 0; } @@ -134,81 +222,197 @@ int LuaVoxelManip::l_calc_lighting(lua_State *L) int LuaVoxelManip::l_set_lighting(lua_State *L) { NO_MAP_LOCK_REQUIRED; - + LuaVoxelManip *o = checkobject(L, 1); - v3s16 p1 = read_v3s16(L, 2); - v3s16 p2 = read_v3s16(L, 3); - sortBoxVerticies(p1, p2); - - u8 light; - if (!lua_istable(L, 4)) + if (!o->is_mapgen_vm) { + warningstream << "VoxelManip:set_lighting called for a non-mapgen " + "VoxelManip object" << std::endl; return 0; + } + + if (!lua_istable(L, 2)) + throw LuaError("VoxelManip:set_lighting called with missing parameter"); + + u8 light; + light = (getintfield_default(L, 2, "day", 0) & 0x0F); + light |= (getintfield_default(L, 2, "night", 0) & 0x0F) << 4; + + MMVManip *vm = o->vm; + + v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE; + v3s16 pmin = lua_istable(L, 3) ? check_v3s16(L, 3) : vm->m_area.MinEdge + yblock; + v3s16 pmax = lua_istable(L, 4) ? check_v3s16(L, 4) : vm->m_area.MaxEdge - yblock; + + sortBoxVerticies(pmin, pmax); + if (!vm->m_area.contains(VoxelArea(pmin, pmax))) + throw LuaError("Specified voxel area out of VoxelManipulator bounds"); - light = getintfield_default(L, 4, "day", 0); - light |= getintfield_default(L, 4, "night", 0); - - ManualMapVoxelManipulator *vm = o->vm; - Mapgen mg; mg.vm = vm; - - mg.setLighting(p1, p2, light); + + mg.setLighting(light, pmin, pmax); + + return 0; +} + +int LuaVoxelManip::l_get_light_data(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + LuaVoxelManip *o = checkobject(L, 1); + MMVManip *vm = o->vm; + + u32 volume = vm->m_area.getVolume(); + + lua_createtable(L, volume, 0); + for (u32 i = 0; i != volume; i++) { + lua_Integer light = vm->m_data[i].param1; + lua_pushinteger(L, light); + lua_rawseti(L, -2, i + 1); + } + + return 1; +} + +int LuaVoxelManip::l_set_light_data(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + LuaVoxelManip *o = checkobject(L, 1); + MMVManip *vm = o->vm; + + if (!lua_istable(L, 2)) + throw LuaError("VoxelManip:set_light_data called with missing " + "parameter"); + + u32 volume = vm->m_area.getVolume(); + for (u32 i = 0; i != volume; i++) { + lua_rawgeti(L, 2, i + 1); + u8 light = lua_tointeger(L, -1); + + vm->m_data[i].param1 = light; + + lua_pop(L, 1); + } + + return 0; +} + +int LuaVoxelManip::l_get_param2_data(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + LuaVoxelManip *o = checkobject(L, 1); + bool use_buffer = lua_istable(L, 2); + + MMVManip *vm = o->vm; + + u32 volume = vm->m_area.getVolume(); + + if (use_buffer) + lua_pushvalue(L, 2); + else + lua_createtable(L, volume, 0); + + for (u32 i = 0; i != volume; i++) { + lua_Integer param2 = vm->m_data[i].param2; + lua_pushinteger(L, param2); + lua_rawseti(L, -2, i + 1); + } + + return 1; +} + +int LuaVoxelManip::l_set_param2_data(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + LuaVoxelManip *o = checkobject(L, 1); + MMVManip *vm = o->vm; + + if (!lua_istable(L, 2)) + throw LuaError("VoxelManip:set_param2_data called with missing " + "parameter"); + + u32 volume = vm->m_area.getVolume(); + for (u32 i = 0; i != volume; i++) { + lua_rawgeti(L, 2, i + 1); + u8 param2 = lua_tointeger(L, -1); + + vm->m_data[i].param2 = param2; + + lua_pop(L, 1); + } return 0; } int LuaVoxelManip::l_update_map(lua_State *L) { + return 0; +} + +int LuaVoxelManip::l_was_modified(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaVoxelManip *o = checkobject(L, 1); - - // TODO: Optimize this by using Mapgen::calcLighting() instead - std::map lighting_mblocks; - std::map *mblocks = &o->modified_blocks; - - lighting_mblocks.insert(mblocks->begin(), mblocks->end()); - - Map *map = &(get_scriptapi(L)->getEnv()->getMap()); - map->updateLighting(lighting_mblocks, *mblocks); + MMVManip *vm = o->vm; - MapEditEvent event; - event.type = MEET_OTHER; - for (std::map::iterator - it = mblocks->begin(); - it != mblocks->end(); ++it) - event.modified_blocks.insert(it->first); - - map->dispatchEvent(&event); + lua_pushboolean(L, vm->m_is_dirty); - mblocks->clear(); + return 1; +} + +int LuaVoxelManip::l_get_emerged_area(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; - return 0; + LuaVoxelManip *o = checkobject(L, 1); + + push_v3s16(L, o->vm->m_area.MinEdge); + push_v3s16(L, o->vm->m_area.MaxEdge); + + return 2; +} + +LuaVoxelManip::LuaVoxelManip(MMVManip *mmvm, bool is_mg_vm) : + is_mapgen_vm(is_mg_vm), + vm(mmvm) +{ } -LuaVoxelManip::LuaVoxelManip(ManualMapVoxelManipulator *mmvm, bool dogc) +LuaVoxelManip::LuaVoxelManip(Map *map) : vm(new MMVManip(map)) { - this->vm = mmvm; - this->do_gc = dogc; } -LuaVoxelManip::LuaVoxelManip(Map *map) +LuaVoxelManip::LuaVoxelManip(Map *map, v3s16 p1, v3s16 p2) { - vm = new ManualMapVoxelManipulator(map); + vm = new MMVManip(map); + + v3s16 bp1 = getNodeBlockPos(p1); + v3s16 bp2 = getNodeBlockPos(p2); + sortBoxVerticies(bp1, bp2); + vm->initialEmerge(bp1, bp2); } LuaVoxelManip::~LuaVoxelManip() { - delete vm; + if (!is_mapgen_vm) + delete vm; } // LuaVoxelManip() // Creates an LuaVoxelManip and leaves it on top of stack int LuaVoxelManip::create_object(lua_State *L) { - NO_MAP_LOCK_REQUIRED; - - Map *map = &(get_scriptapi(L)->getEnv()->getMap()); - LuaVoxelManip *o = new LuaVoxelManip(map); - + GET_ENV_PTR; + + Map *map = &(env->getMap()); + LuaVoxelManip *o = (lua_istable(L, 1) && lua_istable(L, 2)) ? + new LuaVoxelManip(map, check_v3s16(L, 1), check_v3s16(L, 2)) : + new LuaVoxelManip(map); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; luaL_getmetatable(L, className); lua_setmetatable(L, -2); @@ -218,16 +422,44 @@ int LuaVoxelManip::create_object(lua_State *L) LuaVoxelManip *LuaVoxelManip::checkobject(lua_State *L, int narg) { NO_MAP_LOCK_REQUIRED; - + luaL_checktype(L, narg, LUA_TUSERDATA); void *ud = luaL_checkudata(L, narg, className); if (!ud) luaL_typerror(L, narg, className); - + return *(LuaVoxelManip **)ud; // unbox pointer } +void *LuaVoxelManip::packIn(lua_State *L, int idx) +{ + LuaVoxelManip *o = checkobject(L, idx); + + if (o->is_mapgen_vm) + throw LuaError("nope"); + return o->vm->clone(); +} + +void LuaVoxelManip::packOut(lua_State *L, void *ptr) +{ + MMVManip *vm = reinterpret_cast(ptr); + if (!L) { + delete vm; + return; + } + + // Associate vmanip with map if the Lua env has one + Environment *env = getEnv(L); + if (env) + vm->reparent(&(env->getMap())); + + LuaVoxelManip *o = new LuaVoxelManip(vm, false); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); +} + void LuaVoxelManip::Register(lua_State *L) { lua_newtable(L); @@ -249,22 +481,32 @@ void LuaVoxelManip::Register(lua_State *L) lua_pop(L, 1); // drop metatable - luaL_openlib(L, 0, methods, 0); // fill methodtable + luaL_register(L, nullptr, methods); // fill methodtable lua_pop(L, 1); // drop methodtable - // Can be created from Lua (VoxelManip() + // Can be created from Lua (VoxelManip()) lua_register(L, className, create_object); + + script_register_packer(L, className, packIn, packOut); } const char LuaVoxelManip::className[] = "VoxelManip"; -const luaL_reg LuaVoxelManip::methods[] = { - luamethod(LuaVoxelManip, read_chunk), - luamethod(LuaVoxelManip, write_chunk), +const luaL_Reg LuaVoxelManip::methods[] = { + luamethod(LuaVoxelManip, read_from_map), + luamethod(LuaVoxelManip, get_data), + luamethod(LuaVoxelManip, set_data), + luamethod(LuaVoxelManip, get_node_at), + luamethod(LuaVoxelManip, set_node_at), + luamethod(LuaVoxelManip, write_to_map), luamethod(LuaVoxelManip, update_map), luamethod(LuaVoxelManip, update_liquids), luamethod(LuaVoxelManip, calc_lighting), luamethod(LuaVoxelManip, set_lighting), + luamethod(LuaVoxelManip, get_light_data), + luamethod(LuaVoxelManip, set_light_data), + luamethod(LuaVoxelManip, get_param2_data), + luamethod(LuaVoxelManip, set_param2_data), + luamethod(LuaVoxelManip, was_modified), + luamethod(LuaVoxelManip, get_emerged_area), {0,0} }; - -REGISTER_LUA_REF(LuaVoxelManip);