diff options
-rw-r--r-- | src/map.cpp | 65 | ||||
-rw-r--r-- | src/nodedef.h | 6 |
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); |