From 0d4b4895457c0ba07ba0704ea39818c5bd1b1a2b Mon Sep 17 00:00:00 2001 From: lhofhansl Date: Thu, 22 Feb 2024 21:47:42 -0800 Subject: [PATCH] Detect air-only blocks instead of day/night differences (#14264) * Detect air-only blocks instead day/night differences * Write !is_air into the former day-night-diff bit on disk, so that old server can still read maps written by new servers * Only set is_air bit when reading from disk --- builtin/settingtypes.txt | 3 +- src/map.cpp | 15 ++++---- src/mapblock.cpp | 74 +++++++++++++++----------------------- src/mapblock.h | 23 ++++++------ src/server/clientiface.cpp | 12 ++----- 5 files changed, 52 insertions(+), 75 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 1daa6dc4d..474e56d6f 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -2091,8 +2091,7 @@ liquid_update (Liquid update tick) float 1.0 0.001 # At this distance the server will aggressively optimize which blocks are sent to # clients. # Small values potentially improve performance a lot, at the expense of visible -# rendering glitches (some blocks will not be rendered under water and in caves, -# as well as sometimes on land). +# rendering glitches (some blocks might not be rendered correctly in caves). # Setting this to a value greater than max_block_send_distance disables this # optimization. # Stated in MapBlocks (16 nodes). diff --git a/src/map.cpp b/src/map.cpp index 38003151e..9d3cc8376 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -228,12 +228,12 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, 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 (n.getContent() != oldnode.getContent() && + (oldnode.getContent() == CONTENT_AIR || n.getContent() == CONTENT_AIR)) + block->expireIsAirCache(); + // Report for rollback if(m_gamedef->rollback()) { @@ -1462,14 +1462,14 @@ void ServerMap::finishBlockMake(BlockMakeData *data, if (!block) continue; /* - Update day/night difference cache of the MapBlocks + Update is air cache of the MapBlocks */ - block->expireDayNightDiff(); + block->expireIsAirCache(); /* Set block as modified */ block->raiseModified(MOD_STATE_WRITE_NEEDED, - MOD_REASON_EXPIRE_DAYNIGHTDIFF); + MOD_REASON_EXPIRE_IS_AIR); } /* @@ -2064,6 +2064,7 @@ void MMVManip::blitBackAll(std::map *modified_blocks, block->copyFrom(*this); block->raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_VMANIP); + block->expireIsAirCache(); if(modified_blocks) (*modified_blocks)[p] = block; diff --git a/src/mapblock.cpp b/src/mapblock.cpp index ae7ff31c6..36210cad1 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -186,57 +186,27 @@ void MapBlock::copyFrom(VoxelManipulator &dst) getPosRelative(), data_size); } -void MapBlock::actuallyUpdateDayNightDiff() +void MapBlock::actuallyUpdateIsAir() { - const NodeDefManager *nodemgr = m_gamedef->ndef(); + // Running this function un-expires m_is_air + m_is_air_expired = false; - // Running this function un-expires m_day_night_differs - m_day_night_differs_expired = false; - - bool differs = false; - - /* - Check if any lighting value differs - */ - - MapNode previous_n(CONTENT_IGNORE); + bool only_air = true; for (u32 i = 0; i < nodecount; i++) { - MapNode n = data[i]; - - // If node is identical to previous node, don't verify if it differs - if (n == previous_n) - continue; - - differs = !n.isLightDayNightEq(nodemgr->getLightingFlags(n)); - if (differs) + MapNode &n = data[i]; + if (n.getContent() != CONTENT_AIR) { + only_air = false; break; - previous_n = n; - } - - /* - If some lighting values differ, check if the whole thing is - just air. If it is just air, differs = false - */ - if (differs) { - bool only_air = true; - for (u32 i = 0; i < nodecount; i++) { - MapNode &n = data[i]; - if (n.getContent() != CONTENT_AIR) { - only_air = false; - break; - } } - if (only_air) - differs = false; } // Set member variable - m_day_night_differs = differs; + m_is_air = only_air; } -void MapBlock::expireDayNightDiff() +void MapBlock::expireIsAirCache() { - m_day_night_differs_expired = true; + m_is_air_expired = true; } /* @@ -369,7 +339,12 @@ void MapBlock::serialize(std::ostream &os_compressed, u8 version, bool disk, int u8 flags = 0; if(is_underground) flags |= 0x01; - if(getDayNightDiff()) + // This flag used to be day-night-differs, and it is no longer used. + // We write it anyway so that old servers can still use this. + // Above ground isAir implies !day-night-differs, !isAir is good enough for old servers + // to check whether above ground blocks should be sent. + // See RemoteClient::getNextBlocks(...) + if(!isAir()) flags |= 0x02; if (!m_generated) flags |= 0x08; @@ -473,7 +448,7 @@ void MapBlock::deSerialize(std::istream &in_compressed, u8 version, bool disk) TRACESTREAM(<<"MapBlock::deSerialize "<=25)"<= 18) m_generated = (flags & 0x08) == 0; @@ -798,9 +778,13 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk) // If supported, read node definition id mapping if (version >= 21) { nimap.deSerialize(is); + u16 dummy; + m_is_air = nimap.size() == 1 && nimap.getId("air", dummy); // Else set the legacy mapping } else { content_mapnode_get_name_id_mapping(&nimap); + m_is_air = false; + m_is_air_expired = true; } correctBlockNodeIds(&nimap, data, m_gamedef); } diff --git a/src/mapblock.h b/src/mapblock.h index c88818498..a32f9b312 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -60,7 +60,7 @@ enum ModReason : u32 { MOD_REASON_STATIC_DATA_ADDED = 1 << 13, MOD_REASON_STATIC_DATA_REMOVED = 1 << 14, MOD_REASON_STATIC_DATA_CHANGED = 1 << 15, - MOD_REASON_EXPIRE_DAYNIGHTDIFF = 1 << 16, + MOD_REASON_EXPIRE_IS_AIR = 1 << 16, MOD_REASON_VMANIP = 1 << 17, MOD_REASON_UNKNOWN = 1 << 18, }; @@ -310,20 +310,19 @@ public: // Copies data from VoxelManipulator getPosRelative() void copyFrom(VoxelManipulator &dst); - // Update day-night lighting difference flag. - // Sets m_day_night_differs to appropriate value. - // These methods don't care about neighboring blocks. - void actuallyUpdateDayNightDiff(); + // Update is air flag. + // Sets m_is_air to appropriate value. + void actuallyUpdateIsAir(); // Call this to schedule what the previous function does to be done // when the value is actually needed. - void expireDayNightDiff(); + void expireIsAirCache(); - inline bool getDayNightDiff() + inline bool isAir() { - if (m_day_night_differs_expired) - actuallyUpdateDayNightDiff(); - return m_day_night_differs; + if (m_is_air_expired) + actuallyUpdateIsAir(); + return m_is_air; } bool onObjectsActivation(); @@ -517,8 +516,8 @@ public: private: // Whether day and night lighting differs - bool m_day_night_differs = false; - bool m_day_night_differs_expired = true; + bool m_is_air = false; + bool m_is_air_expired = true; /* - On the server, this is used for telling whether the diff --git a/src/server/clientiface.cpp b/src/server/clientiface.cpp index 22e3e42d0..451e74407 100644 --- a/src/server/clientiface.cpp +++ b/src/server/clientiface.cpp @@ -354,18 +354,12 @@ void RemoteClient::GetNextBlocks ( continue; /* - If block is not close, don't send it unless it is near - ground level. - - Block is near ground level if night-time mesh - differs from day-time mesh. + If block is not close, don't send it if it + consists of air only. */ - if (d >= d_opt) { - if (!block->getIsUnderground() && !block->getDayNightDiff()) + if (d >= d_opt && block->isAir()) continue; - } } - /* Check occlusion cache first. */