// create_schematic(p1, p2, probability_list, filename, y_slice_prob_list) int ModApiMapgen::l_create_schematic(lua_State *L) { INodeDefManager *ndef = getServer(L)->getNodeDefManager(); const char *filename = luaL_checkstring(L, 4); CHECK_SECURE_PATH_OPTIONAL(L, filename); Map *map = &(getEnv(L)->getMap()); Schematic schem; v3s16 p1 = check_v3s16(L, 1); v3s16 p2 = check_v3s16(L, 2); sortBoxVerticies(p1, p2); std::vector<std::pair<v3s16, u8> > prob_list; if (lua_istable(L, 3)) { lua_pushnil(L); while (lua_next(L, 3)) { if (lua_istable(L, -1)) { lua_getfield(L, -1, "pos"); v3s16 pos = check_v3s16(L, -1); lua_pop(L, 1); u8 prob = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS); prob_list.push_back(std::make_pair(pos, prob)); } lua_pop(L, 1); } } std::vector<std::pair<s16, u8> > slice_prob_list; if (lua_istable(L, 5)) { lua_pushnil(L); while (lua_next(L, 5)) { if (lua_istable(L, -1)) { s16 ypos = getintfield_default(L, -1, "ypos", 0); u8 prob = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS); slice_prob_list.push_back(std::make_pair(ypos, prob)); } lua_pop(L, 1); } } if (!schem.getSchematicFromMap(map, p1, p2)) { errorstream << "create_schematic: failed to get schematic " "from map" << std::endl; return 0; } schem.applyProbabilities(p1, &prob_list, &slice_prob_list); schem.saveSchematicToFile(filename, ndef); actionstream << "create_schematic: saved schematic file '" << filename << "'." << std::endl; lua_pushboolean(L, true); return 1; }
// delete_area(p1, p2) // delete mapblocks in area p1..p2 int ModApiEnvMod::l_delete_area(lua_State *L) { GET_ENV_PTR; v3s16 bpmin = getNodeBlockPos(read_v3s16(L, 1)); v3s16 bpmax = getNodeBlockPos(read_v3s16(L, 2)); sortBoxVerticies(bpmin, bpmax); ServerMap &map = env->getServerMap(); MapEditEvent event; event.type = MEET_OTHER; bool success = true; for (s16 z = bpmin.Z; z <= bpmax.Z; z++) for (s16 y = bpmin.Y; y <= bpmax.Y; y++) for (s16 x = bpmin.X; x <= bpmax.X; x++) { v3s16 bp(x, y, z); if (map.deleteBlock(bp)) { env->setStaticForActiveObjectsInBlock(bp, false); event.modified_blocks.insert(bp); } else { success = false; } } map.dispatchEvent(&event); lua_pushboolean(L, success); return 1; }
int LuaVoxelManip::l_set_lighting(lua_State *L) { NO_MAP_LOCK_REQUIRED; LuaVoxelManip *o = checkobject(L, 1); if (!o->is_mapgen_vm) return 0; if (!lua_istable(L, 2)) return 0; 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"); Mapgen mg; mg.vm = vm; mg.setLighting(light, pmin, pmax); return 0; }
int LuaVoxelManip::l_calc_lighting(lua_State *L) { NO_MAP_LOCK_REQUIRED; LuaVoxelManip *o = checkobject(L, 1); if (!o->is_mapgen_vm) return 0; INodeDefManager *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) || lua_toboolean(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->mgparams->water_level; mg.calcLighting(pmin, pmax, fpmin, fpmax, propagate_shadow); return 0; }
// create_schematic(p1, p2, probability_list, filename) int ModApiMapgen::l_create_schematic(lua_State *L) { DecoSchematic dschem; Map *map = &(getEnv(L)->getMap()); INodeDefManager *ndef = getServer(L)->getNodeDefManager(); v3s16 p1 = read_v3s16(L, 1); v3s16 p2 = read_v3s16(L, 2); sortBoxVerticies(p1, p2); std::vector<std::pair<v3s16, u8> > prob_list; if (lua_istable(L, 3)) { lua_pushnil(L); while (lua_next(L, 3)) { if (lua_istable(L, -1)) { lua_getfield(L, -1, "pos"); v3s16 pos = read_v3s16(L, -1); lua_pop(L, 1); u8 prob = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS); prob_list.push_back(std::make_pair(pos, prob)); } lua_pop(L, 1); } } std::vector<std::pair<s16, u8> > slice_prob_list; if (lua_istable(L, 5)) { lua_pushnil(L); while (lua_next(L, 5)) { if (lua_istable(L, -1)) { s16 ypos = getintfield_default(L, -1, "ypos", 0); u8 prob = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS); slice_prob_list.push_back(std::make_pair(ypos, prob)); } lua_pop(L, 1); } } const char *s = lua_tostring(L, 4); dschem.filename = std::string(s ? s : ""); if (!dschem.getSchematicFromMap(map, p1, p2)) { errorstream << "create_schematic: failed to get schematic " "from map" << std::endl; return 0; } dschem.applyProbabilities(p1, &prob_list, &slice_prob_list); dschem.saveSchematicFile(ndef); actionstream << "create_schematic: saved schematic file '" << dschem.filename << "'." << std::endl; return 1; }
// find_nodes_in_area(minp, maxp, nodenames) -> list of positions // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) { GET_ENV_PTR; INodeDefManager *ndef = getServer(L)->ndef(); v3s16 minp = read_v3s16(L, 1); v3s16 maxp = read_v3s16(L, 2); sortBoxVerticies(minp, maxp); v3s16 cube = maxp - minp + 1; /* Limit for too large areas, assume default values * and give tolerances of 1 node on each side * (chunksize * MAP_BLOCKSIZE + 2)^3 = 551368 */ if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 551368) { luaL_error(L, "find_nodes_in_area(): area volume" " exceeds allowed value of 551368"); return 0; } std::set<content_t> filter; if (lua_istable(L, 3)) { lua_pushnil(L); while (lua_next(L, 3) != 0) { // key at index -2 and value at index -1 luaL_checktype(L, -1, LUA_TSTRING); ndef->getIds(lua_tostring(L, -1), filter); // removes value, keeps key for next iteration lua_pop(L, 1); } } else if (lua_isstring(L, 3)) { ndef->getIds(lua_tostring(L, 3), filter); } std::unordered_map<content_t, u32> individual_count; lua_newtable(L); u64 i = 0; for (s16 x = minp.X; x <= maxp.X; x++) for (s16 y = minp.Y; y <= maxp.Y; y++) for (s16 z = minp.Z; z <= maxp.Z; z++) { v3s16 p(x, y, z); content_t c = env->getMap().getNodeNoEx(p).getContent(); if (filter.count(c) != 0) { push_v3s16(L, p); lua_rawseti(L, -2, ++i); individual_count[c]++; } } lua_newtable(L); for (std::set<content_t>::const_iterator it = filter.begin(); it != filter.end(); ++it) { lua_pushnumber(L, individual_count[*it]); lua_setfield(L, -2, ndef->get(*it).name.c_str()); } return 2; }
LuaVoxelManip::LuaVoxelManip(Map *map, v3s16 p1, v3s16 p2) { vm = new MMVManip(map); v3s16 bp1 = getNodeBlockPos(p1); v3s16 bp2 = getNodeBlockPos(p2); sortBoxVerticies(bp1, bp2); vm->initialEmerge(bp1, bp2); }
// create_schematic(p1, p2, probability_list, filename) int ModApiBasic::l_create_schematic(lua_State *L) { DecoSchematic dschem; Map *map = &(getEnv(L)->getMap()); INodeDefManager *ndef = getServer(L)->getNodeDefManager(); v3s16 p1 = read_v3s16(L, 1); v3s16 p2 = read_v3s16(L, 2); sortBoxVerticies(p1, p2); std::vector<std::pair<v3s16, s16> > probability_list; if (lua_istable(L, 3)) { lua_pushnil(L); while (lua_next(L, 3)) { if (lua_istable(L, -1)) { lua_getfield(L, -1, "pos"); v3s16 pos = read_v3s16(L, -1); lua_pop(L, 1); s16 prob = getintfield_default(L, -1, "prob", 0); if (prob < -1 || prob >= UCHAR_MAX) { errorstream << "create_schematic: probability value of " << prob << " at " << PP(pos) << " out of range" << std::endl; } else { probability_list.push_back(std::make_pair(pos, prob)); } } lua_pop(L, 1); } } dschem.filename = std::string(lua_tostring(L, 4)); if (!dschem.getSchematicFromMap(map, p1, p2)) { errorstream << "create_schematic: failed to get schematic " "from map" << std::endl; return 0; } dschem.applyProbabilities(&probability_list, p1); dschem.saveSchematicFile(ndef); actionstream << "create_schematic: saved schematic file '" << dschem.filename << "'." << std::endl; return 1; }
int LuaVoxelManip::l_read_from_map(lua_State *L) { LuaVoxelManip *o = checkobject(L, 1); ManualMapVoxelManipulator *vm = o->vm; v3s16 bp1 = getNodeBlockPos(read_v3s16(L, 2)); v3s16 bp2 = getNodeBlockPos(read_v3s16(L, 3)); sortBoxVerticies(bp1, bp2); vm->initialEmerge(bp1, bp2); push_v3s16(L, vm->m_area.MinEdge); push_v3s16(L, vm->m_area.MaxEdge); return 2; }
int LuaVoxelManip::l_read_from_map(lua_State *L) { MAP_LOCK_REQUIRED; LuaVoxelManip *o = checkobject(L, 1); MMVManip *vm = o->vm; v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 2)); v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 3)); sortBoxVerticies(bp1, bp2); vm->initialEmerge(bp1, bp2); push_v3s16(L, vm->m_area.MinEdge); push_v3s16(L, vm->m_area.MaxEdge); return 2; }
// emerge_area(p1, p2, [callback, context]) // emerge mapblocks in area p1..p2, calls callback with context upon completion int ModApiEnvMod::l_emerge_area(lua_State *L) { GET_ENV_PTR; EmergeCompletionCallback callback = NULL; ScriptCallbackState *state = NULL; EmergeManager *emerge = getServer(L)->getEmergeManager(); v3s16 bpmin = getNodeBlockPos(read_v3s16(L, 1)); v3s16 bpmax = getNodeBlockPos(read_v3s16(L, 2)); sortBoxVerticies(bpmin, bpmax); size_t num_blocks = VoxelArea(bpmin, bpmax).getVolume(); assert(num_blocks != 0); if (lua_isfunction(L, 3)) { callback = LuaEmergeAreaCallback; lua_pushvalue(L, 3); int callback_ref = luaL_ref(L, LUA_REGISTRYINDEX); lua_pushvalue(L, 4); int args_ref = luaL_ref(L, LUA_REGISTRYINDEX); state = new ScriptCallbackState; state->script = getServer(L)->getScriptIface(); state->callback_ref = callback_ref; state->args_ref = args_ref; state->refcount = num_blocks; state->origin = getScriptApiBase(L)->getOrigin(); } for (s16 z = bpmin.Z; z <= bpmax.Z; z++) for (s16 y = bpmin.Y; y <= bpmax.Y; y++) for (s16 x = bpmin.X; x <= bpmax.X; x++) { emerge->enqueueBlockEmergeEx(v3s16(x, y, z), PEER_ID_INEXISTENT, BLOCK_EMERGE_ALLOW_GEN | BLOCK_EMERGE_FORCE_QUEUE, callback, state); } return 0; }
// generate_decorations(vm, p1, p2, [deco_id]) int ModApiMapgen::l_generate_decorations(lua_State *L) { EmergeManager *emerge = getServer(L)->getEmergeManager(); Mapgen mg; mg.seed = emerge->params.seed; mg.vm = LuaVoxelManip::checkobject(L, 1)->vm; mg.ndef = getServer(L)->getNodeDefManager(); v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) : mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE; v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) : mg.vm->m_area.MaxEdge - v3s16(1,1,1) * MAP_BLOCKSIZE; sortBoxVerticies(pmin, pmax); u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed); emerge->decomgr->placeAllDecos(&mg, blockseed, pmin, pmax); return 0; }
// find_nodes_in_area_under_air(minp, maxp, nodenames) -> list of positions // nodenames: e.g. {"ignore", "group:tree"} or "default:dirt" int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L) { /* Note: A similar but generalized (and therefore slower) version of this * function could be created -- e.g. find_nodes_in_area_under -- which * would accept a node name (or ID?) or list of names that the "above node" * should be. * TODO */ GET_ENV_PTR; INodeDefManager *ndef = getServer(L)->ndef(); v3s16 minp = read_v3s16(L, 1); v3s16 maxp = read_v3s16(L, 2); sortBoxVerticies(minp, maxp); v3s16 cube = maxp - minp + 1; /* Limit for too large areas, assume default values * and give tolerances of 1 node on each side * (chunksize * MAP_BLOCKSIZE + 2)^3 = 551368 */ if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 551368) { luaL_error(L, "find_nodes_in_area_under_air(): area volume" " exceeds allowed value of 551368"); return 0; } std::vector<content_t> filter; if (lua_istable(L, 3)) { lua_pushnil(L); while (lua_next(L, 3) != 0) { // key at index -2 and value at index -1 luaL_checktype(L, -1, LUA_TSTRING); ndef->getIds(lua_tostring(L, -1), filter); // removes value, keeps key for next iteration lua_pop(L, 1); } } else if (lua_isstring(L, 3)) { ndef->getIds(lua_tostring(L, 3), filter); } lua_newtable(L); u64 i = 0; for (s16 x = minp.X; x <= maxp.X; x++) for (s16 z = minp.Z; z <= maxp.Z; z++) { s16 y = minp.Y; v3s16 p(x, y, z); content_t c = env->getMap().getNodeNoEx(p).getContent(); for (; y <= maxp.Y; y++) { v3s16 psurf(x, y + 1, z); content_t csurf = env->getMap().getNodeNoEx(psurf).getContent(); if (c != CONTENT_AIR && csurf == CONTENT_AIR && CONTAINS(filter, c)) { push_v3s16(L, v3s16(x, y, z)); lua_rawseti(L, -2, ++i); } c = csurf; } } return 1; }