diff --git a/src/map.cpp b/src/map.cpp index bc2b337aa..e0efeedf4 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -174,22 +174,30 @@ MapNode Map::getNode(v3s16 p, bool *is_valid_position) return node; } +static void set_node_in_block(MapBlock *block, v3s16 relpos, MapNode n) +{ + // 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<<"Not allowing to place CONTENT_IGNORE" + <<" while trying to replace \"" + <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; - // Never allow placing CONTENT_IGNORE, it causes problems - if(n.getContent() == CONTENT_IGNORE){ - bool temp_bool; - errorstream<<"Map::setNode(): Not allowing to place CONTENT_IGNORE" - <<" while trying to replace \"" - <get(block->getNodeNoCheck(relpos, &temp_bool)).name - <<"\" at "<setNodeNoCheck(relpos, n); + set_node_in_block(block, relpos, n); } void Map::addNodeAndUpdate(v3s16 p, MapNode n, @@ -201,8 +209,14 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, RollbackNode rollback_oldnode(this, p, m_gamedef); #endif + 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) { @@ -210,18 +224,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); + 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); - // Update lighting - std::vector > oldnodes; - oldnodes.emplace_back(p, oldnode); - voxalgo::update_lighting_nodes(this, oldnodes, modified_blocks); + 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); - for (auto &modified_block : modified_blocks) { - modified_block.second->expireDayNightDiff(); + // 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(); + } } #if USE_SQLITE diff --git a/src/nodedef.h b/src/nodedef.h index ef268e7bd..7558fa8c7 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -471,6 +471,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);