1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-09-15 18:57:08 +00:00

Prevent MapBlocks in generation from being unloaded (#16339)

This change prevents issues arising from partial generation of MapChunks, which are liable to be regenerated completely when ungenerated MapBlocks within are encountered.

Co-authored-by: Po Lu <luangruo@yahoo.com>
Co-authored-by: sfan5 <sfan5@live.de>
This commit is contained in:
Montandalar 2025-09-05 02:57:29 +10:00 committed by GitHub
parent 2ef085967d
commit e86d2fea8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 52 additions and 18 deletions

View file

@ -737,6 +737,8 @@ void *EmergeThread::run()
if (!error) if (!error)
block = finishGen(pos, &bmdata, &modified_blocks); block = finishGen(pos, &bmdata, &modified_blocks);
else
m_map->cancelBlockMake(&bmdata);
if (!block || error) if (!block || error)
action = EMERGE_ERRORED; action = EMERGE_ERRORED;

View file

@ -201,8 +201,8 @@ bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data)
{ {
assert(data); assert(data);
s16 csize = getMapgenParams()->chunksize; s16 csize = getMapgenParams()->chunksize;
v3s16 bpmin = EmergeManager::getContainingChunk(blockpos, csize); const v3s16 bpmin = EmergeManager::getContainingChunk(blockpos, csize);
v3s16 bpmax = bpmin + v3s16(1, 1, 1) * (csize - 1); const v3s16 bpmax = bpmin + v3s16(1, 1, 1) * (csize - 1);
if (!m_chunks_in_progress.insert(bpmin).second) if (!m_chunks_in_progress.insert(bpmin).second)
return false; return false;
@ -210,11 +210,10 @@ bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data)
bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info; bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info;
EMERGE_DBG_OUT("initBlockMake(): " << bpmin << " - " << bpmax); EMERGE_DBG_OUT("initBlockMake(): " << bpmin << " - " << bpmax);
v3s16 extra_borders(1, 1, 1); const v3s16 full_bpmin = bpmin - EMERGE_EXTRA_BORDER;
v3s16 full_bpmin = bpmin - extra_borders; const v3s16 full_bpmax = bpmax + EMERGE_EXTRA_BORDER;
v3s16 full_bpmax = bpmax + extra_borders;
// Do nothing if not inside mapgen limits (+-1 because of neighbors) // Do nothing if not fully inside mapgen limits
if (blockpos_over_mapgen_limit(full_bpmin) || if (blockpos_over_mapgen_limit(full_bpmin) ||
blockpos_over_mapgen_limit(full_bpmax)) blockpos_over_mapgen_limit(full_bpmax))
return false; return false;
@ -246,6 +245,7 @@ bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data)
bool ug = m_emerge->isBlockUnderground(p); bool ug = m_emerge->isBlockUnderground(p);
block->setIsUnderground(ug); block->setIsUnderground(ug);
} }
block->refGrab();
} }
} }
@ -263,13 +263,28 @@ bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data)
return true; return true;
} }
void ServerMap::cancelBlockMake(BlockMakeData *data)
{
assert(data->vmanip); // no vmanip = initBlockMake did not complete (caller mistake)
const v3s16 full_bpmin = data->blockpos_min - EMERGE_EXTRA_BORDER;
const v3s16 full_bpmax = data->blockpos_max + EMERGE_EXTRA_BORDER;
for (s16 x = full_bpmin.X; x <= full_bpmax.X; x++)
for (s16 z = full_bpmin.Z; z <= full_bpmax.Z; z++)
for (s16 y = full_bpmin.Y; y <= full_bpmax.Y; y++) {
MapBlock *block = getBlockNoCreateNoEx(v3s16(x, y, z));
if (block)
block->refDrop();
}
}
void ServerMap::finishBlockMake(BlockMakeData *data, void ServerMap::finishBlockMake(BlockMakeData *data,
std::map<v3s16, MapBlock*> *changed_blocks, u32 now) std::map<v3s16, MapBlock*> *changed_blocks, u32 now)
{ {
assert(data); assert(data);
assert(changed_blocks); assert(changed_blocks);
v3s16 bpmin = data->blockpos_min; const v3s16 bpmin = data->blockpos_min;
v3s16 bpmax = data->blockpos_max; const v3s16 bpmax = data->blockpos_max;
bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info; bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info;
EMERGE_DBG_OUT("finishBlockMake(): " << bpmin << " - " << bpmax); EMERGE_DBG_OUT("finishBlockMake(): " << bpmin << " - " << bpmax);
@ -306,18 +321,31 @@ void ServerMap::finishBlockMake(BlockMakeData *data,
MOD_REASON_EXPIRE_IS_AIR); MOD_REASON_EXPIRE_IS_AIR);
} }
// Note: this does not apply to the extra border area const v3s16 full_bpmin = bpmin - EMERGE_EXTRA_BORDER;
for (s16 x = bpmin.X; x <= bpmax.X; x++) const v3s16 full_bpmax = bpmax + EMERGE_EXTRA_BORDER;
for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
for (s16 y = bpmin.Y; y <= bpmax.Y; y++) {
MapBlock *block = getBlockNoCreateNoEx(v3s16(x, y, z));
if (!block)
continue;
v3s16 bp;
for (bp.X = full_bpmin.X; bp.X <= full_bpmax.X; bp.X++)
for (bp.Z = full_bpmin.Z; bp.Z <= full_bpmax.Z; bp.Z++)
for (bp.Y = full_bpmin.Y; bp.Y <= full_bpmax.Y; bp.Y++) {
MapBlock *block = getBlockNoCreateNoEx(bp);
if (!block) {
warningstream << "ServerMap::finishBlockMake: block " << bp
<< " disappeared during generation" << std::endl;
continue;
}
block->refDrop();
/* Border blocks are grabbed during
generation but mustn't be marked generated. */
if (bp >= bpmin && bp <= bpmax) {
block->setGenerated(true); block->setGenerated(true);
// Set timestamp to ensure correct application of LBMs and other stuff // Set timestamp to ensure correct application
// of LBMs and other stuff.
block->setTimestampNoChangedFlag(now); block->setTimestampNoChangedFlag(now);
} }
}
m_chunks_in_progress.erase(bpmin); m_chunks_in_progress.erase(bpmin);
} }

View file

@ -67,6 +67,7 @@ public:
/// @param now current game time /// @param now current game time
void finishBlockMake(BlockMakeData *data, void finishBlockMake(BlockMakeData *data,
std::map<v3s16, MapBlock*> *changed_blocks, u32 now); std::map<v3s16, MapBlock*> *changed_blocks, u32 now);
void cancelBlockMake(BlockMakeData *data);
/* /*
Get a block from somewhere. Get a block from somewhere.
@ -169,6 +170,9 @@ protected:
private: private:
friend class ModApiMapgen; // for m_transforming_liquid friend class ModApiMapgen; // for m_transforming_liquid
// extra border area during mapgen (in blocks)
constexpr static v3s16 EMERGE_EXTRA_BORDER{1, 1, 1};
// Emerge manager // Emerge manager
EmergeManager *m_emerge; EmergeManager *m_emerge;