]> git.lizzy.rs Git - dragonfireclient.git/commitdiff
Optimize swapping nodes with equivalent lighting
authorJude Melton-Houghton <jwmhjwmh@gmail.com>
Tue, 29 Mar 2022 16:06:44 +0000 (12:06 -0400)
committerGitHub <noreply@github.com>
Tue, 29 Mar 2022 16:06:44 +0000 (18:06 +0200)
src/map.cpp
src/nodedef.h

index a11bbb96a27e50130885c318aca9c469ae6f2b07..1cbc557078c7ce3a9ca15dc039d5c1106d391a46 100644 (file)
@@ -165,24 +165,32 @@ MapNode Map::getNode(v3s16 p, bool *is_valid_position)
        return node;
 }
 
-// throws InvalidPositionException if not found
-void Map::setNode(v3s16 p, MapNode & n)
+static void set_node_in_block(MapBlock *block, v3s16 relpos, MapNode n)
 {
-       v3s16 blockpos = getNodeBlockPos(p);
-       MapBlock *block = getBlockNoCreate(blockpos);
-       v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
        // Never allow placing CONTENT_IGNORE, it causes problems
        if(n.getContent() == CONTENT_IGNORE){
+               const NodeDefManager *nodedef = block->getParent()->getNodeDefManager();
+               v3s16 blockpos = block->getPos();
+               v3s16 p = blockpos * MAP_BLOCKSIZE + relpos;
                bool temp_bool;
-               errorstream<<"Map::setNode(): Not allowing to place CONTENT_IGNORE"
+               errorstream<<"Not allowing to place CONTENT_IGNORE"
                                <<" while trying to replace \""
-                               <<m_nodedef->get(block->getNodeNoCheck(relpos, &temp_bool)).name
+                               <<nodedef->get(block->getNodeNoCheck(relpos, &temp_bool)).name
                                <<"\" at "<<PP(p)<<" (block "<<PP(blockpos)<<")"<<std::endl;
                return;
        }
        block->setNodeNoCheck(relpos, n);
 }
 
+// throws InvalidPositionException if not found
+void Map::setNode(v3s16 p, MapNode & n)
+{
+       v3s16 blockpos = getNodeBlockPos(p);
+       MapBlock *block = getBlockNoCreate(blockpos);
+       v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
+       set_node_in_block(block, relpos, n);
+}
+
 void Map::addNodeAndUpdate(v3s16 p, MapNode n,
                std::map<v3s16, MapBlock*> &modified_blocks,
                bool remove_metadata)
@@ -190,8 +198,14 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
        // Collect old node for rollback
        RollbackNode rollback_oldnode(this, p, m_gamedef);
 
+       v3s16 blockpos = getNodeBlockPos(p);
+       MapBlock *block = getBlockNoCreate(blockpos);
+       if (block->isDummy())
+               throw InvalidPositionException();
+       v3s16 relpos = p - blockpos * MAP_BLOCKSIZE;
+
        // This is needed for updating the lighting
-       MapNode oldnode = getNode(p);
+       MapNode oldnode = block->getNodeUnsafe(relpos);
 
        // Remove node metadata
        if (remove_metadata) {
@@ -199,18 +213,29 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
        }
 
        // Set the node on the map
-       // Ignore light (because calling voxalgo::update_lighting_nodes)
-       n.setLight(LIGHTBANK_DAY, 0, m_nodedef);
-       n.setLight(LIGHTBANK_NIGHT, 0, m_nodedef);
-       setNode(p, n);
-
-       // Update lighting
-       std::vector<std::pair<v3s16, MapNode> > oldnodes;
-       oldnodes.emplace_back(p, oldnode);
-       voxalgo::update_lighting_nodes(this, oldnodes, modified_blocks);
-
-       for (auto &modified_block : modified_blocks) {
-               modified_block.second->expireDayNightDiff();
+       const ContentFeatures &cf = m_nodedef->get(n);
+       const ContentFeatures &oldcf = m_nodedef->get(oldnode);
+       if (cf.lightingEquivalent(oldcf)) {
+               // No light update needed, just copy over the old light.
+               n.setLight(LIGHTBANK_DAY, oldnode.getLightRaw(LIGHTBANK_DAY, oldcf), cf);
+               n.setLight(LIGHTBANK_NIGHT, oldnode.getLightRaw(LIGHTBANK_NIGHT, oldcf), cf);
+               set_node_in_block(block, relpos, n);
+
+               modified_blocks[blockpos] = block;
+       } else {
+               // Ignore light (because calling voxalgo::update_lighting_nodes)
+               n.setLight(LIGHTBANK_DAY, 0, cf);
+               n.setLight(LIGHTBANK_NIGHT, 0, cf);
+               set_node_in_block(block, relpos, n);
+
+               // Update lighting
+               std::vector<std::pair<v3s16, MapNode> > oldnodes;
+               oldnodes.emplace_back(p, oldnode);
+               voxalgo::update_lighting_nodes(this, oldnodes, modified_blocks);
+
+               for (auto &modified_block : modified_blocks) {
+                       modified_block.second->expireDayNightDiff();
+               }
        }
 
        // Report for rollback
index ea50d428137e14034d799fe5ca52191a057f7504..f90caff8aea500daa4f59271cf1edb0b3d3881dc 100644 (file)
@@ -478,6 +478,12 @@ struct ContentFeatures
                return (liquid_alternative_flowing_id == f.liquid_alternative_flowing_id);
        }
 
+       bool lightingEquivalent(const ContentFeatures &other) const {
+               return light_propagates == other.light_propagates
+                               && sunlight_propagates == other.sunlight_propagates
+                               && light_source == other.light_source;
+       }
+
        int getGroup(const std::string &group) const
        {
                return itemgroup_get(groups, group);