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
This commit is contained in:
lhofhansl 2024-02-22 21:47:42 -08:00 committed by GitHub
parent 0d30a3071a
commit 0d4b489545
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 52 additions and 75 deletions

View File

@ -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 # At this distance the server will aggressively optimize which blocks are sent to
# clients. # clients.
# Small values potentially improve performance a lot, at the expense of visible # 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, # rendering glitches (some blocks might not be rendered correctly in caves).
# as well as sometimes on land).
# Setting this to a value greater than max_block_send_distance disables this # Setting this to a value greater than max_block_send_distance disables this
# optimization. # optimization.
# Stated in MapBlocks (16 nodes). # Stated in MapBlocks (16 nodes).

View File

@ -228,12 +228,12 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
std::vector<std::pair<v3s16, MapNode> > oldnodes; std::vector<std::pair<v3s16, MapNode> > oldnodes;
oldnodes.emplace_back(p, oldnode); oldnodes.emplace_back(p, oldnode);
voxalgo::update_lighting_nodes(this, oldnodes, modified_blocks); 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 // Report for rollback
if(m_gamedef->rollback()) if(m_gamedef->rollback())
{ {
@ -1462,14 +1462,14 @@ void ServerMap::finishBlockMake(BlockMakeData *data,
if (!block) if (!block)
continue; continue;
/* /*
Update day/night difference cache of the MapBlocks Update is air cache of the MapBlocks
*/ */
block->expireDayNightDiff(); block->expireIsAirCache();
/* /*
Set block as modified Set block as modified
*/ */
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
MOD_REASON_EXPIRE_DAYNIGHTDIFF); MOD_REASON_EXPIRE_IS_AIR);
} }
/* /*
@ -2064,6 +2064,7 @@ void MMVManip::blitBackAll(std::map<v3s16, MapBlock*> *modified_blocks,
block->copyFrom(*this); block->copyFrom(*this);
block->raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_VMANIP); block->raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_VMANIP);
block->expireIsAirCache();
if(modified_blocks) if(modified_blocks)
(*modified_blocks)[p] = block; (*modified_blocks)[p] = block;

View File

@ -186,57 +186,27 @@ void MapBlock::copyFrom(VoxelManipulator &dst)
getPosRelative(), data_size); 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 bool only_air = true;
m_day_night_differs_expired = false;
bool differs = false;
/*
Check if any lighting value differs
*/
MapNode previous_n(CONTENT_IGNORE);
for (u32 i = 0; i < nodecount; i++) { for (u32 i = 0; i < nodecount; i++) {
MapNode n = data[i]; MapNode &n = data[i];
if (n.getContent() != CONTENT_AIR) {
// If node is identical to previous node, don't verify if it differs only_air = false;
if (n == previous_n)
continue;
differs = !n.isLightDayNightEq(nodemgr->getLightingFlags(n));
if (differs)
break; 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 // 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; u8 flags = 0;
if(is_underground) if(is_underground)
flags |= 0x01; 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; flags |= 0x02;
if (!m_generated) if (!m_generated)
flags |= 0x08; flags |= 0x08;
@ -473,7 +448,7 @@ void MapBlock::deSerialize(std::istream &in_compressed, u8 version, bool disk)
TRACESTREAM(<<"MapBlock::deSerialize "<<getPos()<<std::endl); TRACESTREAM(<<"MapBlock::deSerialize "<<getPos()<<std::endl);
m_day_night_differs_expired = false; m_is_air_expired = true;
if(version <= 21) if(version <= 21)
{ {
@ -489,7 +464,9 @@ void MapBlock::deSerialize(std::istream &in_compressed, u8 version, bool disk)
u8 flags = readU8(is); u8 flags = readU8(is);
is_underground = (flags & 0x01) != 0; is_underground = (flags & 0x01) != 0;
m_day_night_differs = (flags & 0x02) != 0; // IMPORTANT: when the version is bumped to 30 we can read m_is_air from here
// m_is_air = (flags & 0x02) == 0;
if (version < 27) if (version < 27)
m_lighting_complete = 0xFFFF; m_lighting_complete = 0xFFFF;
else else
@ -599,6 +576,10 @@ void MapBlock::deSerialize(std::istream &in_compressed, u8 version, bool disk)
<<": Node timers (ver>=25)"<<std::endl); <<": Node timers (ver>=25)"<<std::endl);
m_node_timers.deSerialize(is, version); m_node_timers.deSerialize(is, version);
} }
u16 dummy;
m_is_air = nimap.size() == 1 && nimap.getId("air", dummy);
m_is_air_expired = false;
} }
TRACESTREAM(<<"MapBlock::deSerialize "<<getPos() TRACESTREAM(<<"MapBlock::deSerialize "<<getPos()
@ -647,7 +628,7 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk)
{ {
// Initialize default flags // Initialize default flags
is_underground = false; is_underground = false;
m_day_night_differs = false; m_is_air = false;
m_lighting_complete = 0xFFFF; m_lighting_complete = 0xFFFF;
m_generated = true; m_generated = true;
@ -713,7 +694,6 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk)
u8 flags; u8 flags;
is.read((char*)&flags, 1); is.read((char*)&flags, 1);
is_underground = (flags & 0x01) != 0; is_underground = (flags & 0x01) != 0;
m_day_night_differs = (flags & 0x02) != 0;
if (version >= 18) if (version >= 18)
m_generated = (flags & 0x08) == 0; 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 supported, read node definition id mapping
if (version >= 21) { if (version >= 21) {
nimap.deSerialize(is); nimap.deSerialize(is);
u16 dummy;
m_is_air = nimap.size() == 1 && nimap.getId("air", dummy);
// Else set the legacy mapping // Else set the legacy mapping
} else { } else {
content_mapnode_get_name_id_mapping(&nimap); content_mapnode_get_name_id_mapping(&nimap);
m_is_air = false;
m_is_air_expired = true;
} }
correctBlockNodeIds(&nimap, data, m_gamedef); correctBlockNodeIds(&nimap, data, m_gamedef);
} }

View File

@ -60,7 +60,7 @@ enum ModReason : u32 {
MOD_REASON_STATIC_DATA_ADDED = 1 << 13, MOD_REASON_STATIC_DATA_ADDED = 1 << 13,
MOD_REASON_STATIC_DATA_REMOVED = 1 << 14, MOD_REASON_STATIC_DATA_REMOVED = 1 << 14,
MOD_REASON_STATIC_DATA_CHANGED = 1 << 15, 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_VMANIP = 1 << 17,
MOD_REASON_UNKNOWN = 1 << 18, MOD_REASON_UNKNOWN = 1 << 18,
}; };
@ -310,20 +310,19 @@ public:
// Copies data from VoxelManipulator getPosRelative() // Copies data from VoxelManipulator getPosRelative()
void copyFrom(VoxelManipulator &dst); void copyFrom(VoxelManipulator &dst);
// Update day-night lighting difference flag. // Update is air flag.
// Sets m_day_night_differs to appropriate value. // Sets m_is_air to appropriate value.
// These methods don't care about neighboring blocks. void actuallyUpdateIsAir();
void actuallyUpdateDayNightDiff();
// Call this to schedule what the previous function does to be done // Call this to schedule what the previous function does to be done
// when the value is actually needed. // when the value is actually needed.
void expireDayNightDiff(); void expireIsAirCache();
inline bool getDayNightDiff() inline bool isAir()
{ {
if (m_day_night_differs_expired) if (m_is_air_expired)
actuallyUpdateDayNightDiff(); actuallyUpdateIsAir();
return m_day_night_differs; return m_is_air;
} }
bool onObjectsActivation(); bool onObjectsActivation();
@ -517,8 +516,8 @@ public:
private: private:
// Whether day and night lighting differs // Whether day and night lighting differs
bool m_day_night_differs = false; bool m_is_air = false;
bool m_day_night_differs_expired = true; bool m_is_air_expired = true;
/* /*
- On the server, this is used for telling whether the - On the server, this is used for telling whether the

View File

@ -354,18 +354,12 @@ void RemoteClient::GetNextBlocks (
continue; continue;
/* /*
If block is not close, don't send it unless it is near If block is not close, don't send it if it
ground level. consists of air only.
Block is near ground level if night-time mesh
differs from day-time mesh.
*/ */
if (d >= d_opt) { if (d >= d_opt && block->isAir())
if (!block->getIsUnderground() && !block->getDayNightDiff())
continue; continue;
}
} }
/* /*
Check occlusion cache first. Check occlusion cache first.
*/ */