From 82e41378937378667cdbdda3ea9e8c1acb5822ea Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Thu, 21 May 2020 00:52:10 +0300 Subject: [PATCH] Cache liquid alternative IDs (#8053) --- src/client/content_mapblock.cpp | 4 ++-- src/map.cpp | 12 ++++++------ src/mapnode.cpp | 4 ++-- src/nodedef.cpp | 21 ++++++++++++++++++++- src/nodedef.h | 9 ++++++--- src/server.cpp | 4 ++-- 6 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index bf1b4c7d6..50efd2e40 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -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) { diff --git a/src/map.cpp b/src/map.cpp index 5f1b984a4..677cbc869 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -568,7 +568,7 @@ void Map::transformLiquids(std::map &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 &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 &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 &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; diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 24d62b504..dcf1f6d6e 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -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) { diff --git a/src/nodedef.cpp b/src/nodedef.cpp index b8211fceb..cb841e544 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -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 &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); } } diff --git a/src/nodedef.h b/src/nodedef.h index 497e7ee0e..0992001e1 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -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: /*! diff --git a/src/server.cpp b/src/server.cpp index b28c30e1e..92870f972 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -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);