Make INodeDefManager::getIds return a vector, not a set
authorKahrl <kahrl@gmx.net>
Mon, 11 Sep 2017 13:51:40 +0000 (15:51 +0200)
committersfan5 <sfan5@live.de>
Tue, 12 Sep 2017 17:31:46 +0000 (19:31 +0200)
src/nodedef.cpp
src/nodedef.h
src/script/cpp_api/s_env.cpp
src/script/lua_api/l_env.cpp
src/script/lua_api/l_env.h
src/serverenvironment.cpp
src/serverenvironment.h

index e547e31b131db5b74375ade37727940e9268ec82..d13f93068a3829f2bcd854d641aaed7b893bfe2d 100644 (file)
@@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gamedef.h"
 #include "mapnode.h"
 #include <fstream> // Used in applyTextureOverrides()
+#include <algorithm>
 
 /*
        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<content_t> &result) const;
+       virtual bool getIds(const std::string &name, std::vector<content_t> &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<std::string, content_t> 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<std::string, GroupItems> m_group_to_items;
+       std::unordered_map<std::string, std::vector<content_t>> 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<content_t> &result) const
+               std::vector<content_t> &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<std::string, GroupItems>::const_iterator
+       std::unordered_map<std::string, std::vector<content_t>>::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<content_t> &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<std::string, GroupItems>::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<std::string, GroupItems>::iterator iter_groups =
+       for (std::unordered_map<std::string, std::vector<content_t>>::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<content_t> &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<std::string>::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<content_t> *result_out,
                                success = false;
                        }
                } else {
-                       std::set<content_t> cids;
-                       std::set<content_t>::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);
                }
        }
 
index 853b9bdddeb199025854871b2457dfbbe57afffb..23100a2ed6ceb2a6cbaac981cac8c0ce2fda90e3 100644 (file)
@@ -23,7 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <string>
 #include <iostream>
 #include <map>
-#include <list>
 #include "mapnode.h"
 #ifndef SERVER
 #include "client/tile.h"
@@ -42,8 +41,6 @@ class IShaderSource;
 class IGameDef;
 class NodeResolver;
 
-typedef std::list<std::pair<content_t, int> > GroupItems;
-
 enum ContentParamType
 {
        CPT_NONE,
@@ -290,7 +287,7 @@ struct ContentFeatures
        // for NDT_CONNECTED pairing
        u8 connect_sides;
        std::vector<std::string> connects_to;
-       std::set<content_t> connects_to_ids;
+       std::vector<content_t> 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<content_t> &result)
+       virtual bool getIds(const std::string &name, std::vector<content_t> &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<content_t> &result)
+       virtual bool getIds(const std::string &name, std::vector<content_t> &result)
                const=0;
        // If not found, returns the features of CONTENT_UNKNOWN
        virtual const ContentFeatures &get(const std::string &name) const=0;
index b1404bf22d791f46986b66a3775708ad921cc9a1..517892b038c70e28ed2cb58e554e79c4477803aa 100644 (file)
@@ -108,7 +108,7 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env)
                int id = lua_tonumber(L, -2);
                int current_abm = lua_gettop(L);
 
-               std::set<std::string> trigger_contents;
+               std::vector<std::string> 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<std::string> required_neighbors;
+               std::vector<std::string> 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);
 
index be92365acf5c06ccacfd4943f4d5c1489837e70c..1d0716484c67cac0e1d4e28537cd9c55e9312284 100644 (file)
@@ -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<content_t> filter;
+       std::vector<content_t> 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<content_t> filter;
+       std::vector<content_t> 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<content_t, u32> individual_count;
+       std::vector<u32> 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<content_t>::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<content_t> filter;
+       std::vector<content_t> 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);
                        }
index 4d295b6eba85741d62e04ff82af1d6f66a86982c..6cfdc0f6d7a340e742011a0c8c98cc6b11bc060e 100644 (file)
@@ -188,15 +188,15 @@ class LuaABM : public ActiveBlockModifier {
 private:
        int m_id;
 
-       std::set<std::string> m_trigger_contents;
-       std::set<std::string> m_required_neighbors;
+       std::vector<std::string> m_trigger_contents;
+       std::vector<std::string> 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<std::string> &trigger_contents,
-                       const std::set<std::string> &required_neighbors,
+                       const std::vector<std::string> &trigger_contents,
+                       const std::vector<std::string> &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<std::string> &getTriggerContents() const
+       virtual const std::vector<std::string> &getTriggerContents() const
        {
                return m_trigger_contents;
        }
-       virtual const std::set<std::string> &getRequiredNeighbors() const
+       virtual const std::vector<std::string> &getRequiredNeighbors() const
        {
                return m_required_neighbors;
        }
index 7d95b828004a63d2447ebb09a4ad218fc0685284..1abe5054cf5e57245e3f9b742f020a573330f1e0 100644 (file)
@@ -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 <algorithm>
 
 #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<content_t> c_ids;
+               std::vector<content_t> 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<content_t> required_neighbors;
+       std::vector<content_t> 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<std::string> &required_neighbors_s =
+                       const std::vector<std::string> &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<std::string> &contents_s = abm->getTriggerContents();
+                       const std::vector<std::string> &contents_s = abm->getTriggerContents();
                        for (const std::string &content_s : contents_s) {
-                               std::set<content_t> ids;
+                               std::vector<content_t> 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<content_t>::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;
index 0eabfc08fa0867cc24b49cca89ac90a31daa7b5d..3fdd6d77ee4efe87ba5d8c8984506fdb4c5a799a 100644 (file)
@@ -53,10 +53,10 @@ public:
        virtual ~ActiveBlockModifier() = default;
 
        // Set of contents to trigger on
-       virtual const std::set<std::string> &getTriggerContents() const = 0;
+       virtual const std::vector<std::string> &getTriggerContents() const = 0;
        // Set of required neighbors (trigger doesn't happen if none are found)
        // Empty = do not check neighbors
-       virtual const std::set<std::string> &getRequiredNeighbors() const = 0;
+       virtual const std::vector<std::string> &getRequiredNeighbors() const = 0;
        // Trigger interval in seconds
        virtual float getTriggerInterval() = 0;
        // Random chance of (1 / return value), 0 is disallowed