mirror of
https://github.com/minetest/minetest.git
synced 2024-11-23 16:13:46 +01:00
Safely handle block deletion (#13315)
Co-authored-by: Jude Melton-Houghton <jwmhjwmh@gmail.com>
This commit is contained in:
parent
f3b198e490
commit
ed632f3854
23
src/map.cpp
23
src/map.cpp
@ -1309,6 +1309,8 @@ ServerMap::~ServerMap()
|
|||||||
*/
|
*/
|
||||||
delete dbase;
|
delete dbase;
|
||||||
delete dbase_ro;
|
delete dbase_ro;
|
||||||
|
|
||||||
|
deleteDetachedBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
MapgenParams *ServerMap::getMapgenParams()
|
MapgenParams *ServerMap::getMapgenParams()
|
||||||
@ -1888,12 +1890,31 @@ bool ServerMap::deleteBlock(v3s16 blockpos)
|
|||||||
MapSector *sector = getSectorNoGenerate(p2d);
|
MapSector *sector = getSectorNoGenerate(p2d);
|
||||||
if (!sector)
|
if (!sector)
|
||||||
return false;
|
return false;
|
||||||
sector->deleteBlock(block);
|
// It may not be safe to delete the block from memory at the moment
|
||||||
|
// (pointers to it could still be in use)
|
||||||
|
sector->detachBlock(block);
|
||||||
|
m_detached_blocks.push_back(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerMap::deleteDetachedBlocks()
|
||||||
|
{
|
||||||
|
for (MapBlock *block : m_detached_blocks) {
|
||||||
|
assert(block->isOrphan());
|
||||||
|
delete block;
|
||||||
|
}
|
||||||
|
m_detached_blocks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerMap::step()
|
||||||
|
{
|
||||||
|
// Delete from memory blocks removed by deleteBlocks() only when pointers
|
||||||
|
// to them are (probably) no longer in use
|
||||||
|
deleteDetachedBlocks();
|
||||||
|
}
|
||||||
|
|
||||||
void ServerMap::PrintInfo(std::ostream &out)
|
void ServerMap::PrintInfo(std::ostream &out)
|
||||||
{
|
{
|
||||||
out<<"ServerMap: ";
|
out<<"ServerMap: ";
|
||||||
|
10
src/map.h
10
src/map.h
@ -412,8 +412,15 @@ public:
|
|||||||
// Database version
|
// Database version
|
||||||
void loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load=false);
|
void loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load=false);
|
||||||
|
|
||||||
|
// Blocks are removed from the map but not deleted from memory until
|
||||||
|
// deleteDetachedBlocks() is called, since pointers to them may still exist
|
||||||
|
// when deleteBlock() is called.
|
||||||
bool deleteBlock(v3s16 blockpos) override;
|
bool deleteBlock(v3s16 blockpos) override;
|
||||||
|
|
||||||
|
void deleteDetachedBlocks();
|
||||||
|
|
||||||
|
void step();
|
||||||
|
|
||||||
void updateVManip(v3s16 pos);
|
void updateVManip(v3s16 pos);
|
||||||
|
|
||||||
// For debug printing
|
// For debug printing
|
||||||
@ -457,6 +464,9 @@ private:
|
|||||||
|
|
||||||
std::set<v3s16> m_chunks_in_progress;
|
std::set<v3s16> m_chunks_in_progress;
|
||||||
|
|
||||||
|
// used by deleteBlock() and deleteDetachedBlocks()
|
||||||
|
MapBlockVect m_detached_blocks;
|
||||||
|
|
||||||
// Queued transforming water nodes
|
// Queued transforming water nodes
|
||||||
UniqueQueue<v3s16> m_transforming_liquid;
|
UniqueQueue<v3s16> m_transforming_liquid;
|
||||||
f32 m_transforming_liquid_loop_count_multiplier = 1.0f;
|
f32 m_transforming_liquid_loop_count_multiplier = 1.0f;
|
||||||
|
@ -81,11 +81,24 @@ public:
|
|||||||
return NODECONTAINER_ID_MAPBLOCK;
|
return NODECONTAINER_ID_MAPBLOCK;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
Map * getParent()
|
Map *getParent()
|
||||||
{
|
{
|
||||||
return m_parent;
|
return m_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Any server-modding code can "delete" arbitrary blocks (i.e. with
|
||||||
|
// core.delete_area), which makes them orphan. Avoid using orphan blocks for
|
||||||
|
// anything.
|
||||||
|
bool isOrphan() const
|
||||||
|
{
|
||||||
|
return !m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeOrphan()
|
||||||
|
{
|
||||||
|
m_parent = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void reallocate()
|
void reallocate()
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < nodecount; i++)
|
for (u32 i = 0; i < nodecount; i++)
|
||||||
|
@ -109,6 +109,12 @@ void MapSector::insertBlock(MapBlock *block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MapSector::deleteBlock(MapBlock *block)
|
void MapSector::deleteBlock(MapBlock *block)
|
||||||
|
{
|
||||||
|
detachBlock(block);
|
||||||
|
delete block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapSector::detachBlock(MapBlock *block)
|
||||||
{
|
{
|
||||||
s16 block_y = block->getPos().Y;
|
s16 block_y = block->getPos().Y;
|
||||||
|
|
||||||
@ -118,8 +124,8 @@ void MapSector::deleteBlock(MapBlock *block)
|
|||||||
// Remove from container
|
// Remove from container
|
||||||
m_blocks.erase(block_y);
|
m_blocks.erase(block_y);
|
||||||
|
|
||||||
// Delete
|
// Mark as removed
|
||||||
delete block;
|
block->makeOrphan();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapSector::getBlocks(MapBlockVect &dest)
|
void MapSector::getBlocks(MapBlockVect &dest)
|
||||||
|
@ -58,6 +58,9 @@ public:
|
|||||||
|
|
||||||
void deleteBlock(MapBlock *block);
|
void deleteBlock(MapBlock *block);
|
||||||
|
|
||||||
|
// Remove a block from the map and the sector without deleting it
|
||||||
|
void detachBlock(MapBlock *block);
|
||||||
|
|
||||||
void getBlocks(MapBlockVect &dest);
|
void getBlocks(MapBlockVect &dest);
|
||||||
|
|
||||||
bool empty() const { return m_blocks.empty(); }
|
bool empty() const { return m_blocks.empty(); }
|
||||||
|
@ -666,6 +666,11 @@ void Server::AsyncRunStep(bool initial_step)
|
|||||||
-1);
|
-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note: Orphan MapBlock ptrs become dangling after this call.
|
||||||
|
*/
|
||||||
|
m_env->getServerMap().step();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Listen to the admin chat, if available
|
Listen to the admin chat, if available
|
||||||
*/
|
*/
|
||||||
|
@ -282,6 +282,8 @@ void LBMManager::applyLBMs(ServerEnvironment *env, MapBlock *block,
|
|||||||
continue;
|
continue;
|
||||||
for (auto lbmdef : *lbm_list) {
|
for (auto lbmdef : *lbm_list) {
|
||||||
lbmdef->trigger(env, pos + pos_of_block, n, dtime_s);
|
lbmdef->trigger(env, pos + pos_of_block, n, dtime_s);
|
||||||
|
if (block->isOrphan())
|
||||||
|
return;
|
||||||
n = block->getNodeNoCheck(pos);
|
n = block->getNodeNoCheck(pos);
|
||||||
if (n.getContent() != c)
|
if (n.getContent() != c)
|
||||||
break; // The node was changed and the LBMs no longer apply
|
break; // The node was changed and the LBMs no longer apply
|
||||||
@ -966,6 +968,9 @@ public:
|
|||||||
aabm.abm->trigger(m_env, p, n,
|
aabm.abm->trigger(m_env, p, n,
|
||||||
active_object_count, active_object_count_wider);
|
active_object_count, active_object_count_wider);
|
||||||
|
|
||||||
|
if (block->isOrphan())
|
||||||
|
return;
|
||||||
|
|
||||||
// Count surrounding objects again if the abms added any
|
// Count surrounding objects again if the abms added any
|
||||||
if(m_env->m_added_objects > 0) {
|
if(m_env->m_added_objects > 0) {
|
||||||
active_object_count = countObjects(block, map, active_object_count_wider);
|
active_object_count = countObjects(block, map, active_object_count_wider);
|
||||||
@ -1016,13 +1021,17 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
|
|||||||
|
|
||||||
// Activate stored objects
|
// Activate stored objects
|
||||||
activateObjects(block, dtime_s);
|
activateObjects(block, dtime_s);
|
||||||
|
if (block->isOrphan())
|
||||||
|
return;
|
||||||
|
|
||||||
/* Handle LoadingBlockModifiers */
|
/* Handle LoadingBlockModifiers */
|
||||||
m_lbm_mgr.applyLBMs(this, block, stamp, (float)dtime_s);
|
m_lbm_mgr.applyLBMs(this, block, stamp, (float)dtime_s);
|
||||||
|
if (block->isOrphan())
|
||||||
|
return;
|
||||||
|
|
||||||
// Run node timers
|
// Run node timers
|
||||||
block->step((float)dtime_s, [&](v3s16 p, MapNode n, f32 d) -> bool {
|
block->step((float)dtime_s, [&](v3s16 p, MapNode n, f32 d) -> bool {
|
||||||
return m_script->node_on_timer(p, n, d);
|
return !block->isOrphan() && m_script->node_on_timer(p, n, d);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1996,6 +2005,8 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
|
|||||||
<< " type=" << (int)s_obj.type << std::endl;
|
<< " type=" << (int)s_obj.type << std::endl;
|
||||||
// This will also add the object to the active static list
|
// This will also add the object to the active static list
|
||||||
addActiveObjectRaw(obj, false, dtime_s);
|
addActiveObjectRaw(obj, false, dtime_s);
|
||||||
|
if (block->isOrphan())
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear stored list
|
// Clear stored list
|
||||||
|
Loading…
Reference in New Issue
Block a user