Cache liquid alternative IDs (#8053)
authorVitaliy <numzer0@yandex.ru>
Wed, 20 May 2020 21:52:10 +0000 (00:52 +0300)
committerGitHub <noreply@github.com>
Wed, 20 May 2020 21:52:10 +0000 (22:52 +0100)
src/client/content_mapblock.cpp
src/map.cpp
src/mapnode.cpp
src/nodedef.cpp
src/nodedef.h
src/server.cpp

index bf1b4c7d6ba97ac2159d719d44789bbbf83b1087..50efd2e4066daa6b515217937c9f8d7feefae265 100644 (file)
@@ -405,8 +405,8 @@ void MapblockMeshGenerator::prepareLiquidNodeDrawing()
 
        MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(p.X, p.Y + 1, p.Z));
        MapNode nbottom = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(p.X, p.Y - 1, p.Z));
-       c_flowing = nodedef->getId(f->liquid_alternative_flowing);
-       c_source = nodedef->getId(f->liquid_alternative_source);
+       c_flowing = f->liquid_alternative_flowing_id;
+       c_source = f->liquid_alternative_source_id;
        top_is_same_liquid = (ntop.getContent() == c_flowing) || (ntop.getContent() == c_source);
        draw_liquid_bottom = (nbottom.getContent() != c_flowing) && (nbottom.getContent() != c_source);
        if (draw_liquid_bottom) {
index 5f1b984a43952a12d821dee733d616435ecddb2c..677cbc869a785f8d381a663aeff5d16d86196ef9 100644 (file)
@@ -568,7 +568,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
                switch (liquid_type) {
                        case LIQUID_SOURCE:
                                liquid_level = LIQUID_LEVEL_SOURCE;
-                               liquid_kind = m_nodedef->getId(cf.liquid_alternative_flowing);
+                               liquid_kind = cf.liquid_alternative_flowing_id;
                                break;
                        case LIQUID_FLOWING:
                                liquid_level = (n0.param2 & LIQUID_LEVEL_MASK);
@@ -641,8 +641,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
                                case LIQUID_SOURCE:
                                        // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
                                        if (liquid_kind == CONTENT_AIR)
-                                               liquid_kind = m_nodedef->getId(cfnb.liquid_alternative_flowing);
-                                       if (m_nodedef->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
+                                               liquid_kind = cfnb.liquid_alternative_flowing_id;
+                                       if (cfnb.liquid_alternative_flowing_id != liquid_kind) {
                                                neutrals[num_neutrals++] = nb;
                                        } else {
                                                // Do not count bottom source, it will screw things up
@@ -653,8 +653,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
                                case LIQUID_FLOWING:
                                        // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
                                        if (liquid_kind == CONTENT_AIR)
-                                               liquid_kind = m_nodedef->getId(cfnb.liquid_alternative_flowing);
-                                       if (m_nodedef->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
+                                               liquid_kind = cfnb.liquid_alternative_flowing_id;
+                                       if (cfnb.liquid_alternative_flowing_id != liquid_kind) {
                                                neutrals[num_neutrals++] = nb;
                                        } else {
                                                flows[num_flows++] = nb;
@@ -680,7 +680,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
                        // liquid_kind will be set to either the flowing alternative of the node (if it's a liquid)
                        // or the flowing alternative of the first of the surrounding sources (if it's air), so
                        // it's perfectly safe to use liquid_kind here to determine the new node content.
-                       new_node_content = m_nodedef->getId(m_nodedef->get(liquid_kind).liquid_alternative_source);
+                       new_node_content = m_nodedef->get(liquid_kind).liquid_alternative_source_id;
                } else if (num_sources >= 1 && sources[0].t != NEIGHBOR_LOWER) {
                        // liquid_kind is set properly, see above
                        max_node_level = new_node_level = LIQUID_LEVEL_MAX;
index 24d62b5045ccfbf8aeb370370245b8aa965da1f0..dcf1f6d6ec2c2e46c8231a1812cdd6c7f31b718c 100644 (file)
@@ -622,10 +622,10 @@ s8 MapNode::setLevel(const NodeDefManager *nodemgr, s16 level)
                }
                if (level >= LIQUID_LEVEL_SOURCE) {
                        rest = level - LIQUID_LEVEL_SOURCE;
-                       setContent(nodemgr->getId(f.liquid_alternative_source));
+                       setContent(f.liquid_alternative_source_id);
                        setParam2(0);
                } else {
-                       setContent(nodemgr->getId(f.liquid_alternative_flowing));
+                       setContent(f.liquid_alternative_flowing_id);
                        setParam2((level & LIQUID_LEVEL_MASK) | (getParam2() & ~LIQUID_LEVEL_MASK));
                }
        } else if (f.param_type_2 == CPT2_LEVELED) {
index b8211fceb869a38d19ed348e5081bbc95ab26ef3..cb841e544732ca4c3f600d2802477665e25453b9 100644 (file)
@@ -371,7 +371,9 @@ void ContentFeatures::reset()
        leveled_max = LEVELED_MAX;
        liquid_type = LIQUID_NONE;
        liquid_alternative_flowing = "";
+       liquid_alternative_flowing_id = CONTENT_IGNORE;
        liquid_alternative_source = "";
+       liquid_alternative_source_id = CONTENT_IGNORE;
        liquid_viscosity = 0;
        liquid_renewable = true;
        liquid_range = LIQUID_LEVEL_MAX+1;
@@ -1444,6 +1446,10 @@ void NodeDefManager::deSerialize(std::istream &is)
                getNodeBoxUnion(f.selection_box, f, &m_selection_box_union);
                fixSelectionBoxIntUnion();
        }
+
+       // Since liquid_alternative_flowing_id and liquid_alternative_source_id
+       // are not sent, resolve them client-side too.
+       resolveCrossrefs();
 }
 
 
@@ -1504,15 +1510,28 @@ void NodeDefManager::resetNodeResolveState()
        m_pending_resolve_callbacks.clear();
 }
 
-void NodeDefManager::mapNodeboxConnections()
+static void removeDupes(std::vector<content_t> &list)
+{
+       std::sort(list.begin(), list.end());
+       auto new_end = std::unique(list.begin(), list.end());
+       list.erase(new_end, list.end());
+}
+
+void NodeDefManager::resolveCrossrefs()
 {
        for (ContentFeatures &f : m_content_features) {
+               if (f.liquid_type != LIQUID_NONE) {
+                       f.liquid_alternative_flowing_id = getId(f.liquid_alternative_flowing);
+                       f.liquid_alternative_source_id = getId(f.liquid_alternative_source);
+                       continue;
+               }
                if (f.drawtype != NDT_NODEBOX || f.node_box.type != NODEBOX_CONNECTED)
                        continue;
 
                for (const std::string &name : f.connects_to) {
                        getIds(name, f.connects_to_ids);
                }
+               removeDupes(f.connects_to_ids);
        }
 }
 
index 497e7ee0e01956918795748f6d5f607f5a013036..0992001e1585f8e2978b750402d510a733796c8e 100644 (file)
@@ -368,8 +368,10 @@ struct ContentFeatures
        enum LiquidType liquid_type;
        // If the content is liquid, this is the flowing version of the liquid.
        std::string liquid_alternative_flowing;
+       content_t liquid_alternative_flowing_id;
        // If the content is liquid, this is the source version of the liquid.
        std::string liquid_alternative_source;
+       content_t liquid_alternative_source_id;
        // Viscosity for fluid flow, ranging from 1 to 7, with
        // 1 giving almost instantaneous propagation and 7 being
        // the slowest possible
@@ -428,7 +430,7 @@ struct ContentFeatures
        }
        bool sameLiquid(const ContentFeatures &f) const{
                if(!isLiquid() || !f.isLiquid()) return false;
-               return (liquid_alternative_flowing == f.liquid_alternative_flowing);
+               return (liquid_alternative_flowing_id == f.liquid_alternative_flowing_id);
        }
 
        int getGroup(const std::string &group) const
@@ -641,10 +643,11 @@ public:
        void resetNodeResolveState();
 
        /*!
-        * Resolves the IDs to which connecting nodes connect from names.
+        * Resolves (caches the IDs) cross-references between nodes,
+        * like liquid alternatives.
         * Must be called after node registration has finished!
         */
-       void mapNodeboxConnections();
+       void resolveCrossrefs();
 
 private:
        /*!
index b28c30e1e2840b69e9aa08130b0a06d83aa55954..92870f972b9c91aef7d746f570d6f72201a044fe 100644 (file)
@@ -412,8 +412,8 @@ void Server::init()
        // Perform pending node name resolutions
        m_nodedef->runNodeResolveCallbacks();
 
-       // unmap node names for connected nodeboxes
-       m_nodedef->mapNodeboxConnections();
+       // unmap node names in cross-references
+       m_nodedef->resolveCrossrefs();
 
        // init the recipe hashes to speed up crafting
        m_craftdef->initHashes(this);