void ScriptApiItem::pushPointedThing(const PointedThing& pointed) { lua_State* L = getStack(); lua_newtable(L); if(pointed.type == POINTEDTHING_NODE) { lua_pushstring(L, "node"); lua_setfield(L, -2, "type"); push_v3s16(L, pointed.node_undersurface); lua_setfield(L, -2, "under"); push_v3s16(L, pointed.node_abovesurface); lua_setfield(L, -2, "above"); } else if(pointed.type == POINTEDTHING_OBJECT) { lua_pushstring(L, "object"); lua_setfield(L, -2, "type"); objectrefGet(L, pointed.object_id); lua_setfield(L, -2, "ref"); } else { lua_pushstring(L, "nothing"); lua_setfield(L, -2, "type"); } }
int LuaVoxelManip::l_get_emerged_area(lua_State *L) { LuaVoxelManip *o = checkobject(L, 1); push_v3s16(L, o->vm->m_area.MinEdge); push_v3s16(L, o->vm->m_area.MaxEdge); return 2; }
void ScriptApiEnv::environment_OnGenerated(v3s16 minp, v3s16 maxp, u32 blockseed) { SCRIPTAPI_PRECHECKHEADER // Get core.registered_on_generateds lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_generateds"); // Call callbacks push_v3s16(L, minp); push_v3s16(L, maxp); lua_pushnumber(L, blockseed); runCallbacks(3, RUN_CALLBACKS_MODE_FIRST); }
// Return number of accepted items to be put int ScriptApiNodemeta::nodemeta_inventory_AllowPut(v3s16 p, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if (node.getContent() == CONTENT_IGNORE) return 0; // Push callback function on stack std::string nodename = ndef->get(node).name; if (!getItemCallback(nodename.c_str(), "allow_metadata_inventory_put")) return stack.count; // Call function(pos, listname, index, stack, player) push_v3s16(L, p); // pos lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(L, player); // player if (lua_pcall(L, 5, 1, m_errorhandler)) scriptError(); if(!lua_isnumber(L, -1)) throw LuaError("allow_metadata_inventory_put should" " return a number, guilty node: " + nodename); int num = luaL_checkinteger(L, -1); lua_pop(L, 1); // Pop integer return num; }
// 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_STAR; if (!lua_isnil(L, 6)) { std::string algorithm = luaL_checkstring(L,6); } std::vector<v3s16> path = getPath(env, pos1, pos2, searchdistance, max_jump, max_drop, algo, ADJACENCY_4); 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; }
void ScriptApiNode::node_on_receive_fields(v3s16 p, const std::string &formname, const std::map<std::string, std::string> &fields, ServerActiveObject *sender) { SCRIPTAPI_PRECHECKHEADER INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if (node.getContent() == CONTENT_IGNORE) return; // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "on_receive_fields")) return; // Call function push_v3s16(L, p); // pos lua_pushstring(L, formname.c_str()); // formname lua_newtable(L); // fields std::map<std::string, std::string>::const_iterator it; for (it = fields.begin(); it != fields.end(); it++){ const std::string &name = it->first; const std::string &value = it->second; lua_pushstring(L, name.c_str()); lua_pushlstring(L, value.c_str(), value.size()); lua_settable(L, -3); } objectrefGetOrCreate(sender); // player if (lua_pcall(L, 4, 0, m_errorhandler)) scriptError(); }
// Report moved items void ScriptApiNodemeta::nodemeta_inventory_OnMove(v3s16 p, const std::string &from_list, int from_index, const std::string &to_list, int to_index, int count, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if(node.getContent() == CONTENT_IGNORE) return; // Push callback function on stack if(!getItemCallback(ndef->get(node).name.c_str(), "on_metadata_inventory_move")) return; // function(pos, from_list, from_index, to_list, to_index, count, player) push_v3s16(L, p); // pos lua_pushstring(L, from_list.c_str()); // from_list lua_pushinteger(L, from_index + 1); // from_index lua_pushstring(L, to_list.c_str()); // to_list lua_pushinteger(L, to_index + 1); // to_index lua_pushinteger(L, count); // count objectrefGetOrCreate(player); // player if(lua_pcall(L, 7, 0, errorhandler)) scriptError(); lua_pop(L, 1); // Pop error handler }
// Report taken items void ScriptApiNodemeta::nodemeta_inventory_OnTake(v3s16 p, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if(node.getContent() == CONTENT_IGNORE) return; // Push callback function on stack if(!getItemCallback(ndef->get(node).name.c_str(), "on_metadata_inventory_take")) return; // Call function(pos, listname, index, stack, player) push_v3s16(L, p); // pos lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(player); // player if(lua_pcall(L, 5, 0, errorhandler)) scriptError(); lua_pop(L, 1); // Pop error handler }
void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n, u32 active_object_count, u32 active_object_count_wider) { GameScripting *scriptIface = env->getScriptIface(); scriptIface->realityCheck(); lua_State *L = scriptIface->getStack(); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); // Get minetest.registered_abms lua_getglobal(L, "minetest"); lua_getfield(L, -1, "registered_abms"); luaL_checktype(L, -1, LUA_TTABLE); int registered_abms = lua_gettop(L); // Get minetest.registered_abms[m_id] lua_pushnumber(L, m_id); lua_gettable(L, registered_abms); if(lua_isnil(L, -1)) assert(0); // Call action luaL_checktype(L, -1, LUA_TTABLE); lua_getfield(L, -1, "action"); luaL_checktype(L, -1, LUA_TFUNCTION); push_v3s16(L, p); pushnode(L, n, env->getGameDef()->ndef()); lua_pushnumber(L, active_object_count); lua_pushnumber(L, active_object_count_wider); if(lua_pcall(L, 4, 0, 0)) script_error(L, "error: %s", lua_tostring(L, -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 LuaMinimap::l_get_pos(lua_State *L) { LuaMinimap *ref = checkobject(L, 1); Minimap *m = getobject(ref); push_v3s16(L, m->getPos()); 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; }
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; }
void ScriptApiNode::node_falling_update_single(v3s16 p) { SCRIPTAPI_PRECHECKHEADER lua_getglobal(L, "nodeupdate_single"); push_v3s16(L, p); if (lua_pcall(L, 1, 0, m_errorhandler)) scriptError(); }
static void push_area(lua_State *L, const Area *a, bool include_borders, bool include_data) { if (!include_borders && !include_data) { lua_pushboolean(L, true); return; } lua_newtable(L); if (include_borders) { push_v3s16(L, a->minedge); lua_setfield(L, -2, "min"); push_v3s16(L, a->maxedge); lua_setfield(L, -2, "max"); } if (include_data) { lua_pushlstring(L, a->data.c_str(), a->data.size()); lua_setfield(L, -2, "data"); } }
void ScriptApiNode::node_falling_update_single(v3s16 p) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); lua_getglobal(L, "nodeupdate_single"); push_v3s16(L, p); PCALL_RES(lua_pcall(L, 1, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
void ScriptApiNode::node_drop(v3s16 p, int fast = 0) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); lua_getglobal(L, "node_drop"); push_v3s16(L, p); lua_pushinteger(L, fast); PCALL_RES(lua_pcall(L, 2, 0, errorhandler)); lua_pop(L, 1); // Pop error handler }
void ScriptApiNode::node_falling_update_single(v3s16 p) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); lua_getglobal(L, "nodeupdate_single"); push_v3s16(L, p); if(lua_pcall(L, 1, 0, errorhandler)) scriptError(); lua_pop(L, 1); // Pop error handler }
void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n, u32 active_object_count, u32 active_object_count_wider, MapNode neighbor, bool activate) { GameScripting *scriptIface = env->getScriptIface(); auto _script_lock = RecursiveMutexAutoLock(scriptIface->m_luastackmutex, std::try_to_lock); if (!_script_lock.owns_lock()) { return; } scriptIface->realityCheck(); lua_State *L = scriptIface->getStack(); sanity_check(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); int error_handler = PUSH_ERROR_HANDLER(L); // Get registered_abms lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_abms"); luaL_checktype(L, -1, LUA_TTABLE); lua_remove(L, -2); // Remove core // Get registered_abms[m_id] lua_pushnumber(L, m_id); lua_gettable(L, -2); if(lua_isnil(L, -1)) //FATAL_ERROR(""); return; lua_remove(L, -2); // Remove registered_abms scriptIface->setOriginFromTable(-1); // Call action luaL_checktype(L, -1, LUA_TTABLE); lua_getfield(L, -1, "action"); luaL_checktype(L, -1, LUA_TFUNCTION); lua_remove(L, -2); // Remove registered_abms[m_id] push_v3s16(L, p); pushnode(L, n, env->getGameDef()->ndef()); lua_pushnumber(L, active_object_count); lua_pushnumber(L, active_object_count_wider); pushnode(L, neighbor, env->getGameDef()->ndef()); lua_pushboolean(L, activate); int result = lua_pcall(L, 6, 0, error_handler); if (result) scriptIface->scriptError(result, "LuaABM::trigger"); lua_pop(L, 1); // Pop error handler }
// 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); 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 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 && filter.count(c) != 0) { push_v3s16(L, v3s16(x, y, z)); lua_rawseti(L, -2, ++i); } c = csurf; } } return 1; }
// find_nodes_with_meta(pos1, pos2) int ModApiEnvMod::l_find_nodes_with_meta(lua_State *L) { GET_ENV_PTR; std::vector<v3s16> positions = env->getMap().findNodesWithMetadata( check_v3s16(L, 1), check_v3s16(L, 2)); lua_newtable(L); for (size_t i = 0; i != positions.size(); i++) { push_v3s16(L, positions[i]); lua_rawseti(L, -2, i + 1); } return 1; }
void ScriptApiNode::node_on_destruct(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if(!getItemCallback(ndef->get(node).name.c_str(), "on_destruct")) return; // Call function push_v3s16(L, p); if(lua_pcall(L, 1, 0, 0)) scriptError("error: %s", lua_tostring(L, -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; }
void ScriptApiNode::node_after_destruct(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "after_destruct")) return; // Call function push_v3s16(L, p); pushnode(L, node, ndef); if (lua_pcall(L, 2, 0, m_errorhandler)) scriptError(); }
void LuaLBM::trigger(ServerEnvironment *env, v3s16 p, MapNode n) { GameScripting *scriptIface = env->getScriptIface(); auto _script_lock = RecursiveMutexAutoLock(scriptIface->m_luastackmutex, std::try_to_lock); if (!_script_lock.owns_lock()) { return; } scriptIface->realityCheck(); lua_State *L = scriptIface->getStack(); sanity_check(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); int error_handler = PUSH_ERROR_HANDLER(L); // Get registered_lbms lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_lbms"); luaL_checktype(L, -1, LUA_TTABLE); lua_remove(L, -2); // Remove core // Get registered_lbms[m_id] lua_pushnumber(L, m_id); lua_gettable(L, -2); //FATAL_ERROR_IF(lua_isnil(L, -1), "Entry with given id not found in registered_lbms table"); if (lua_isnil(L, -1)) { errorstream << "Entry with given id " << m_id << " not found in registered_lbms table" << std::endl; return; } lua_remove(L, -2); // Remove registered_lbms scriptIface->setOriginFromTable(-1); // Call action luaL_checktype(L, -1, LUA_TTABLE); lua_getfield(L, -1, "action"); luaL_checktype(L, -1, LUA_TFUNCTION); lua_remove(L, -2); // Remove registered_lbms[m_id] push_v3s16(L, p); pushnode(L, n, env->getGameDef()->ndef()); int result = lua_pcall(L, 2, 0, error_handler); if (result) scriptIface->scriptError(result, "LuaLBM::trigger"); lua_pop(L, 1); // Pop error handler }
// 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; }
bool ScriptApiNode::node_on_timer(v3s16 p, MapNode node, f32 dtime) { SCRIPTAPI_PRECHECKHEADER INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "on_timer")) return false; // Call function push_v3s16(L, p); lua_pushnumber(L,dtime); if (lua_pcall(L, 2, 1, m_errorhandler)) scriptError(); return (bool) lua_isboolean(L, -1) && (bool) lua_toboolean(L, -1) == true; }
void scriptapi_node_on_destruct(lua_State *L, v3s16 p, MapNode node) { realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); INodeDefManager *ndef = get_server(L)->ndef(); // Push callback function on stack if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_destruct")) return; // Call function push_v3s16(L, p); if(lua_pcall(L, 1, 0, 0)) script_error(L, "error: %s", lua_tostring(L, -1)); }
void ScriptApiNode::node_on_destruct(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "on_destruct")) return; // Call function push_v3s16(L, p); PCALL_RES(lua_pcall(L, 1, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
// 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; }