// 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); std::set<content_t> filter; if(lua_istable(L, 3)) { int table = 3; lua_pushnil(L); while(lua_next(L, table) != 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::map<content_t, u16> 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>::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; }
// minetest.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); std::set<content_t> filter; if(lua_istable(L, 3)){ int table = 3; lua_pushnil(L); while(lua_next(L, table) != 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); } // Get the table insert function lua_getglobal(L, "table"); lua_getfield(L, -1, "insert"); int table_insert = lua_gettop(L); lua_newtable(L); int table = lua_gettop(L); 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){ lua_pushvalue(L, table_insert); lua_pushvalue(L, table); push_v3s16(L, p); if(lua_pcall(L, 2, 0, 0)) script_error(L, "error: %s", lua_tostring(L, -1)); } } return 1; }
// get_node_level(pos) // pos = {x=num, y=num, z=num} int ModApiEnvMod::l_get_node_level(lua_State *L) { GET_ENV_PTR; v3s16 pos = read_v3s16(L, 1); MapNode n = env->getMap().getNodeNoEx(pos); lua_pushnumber(L, n.getLevel(env->getGameDef()->ndef())); return 1; }
// get_meta(pos) int ModApiEnvMod::l_get_meta(lua_State *L) { GET_ENV_PTR; // Do it v3s16 p = read_v3s16(L, 1); NodeMetaRef::create(L, p, env); return 1; }
// get_node_timer(pos) int ModApiEnvMod::l_get_node_timer(lua_State *L) { GET_ENV_PTR; // Do it v3s16 p = read_v3s16(L, 1); NodeTimerRef::create(L, p, env); return 1; }
// LuaVoxelManip() // Creates an LuaVoxelManip and leaves it on top of stack int LuaVoxelManip::create_object(lua_State *L) { NO_MAP_LOCK_REQUIRED; Environment *env = getEnv(L); if (!env) return 0; Map *map = &(env->getMap()); LuaVoxelManip *o = (lua_istable(L, 1) && lua_istable(L, 2)) ? new LuaVoxelManip(map, read_v3s16(L, 1), read_v3s16(L, 2)) : new LuaVoxelManip(map); *(void **)(lua_newuserdata(L, sizeof(void *))) = o; luaL_getmetatable(L, className); lua_setmetatable(L, -2); return 1; }
// spawn_tree(pos, treedef) int ModApiEnvMod::l_spawn_tree(lua_State *L) { GET_ENV_PTR; v3s16 p0 = read_v3s16(L, 1); treegen::TreeDef tree_def; std::string trunk,leaves,fruit; INodeDefManager *ndef = env->getGameDef()->ndef(); if(lua_istable(L, 2)) { getstringfield(L, 2, "axiom", tree_def.initial_axiom); getstringfield(L, 2, "rules_a", tree_def.rules_a); getstringfield(L, 2, "rules_b", tree_def.rules_b); getstringfield(L, 2, "rules_c", tree_def.rules_c); getstringfield(L, 2, "rules_d", tree_def.rules_d); getstringfield(L, 2, "trunk", trunk); tree_def.trunknode=ndef->getId(trunk); getstringfield(L, 2, "leaves", leaves); tree_def.leavesnode=ndef->getId(leaves); tree_def.leaves2_chance=0; getstringfield(L, 2, "leaves2", leaves); if (leaves !="") { tree_def.leaves2node=ndef->getId(leaves); getintfield(L, 2, "leaves2_chance", tree_def.leaves2_chance); } getintfield(L, 2, "angle", tree_def.angle); getintfield(L, 2, "iterations", tree_def.iterations); if (!getintfield(L, 2, "random_level", tree_def.iterations_random_level)) tree_def.iterations_random_level = 0; getstringfield(L, 2, "trunk_type", tree_def.trunk_type); getboolfield(L, 2, "thin_branches", tree_def.thin_branches); tree_def.fruit_chance=0; getstringfield(L, 2, "fruit", fruit); if (fruit != "") { tree_def.fruitnode=ndef->getId(fruit); getintfield(L, 2, "fruit_chance",tree_def.fruit_chance); } tree_def.explicit_seed = getintfield(L, 2, "seed", tree_def.seed); } else return 0; treegen::error e; if ((e = treegen::spawn_ltree (env, p0, ndef, tree_def)) != treegen::SUCCESS) { if (e == treegen::UNBALANCED_BRACKETS) { luaL_error(L, "spawn_tree(): closing ']' has no matching opening bracket"); } else { luaL_error(L, "spawn_tree(): unknown error"); } } return 1; }
// 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; }
// get_node(pos) // pos = {x=num, y=num, z=num} int ModApiClient::l_get_node(lua_State *L) { // pos v3s16 pos = read_v3s16(L, 1); // Do it bool pos_ok; MapNode n = getClient(L)->getNode(pos, &pos_ok); // Return node pushnode(L, n, getClient(L)->ndef()); return 1; }
// remove_node(pos) // pos = {x=num, y=num, z=num} int ModApiEnvMod::l_remove_node(lua_State *L) { GET_ENV_PTR; // parameters v3s16 pos = read_v3s16(L, 1); // Do it bool succeeded = env->removeNode(pos); lua_pushboolean(L, succeeded); return 1; }
int LuaVoxelManip::l_get_node_at(lua_State *L) { NO_MAP_LOCK_REQUIRED; GET_ENV_PTR; LuaVoxelManip *o = checkobject(L, 1); v3s16 pos = read_v3s16(L, 2); pushnode(L, o->vm->getNodeNoExNoEmerge(pos), env->getGameDef()->ndef()); return 1; }
// get_node_level(pos) // pos = {x=num, y=num, z=num} int ModApiEnvMod::l_get_node_level(lua_State *L) { Environment *env = getEnv(L); if (!env) { return 0; } v3s16 pos = read_v3s16(L, 1); MapNode n = env->getMap().getNodeNoEx(pos); lua_pushnumber(L, n.getLevel(env->getGameDef()->ndef())); return 1; }
// get_node(pos) // pos = {x=num, y=num, z=num} int ModApiEnvMod::l_get_node(lua_State *L) { GET_ENV_PTR; // pos v3s16 pos = read_v3s16(L, 1); // Do it MapNode n = env->getMap().getNodeNoEx(pos); // Return node pushnode(L, n, env->getGameDef()->ndef()); return 1; }
// find_path(pos1, pos2, searchdistance, // max_jump, max_drop, algorithm) -> table containing path int ModApiEnvMod::l_find_path(lua_State *L) { GET_ENV_PTR; v3s16 pos1 = read_v3s16(L, 1); v3s16 pos2 = read_v3s16(L, 2); unsigned int searchdistance = luaL_checkint(L, 3); unsigned int max_jump = luaL_checkint(L, 4); unsigned int max_drop = luaL_checkint(L, 5); algorithm algo = A_PLAIN_NP; if (!lua_isnil(L, 6)) { std::string algorithm = luaL_checkstring(L,6); if (algorithm == "A*") algo = A_PLAIN; if (algorithm == "Dijkstra") algo = DIJKSTRA; } std::vector<v3s16> path = get_Path(env,pos1,pos2,searchdistance,max_jump,max_drop,algo); if (path.size() > 0) { lua_newtable(L); int top = lua_gettop(L); unsigned int index = 1; for (std::vector<v3s16>::iterator i = path.begin(); i != path.end();i++) { lua_pushnumber(L,index); push_v3s16(L, *i); lua_settable(L, top); index++; } return 1; } return 0; }
int LuaVoxelManip::l_set_node_at(lua_State *L) { NO_MAP_LOCK_REQUIRED; GET_ENV_PTR; LuaVoxelManip *o = checkobject(L, 1); v3s16 pos = read_v3s16(L, 2); MapNode n = readnode(L, 3, env->getGameDef()->ndef()); o->vm->setNodeNoEmerge(pos, n); return 0; }
// LuaPerlinNoiseMap(np, size) // Creates an LuaPerlinNoiseMap and leaves it on top of stack int LuaPerlinNoiseMap::create_object(lua_State *L) { NoiseParams *np = read_noiseparams(L, 1); if (!np) return 0; v3s16 size = read_v3s16(L, 2); LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(np, 0, size); *(void **)(lua_newuserdata(L, sizeof(void *))) = o; luaL_getmetatable(L, className); lua_setmetatable(L, -2); return 1; }
// add_node_level(pos, level) // pos = {x=num, y=num, z=num} // level: 0..63 int ModApiEnvMod::l_add_node_level(lua_State *L) { GET_ENV_PTR; v3s16 pos = read_v3s16(L, 1); u8 level = 1; if(lua_isnumber(L, 2)) level = lua_tonumber(L, 2); MapNode n = env->getMap().getNodeNoEx(pos); lua_pushnumber(L, n.addLevel(env->getGameDef()->ndef(), level)); env->setNode(pos, n); return 1; }
// set_node(pos, node) // pos = {x=num, y=num, z=num} int ModApiEnvMod::l_set_node(lua_State *L) { GET_ENV_PTR; INodeDefManager *ndef = env->getGameDef()->ndef(); // parameters v3s16 pos = read_v3s16(L, 1); MapNode n = readnode(L, 2, ndef); // Do it bool succeeded = env->setNode(pos, n); lua_pushboolean(L, succeeded); return 1; }
// find_path(pos1, pos2, searchdistance, // max_jump, max_drop, algorithm) -> table containing path int ModApiEnvMod::l_find_path(lua_State *L) { GET_ENV_PTR; v3s16 pos1 = read_v3s16(L, 1); v3s16 pos2 = read_v3s16(L, 2); unsigned int searchdistance = luaL_checkint(L, 3); unsigned int max_jump = luaL_checkint(L, 4); unsigned int max_drop = luaL_checkint(L, 5); PathAlgorithm algo = PA_PLAIN_NP; if (!lua_isnil(L, 6)) { std::string algorithm = luaL_checkstring(L,6); if (algorithm == "A*") algo = PA_PLAIN; if (algorithm == "Dijkstra") algo = PA_DIJKSTRA; } std::vector<v3s16> path = get_path(env, pos1, pos2, searchdistance, max_jump, max_drop, algo); if (!path.empty()) { lua_newtable(L); int top = lua_gettop(L); unsigned int index = 1; for (const v3s16 &i : path) { lua_pushnumber(L,index); push_v3s16(L, i); lua_settable(L, top); index++; } return 1; } return 0; }
int LuaPerlinNoiseMap::l_getMapSlice(lua_State *L) { NO_MAP_LOCK_REQUIRED; LuaPerlinNoiseMap *o = checkobject(L, 1); v3s16 slice_offset = read_v3s16(L, 2); v3s16 slice_size = read_v3s16(L, 3); bool use_buffer = lua_istable(L, 4); Noise *n = o->noise; if (use_buffer) lua_pushvalue(L, 3); else lua_newtable(L); write_array_slice_float(L, lua_gettop(L), n->result, v3u16(n->sx, n->sy, n->sz), v3u16(slice_offset.X, slice_offset.Y, slice_offset.Z), v3u16(slice_size.X, slice_size.Y, slice_size.Z)); return 1; }
// place_schematic(p, schematic, rotation, replacement) int ModApiMapgen::l_place_schematic(lua_State *L) { DecoSchematic dschem; Map *map = &(getEnv(L)->getMap()); INodeDefManager *ndef = getServer(L)->getNodeDefManager(); v3s16 p = read_v3s16(L, 1); if (!read_schematic(L, 2, &dschem, getServer(L))) return 0; int rot = ROTATE_0; if (lua_isstring(L, 3)) string_to_enum(es_Rotation, rot, std::string(lua_tostring(L, 3))); dschem.rotation = (Rotation)rot; if (lua_istable(L, 4)) { lua_pushnil(L); while (lua_next(L, 4) != 0) { // key at index -2 and value at index -1 lua_rawgeti(L, -1, 1); std::string replace_from = lua_tostring(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 2); std::string replace_to = lua_tostring(L, -1); lua_pop(L, 1); dschem.replacements[replace_from] = replace_to; // removes value, keeps key for next iteration lua_pop(L, 1); } } bool force_placement = true; if (lua_isboolean(L, 5)) force_placement = lua_toboolean(L, 5); if (!dschem.filename.empty()) { if (!dschem.loadSchematicFile()) { errorstream << "place_schematic: failed to load schematic file '" << dschem.filename << "'" << std::endl; return 0; } dschem.resolveNodeNames(ndef); } dschem.placeStructure(map, p, force_placement); 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); std::set<content_t> filter; if(lua_istable(L, 3)){ int table = 3; lua_pushnil(L); while(lua_next(L, table) != 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 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); } } return 1; }
// rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds int ModApiBasic::l_rollback_get_last_node_actor(lua_State *L) { v3s16 p = read_v3s16(L, 1); int range = luaL_checknumber(L, 2); int seconds = luaL_checknumber(L, 3); Server *server = getServer(L); IRollbackManager *rollback = server->getRollbackManager(); v3s16 act_p; int act_seconds = 0; std::string actor = rollback->getLastNodeActor(p, range, seconds, &act_p, &act_seconds); lua_pushstring(L, actor.c_str()); push_v3s16(L, act_p); lua_pushnumber(L, act_seconds); return 3; }
// get_perlin_map(noiseparams, size) // returns world-specific PerlinNoiseMap int ModApiEnvMod::l_get_perlin_map(lua_State *L) { GET_ENV_PTR; NoiseParams *np = read_noiseparams(L, 1); if (!np) return 0; v3s16 size = read_v3s16(L, 2); int seed = (int)(env->getServerMap().getSeed()); LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(np, seed, size); *(void **)(lua_newuserdata(L, sizeof(void *))) = n; luaL_getmetatable(L, "PerlinNoiseMap"); lua_setmetatable(L, -2); return 1; }
// get_perlin_map(noiseparams, size) // returns world-specific PerlinNoiseMap int ModApiEnvMod::l_get_perlin_map(lua_State *L) { GET_ENV_PTR_NO_MAP_LOCK; NoiseParams np; if (!read_noiseparams(L, 1, &np)) return 0; v3s16 size = read_v3s16(L, 2); s32 seed = (s32)(env->getServerMap().getSeed()); LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(&np, seed, size); *(void **)(lua_newuserdata(L, sizeof(void *))) = n; luaL_getmetatable(L, "PerlinNoiseMap"); lua_setmetatable(L, -2); return 1; }
// spawn_tree(pos, treedef) int ModApiEnvMod::l_spawn_tree(lua_State *L) { GET_ENV_PTR; v3s16 p0 = read_v3s16(L, 1); treegen::TreeDef tree_def; std::string trunk,leaves,fruit; INodeDefManager *ndef = env->getGameDef()->ndef(); if(lua_istable(L, 2)) { getstringfield(L, 2, "axiom", tree_def.initial_axiom); getstringfield(L, 2, "rules_a", tree_def.rules_a); getstringfield(L, 2, "rules_b", tree_def.rules_b); getstringfield(L, 2, "rules_c", tree_def.rules_c); getstringfield(L, 2, "rules_d", tree_def.rules_d); getstringfield(L, 2, "trunk", trunk); tree_def.trunknode=ndef->getId(trunk); getstringfield(L, 2, "leaves", leaves); tree_def.leavesnode=ndef->getId(leaves); tree_def.leaves2_chance=0; getstringfield(L, 2, "leaves2", leaves); if (leaves !="") { tree_def.leaves2node=ndef->getId(leaves); getintfield(L, 2, "leaves2_chance", tree_def.leaves2_chance); } getintfield(L, 2, "angle", tree_def.angle); getintfield(L, 2, "iterations", tree_def.iterations); getintfield(L, 2, "random_level", tree_def.iterations_random_level); getstringfield(L, 2, "trunk_type", tree_def.trunk_type); getboolfield(L, 2, "thin_branches", tree_def.thin_branches); tree_def.fruit_chance=0; getstringfield(L, 2, "fruit", fruit); if (fruit != "") { tree_def.fruitnode=ndef->getId(fruit); getintfield(L, 2, "fruit_chance",tree_def.fruit_chance); } getintfield(L, 2, "seed", tree_def.seed); } else return 0; treegen::spawn_ltree (env, p0, ndef, tree_def); return 1; }
// find_node_near(pos, radius, nodenames, search_center) -> pos or nil // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" int ModApiEnvMod::l_find_node_near(lua_State *L) { Environment *env = getEnv(L); if (!env) { return 0; } INodeDefManager *ndef = getGameDef(L)->ndef(); v3s16 pos = read_v3s16(L, 1); int radius = luaL_checkinteger(L, 2); 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); } int start_radius = (lua_toboolean(L, 4)) ? 0 : 1; #ifndef SERVER // Client API limitations if (getClient(L) && getClient(L)->checkCSMFlavourLimit(CSMFlavourLimit::CSM_FL_LOOKUP_NODES)) { radius = std::max<int>(radius, getClient(L)->getCSMNodeRangeLimit()); } #endif for (int d = start_radius; d <= radius; d++) { std::vector<v3s16> list = FacePositionCache::getFacePositions(d); for (const v3s16 &i : list) { v3s16 p = pos + i; content_t c = env->getMap().getNodeNoEx(p).getContent(); if (CONTAINS(filter, c)) { push_v3s16(L, p); return 1; } } } return 0; }
// get_node_or_nil(pos) // pos = {x=num, y=num, z=num} int ModApiEnvMod::l_get_node_or_nil(lua_State *L) { GET_ENV_PTR; // pos v3s16 pos = read_v3s16(L, 1); // Do it bool pos_ok; MapNode n = env->getMap().getNodeNoEx(pos, &pos_ok); if (pos_ok) { // Return node pushnode(L, n, env->getGameDef()->ndef()); } else { lua_pushnil(L); } return 1; }
// freeze_melt(pos, direction) // pos = {x=num, y=num, z=num} // direction: -1 (freeze), 1 (melt) int ModApiEnvMod::l_freeze_melt(lua_State *L) { GET_ENV_PTR; v3s16 pos = read_v3s16(L, 1); int direction = 1; if(lua_isnumber(L, 2)) direction = lua_tonumber(L, 2); MapNode n = env->getMap().getNodeNoEx(pos); if(n.getContent() == CONTENT_IGNORE){ lua_pushnumber(L, 0); return 1; } lua_pushnumber(L, n.freeze_melt(env->getGameDef()->ndef(), direction)); env->setNode(pos, n); return 1; }
// set_node_level(pos, level) // pos = {x=num, y=num, z=num} // level: 0..63 int ModApiEnvMod::l_set_node_level(lua_State *L) { GET_ENV_PTR; v3s16 pos = read_v3s16(L, 1); u8 level = 1; if(lua_isnumber(L, 2)) level = lua_tonumber(L, 2); MapNode n = env->getMap().getNodeNoEx(pos); if(n.getContent() == CONTENT_IGNORE){ lua_pushnumber(L, 0); return 1; } lua_pushnumber(L, n.setLevel(env->getGameDef()->ndef(), level)); env->setNode(pos, n); return 1; }