From 17fd5fe9358615633a04d7a3941b444a8ce5f199 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Mon, 11 Sep 2017 15:51:40 +0200 Subject: [PATCH] Make INodeDefManager::getIds return a vector, not a set --- src/nodedef.cpp | 61 ++++++++++++------------------------ src/nodedef.h | 9 ++---- src/script/cpp_api/s_env.cpp | 12 +++---- src/script/lua_api/l_env.cpp | 27 +++++++++------- src/script/lua_api/l_env.h | 12 +++---- src/serverenvironment.cpp | 22 ++++++------- src/serverenvironment.h | 4 +-- 7 files changed, 64 insertions(+), 83 deletions(-) diff --git a/src/nodedef.cpp b/src/nodedef.cpp index e547e31b1..d13f93068 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gamedef.h" #include "mapnode.h" #include // Used in applyTextureOverrides() +#include /* NodeBox @@ -485,7 +486,7 @@ void ContentFeatures::deSerialize(std::istream &is) u16 connects_to_size = readU16(is); connects_to_ids.clear(); for (u16 i = 0; i < connects_to_size; i++) - connects_to_ids.insert(readU16(is)); + connects_to_ids.push_back(readU16(is)); post_effect_color.setAlpha(readU8(is)); post_effect_color.setRed(readU8(is)); post_effect_color.setGreen(readU8(is)); @@ -845,7 +846,7 @@ public: inline virtual const ContentFeatures& get(const MapNode &n) const; virtual bool getId(const std::string &name, content_t &result) const; virtual content_t getId(const std::string &name) const; - virtual bool getIds(const std::string &name, std::set &result) const; + virtual bool getIds(const std::string &name, std::vector &result) const; virtual const ContentFeatures& get(const std::string &name) const; content_t allocateId(); virtual content_t set(const std::string &name, const ContentFeatures &def); @@ -892,10 +893,10 @@ private: std::unordered_map m_name_id_mapping_with_aliases; - // A mapping from groups to a list of content_ts (and their levels) - // that belong to it. Necessary for a direct lookup in getIds(). + // A mapping from groups to a vector of content_ts that belong to it. + // Necessary for a direct lookup in getIds(). // Note: Not serialized. - std::unordered_map m_group_to_items; + std::unordered_map> m_group_to_items; // Next possibly free id content_t m_next_id; @@ -1037,28 +1038,25 @@ content_t CNodeDefManager::getId(const std::string &name) const bool CNodeDefManager::getIds(const std::string &name, - std::set &result) const + std::vector &result) const { //TimeTaker t("getIds", NULL, PRECISION_MICRO); if (name.substr(0,6) != "group:") { content_t id = CONTENT_IGNORE; bool exists = getId(name, id); if (exists) - result.insert(id); + result.push_back(id); return exists; } std::string group = name.substr(6); - std::unordered_map::const_iterator + std::unordered_map>::const_iterator i = m_group_to_items.find(group); if (i == m_group_to_items.end()) return true; - const GroupItems &items = i->second; - for (const auto &item : items) { - if (item.second != 0) - result.insert(item.first); - } + const std::vector &items = i->second; + result.insert(result.end(), items.begin(), items.end()); //printf("getIds: %dus\n", t.stop()); return true; } @@ -1247,15 +1245,7 @@ content_t CNodeDefManager::set(const std::string &name, const ContentFeatures &d // belongs to when a node is re-registered for (const auto &group : def.groups) { const std::string &group_name = group.first; - - std::unordered_map::iterator - j = m_group_to_items.find(group_name); - if (j == m_group_to_items.end()) { - m_group_to_items[group_name].emplace_back(id, group.second); - } else { - GroupItems &items = j->second; - items.emplace_back(id, group.second); - } + m_group_to_items[group_name].push_back(id); } return id; } @@ -1283,16 +1273,10 @@ void CNodeDefManager::removeNode(const std::string &name) } // Erase node content from all groups it belongs to - for (std::unordered_map::iterator iter_groups = + for (std::unordered_map>::iterator iter_groups = m_group_to_items.begin(); iter_groups != m_group_to_items.end();) { - GroupItems &items = iter_groups->second; - for (GroupItems::iterator iter_groupitems = items.begin(); - iter_groupitems != items.end();) { - if (iter_groupitems->first == id) - items.erase(iter_groupitems++); - else - ++iter_groupitems; - } + std::vector &items = iter_groups->second; + items.erase(std::remove(items.begin(), items.end(), id), items.end()); // Check if group is empty if (items.empty()) @@ -1545,9 +1529,8 @@ void CNodeDefManager::mapNodeboxConnections() if (f.drawtype != NDT_NODEBOX || f.node_box.type != NODEBOX_CONNECTED) continue; - for (std::vector::const_iterator it = f.connects_to.begin(); - it != f.connects_to.end(); ++it) { - getIds(*it, f.connects_to_ids); + for (const std::string &name : f.connects_to) { + getIds(name, f.connects_to_ids); } } } @@ -1560,14 +1543,14 @@ bool CNodeDefManager::nodeboxConnects(MapNode from, MapNode to, u8 connect_face) return false; // lookup target in connected set - if (f1.connects_to_ids.find(to.param0) == f1.connects_to_ids.end()) + if (!CONTAINS(f1.connects_to_ids, to.param0)) return false; const ContentFeatures &f2 = get(to); if ((f2.drawtype == NDT_NODEBOX) && (f2.node_box.type == NODEBOX_CONNECTED)) // ignores actually looking if back connection exists - return (f2.connects_to_ids.find(from.param0) != f2.connects_to_ids.end()); + return CONTAINS(f2.connects_to_ids, from.param0); // does to node declare usable faces? if (f2.connect_sides > 0) { @@ -1686,11 +1669,7 @@ bool NodeResolver::getIdsFromNrBacklog(std::vector *result_out, success = false; } } else { - std::set cids; - std::set::iterator it; - m_ndef->getIds(name, cids); - for (it = cids.begin(); it != cids.end(); ++it) - result_out->push_back(*it); + m_ndef->getIds(name, *result_out); } } diff --git a/src/nodedef.h b/src/nodedef.h index 853b9bddd..23100a2ed 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -23,7 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include -#include #include "mapnode.h" #ifndef SERVER #include "client/tile.h" @@ -42,8 +41,6 @@ class IShaderSource; class IGameDef; class NodeResolver; -typedef std::list > GroupItems; - enum ContentParamType { CPT_NONE, @@ -290,7 +287,7 @@ struct ContentFeatures // for NDT_CONNECTED pairing u8 connect_sides; std::vector connects_to; - std::set connects_to_ids; + std::vector connects_to_ids; // Post effect color, drawn when the camera is inside the node. video::SColor post_effect_color; // Flowing liquid or snow, value = default level @@ -424,7 +421,7 @@ public: virtual content_t getId(const std::string &name) const=0; // Allows "group:name" in addition to regular node names // returns false if node name not found, true otherwise - virtual bool getIds(const std::string &name, std::set &result) + virtual bool getIds(const std::string &name, std::vector &result) const=0; virtual const ContentFeatures &get(const std::string &name) const=0; @@ -452,7 +449,7 @@ public: // If not found, returns CONTENT_IGNORE virtual content_t getId(const std::string &name) const=0; // Allows "group:name" in addition to regular node names - virtual bool getIds(const std::string &name, std::set &result) + virtual bool getIds(const std::string &name, std::vector &result) const=0; // If not found, returns the features of CONTENT_UNKNOWN virtual const ContentFeatures &get(const std::string &name) const=0; diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp index b1404bf22..517892b03 100644 --- a/src/script/cpp_api/s_env.cpp +++ b/src/script/cpp_api/s_env.cpp @@ -108,7 +108,7 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env) int id = lua_tonumber(L, -2); int current_abm = lua_gettop(L); - std::set trigger_contents; + std::vector trigger_contents; lua_getfield(L, current_abm, "nodenames"); if (lua_istable(L, -1)) { int table = lua_gettop(L); @@ -116,16 +116,16 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env) while (lua_next(L, table)) { // key at index -2 and value at index -1 luaL_checktype(L, -1, LUA_TSTRING); - trigger_contents.insert(lua_tostring(L, -1)); + trigger_contents.push_back(lua_tostring(L, -1)); // removes value, keeps key for next iteration lua_pop(L, 1); } } else if (lua_isstring(L, -1)) { - trigger_contents.insert(lua_tostring(L, -1)); + trigger_contents.push_back(lua_tostring(L, -1)); } lua_pop(L, 1); - std::set required_neighbors; + std::vector required_neighbors; lua_getfield(L, current_abm, "neighbors"); if (lua_istable(L, -1)) { int table = lua_gettop(L); @@ -133,12 +133,12 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env) while (lua_next(L, table)) { // key at index -2 and value at index -1 luaL_checktype(L, -1, LUA_TSTRING); - required_neighbors.insert(lua_tostring(L, -1)); + required_neighbors.push_back(lua_tostring(L, -1)); // removes value, keeps key for next iteration lua_pop(L, 1); } } else if (lua_isstring(L, -1)) { - required_neighbors.insert(lua_tostring(L, -1)); + required_neighbors.push_back(lua_tostring(L, -1)); } lua_pop(L, 1); diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index be92365ac..1d0716484 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -719,7 +719,7 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) INodeDefManager *ndef = getGameDef(L)->ndef(); v3s16 pos = read_v3s16(L, 1); int radius = luaL_checkinteger(L, 2); - std::set filter; + std::vector filter; if (lua_istable(L, 3)) { lua_pushnil(L); while (lua_next(L, 3) != 0) { @@ -748,7 +748,7 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) for (const v3s16 &i : list) { v3s16 p = pos + i; content_t c = env->getMap().getNodeNoEx(p).getContent(); - if (filter.count(c) != 0) { + if (CONTAINS(filter, c)) { push_v3s16(L, p); return 1; } @@ -780,7 +780,7 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) return 0; } - std::set filter; + std::vector filter; if (lua_istable(L, 3)) { lua_pushnil(L); while (lua_next(L, 3) != 0) { @@ -794,7 +794,8 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) ndef->getIds(lua_tostring(L, 3), filter); } - std::unordered_map individual_count; + std::vector individual_count; + individual_count.resize(filter.size()); lua_newtable(L); u64 i = 0; @@ -803,16 +804,20 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) 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) { + + std::vector::iterator it = std::find(filter.begin(), filter.end(), c); + if (it != filter.end()) { push_v3s16(L, p); lua_rawseti(L, -2, ++i); - individual_count[c]++; + + u32 filt_index = it - filter.begin(); + individual_count[filt_index]++; } } lua_newtable(L); - for (content_t it : filter) { - lua_pushnumber(L, individual_count[it]); - lua_setfield(L, -2, ndef->get(it).name.c_str()); + for (u32 i = 0; i < filter.size(); i++) { + lua_pushnumber(L, individual_count[i]); + lua_setfield(L, -2, ndef->get(filter[i]).name.c_str()); } return 2; } @@ -847,7 +852,7 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L) return 0; } - std::set filter; + std::vector filter; if (lua_istable(L, 3)) { lua_pushnil(L); @@ -873,7 +878,7 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L) 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) { + CONTAINS(filter, c)) { push_v3s16(L, v3s16(x, y, z)); lua_rawseti(L, -2, ++i); } diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 4d295b6eb..6cfdc0f6d 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -188,15 +188,15 @@ class LuaABM : public ActiveBlockModifier { private: int m_id; - std::set m_trigger_contents; - std::set m_required_neighbors; + std::vector m_trigger_contents; + std::vector m_required_neighbors; float m_trigger_interval; u32 m_trigger_chance; bool m_simple_catch_up; public: LuaABM(lua_State *L, int id, - const std::set &trigger_contents, - const std::set &required_neighbors, + const std::vector &trigger_contents, + const std::vector &required_neighbors, float trigger_interval, u32 trigger_chance, bool simple_catch_up): m_id(id), m_trigger_contents(trigger_contents), @@ -206,11 +206,11 @@ public: m_simple_catch_up(simple_catch_up) { } - virtual const std::set &getTriggerContents() const + virtual const std::vector &getTriggerContents() const { return m_trigger_contents; } - virtual const std::set &getRequiredNeighbors() const + virtual const std::vector &getRequiredNeighbors() const { return m_required_neighbors; } diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 7d95b8280..1abe5054c 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #if USE_POSTGRESQL #include "database-postgresql.h" #endif +#include #define LBM_NAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_:" @@ -84,7 +85,7 @@ void LBMContentMapping::addLBM(LoadingBlockModifierDef *lbm_def, IGameDef *gamed lbm_list.push_back(lbm_def); for (const std::string &nodeTrigger: lbm_def->trigger_contents) { - std::set c_ids; + std::vector c_ids; bool found = nodedef->getIds(nodeTrigger, c_ids); if (!found) { content_t c_id = gamedef->allocateUnknownNodeId(nodeTrigger); @@ -94,7 +95,7 @@ void LBMContentMapping::addLBM(LoadingBlockModifierDef *lbm_def, IGameDef *gamed << "\" while loading LBM \"" << lbm_def->name << "\"." << std::endl; continue; } - c_ids.insert(c_id); + c_ids.push_back(c_id); } for (content_t c_id : c_ids) { @@ -646,7 +647,8 @@ struct ActiveABM { ActiveBlockModifier *abm; int chance; - std::set required_neighbors; + std::vector required_neighbors; + bool check_required_neighbors; // false if required_neighbors is known to be empty }; class ABMHandler @@ -693,16 +695,17 @@ public: } // Trigger neighbors - const std::set &required_neighbors_s = + const std::vector &required_neighbors_s = abm->getRequiredNeighbors(); for (const std::string &required_neighbor_s : required_neighbors_s) { ndef->getIds(required_neighbor_s, aabm.required_neighbors); } + aabm.check_required_neighbors = !required_neighbors_s.empty(); // Trigger contents - const std::set &contents_s = abm->getTriggerContents(); + const std::vector &contents_s = abm->getTriggerContents(); for (const std::string &content_s : contents_s) { - std::set ids; + std::vector ids; ndef->getIds(content_s, ids); for (content_t c : ids) { if (c >= m_aabms.size()) @@ -777,7 +780,7 @@ public: continue; // Check neighbors - if (!aabm.required_neighbors.empty()) { + if (aabm.check_required_neighbors) { v3s16 p1; for(p1.X = p0.X-1; p1.X <= p0.X+1; p1.X++) for(p1.Y = p0.Y-1; p1.Y <= p0.Y+1; p1.Y++) @@ -796,11 +799,8 @@ public: MapNode n = map->getNodeNoEx(p1 + block->getPosRelative()); c = n.getContent(); } - std::set::const_iterator k; - k = aabm.required_neighbors.find(c); - if(k != aabm.required_neighbors.end()){ + if (CONTAINS(aabm.required_neighbors, c)) goto neighbor_found; - } } // No required neighbor found continue; diff --git a/src/serverenvironment.h b/src/serverenvironment.h index 0eabfc08f..3fdd6d77e 100644 --- a/src/serverenvironment.h +++ b/src/serverenvironment.h @@ -53,10 +53,10 @@ public: virtual ~ActiveBlockModifier() = default; // Set of contents to trigger on - virtual const std::set &getTriggerContents() const = 0; + virtual const std::vector &getTriggerContents() const = 0; // Set of required neighbors (trigger doesn't happen if none are found) // Empty = do not check neighbors - virtual const std::set &getRequiredNeighbors() const = 0; + virtual const std::vector &getRequiredNeighbors() const = 0; // Trigger interval in seconds virtual float getTriggerInterval() = 0; // Random chance of (1 / return value), 0 is disallowed