aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map.cpp65
-rw-r--r--src/nodedef.h6
2 files changed, 51 insertions, 20 deletions
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 \""
- <<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
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);