From 11aab4198be1a0f1104a433896e908e4c86de0c9 Mon Sep 17 00:00:00 2001 From: Jude Melton-Houghton Date: Tue, 29 Mar 2022 12:06:44 -0400 Subject: Optimize swapping nodes with equivalent lighting --- src/map.cpp | 65 +++++++++++++++++++++++++++++++++++++++++------------------ src/nodedef.h | 6 ++++++ 2 files changed, 51 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/map.cpp b/src/map.cpp index a11bbb96a..1cbc55707 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -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 \"" - <get(block->getNodeNoCheck(relpos, &temp_bool)).name + <get(block->getNodeNoCheck(relpos, &temp_bool)).name <<"\" at "<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 &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 > 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 > 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 diff --git a/src/nodedef.h b/src/nodedef.h index ea50d4281..f90caff8a 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -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); -- cgit v1.2.3