Handle static_save changes at runtime and between restarts

This commit is contained in:
sfan5 2024-03-02 09:54:53 +01:00
parent 2386bfda7e
commit 8339594206
3 changed files with 49 additions and 26 deletions

View File

@ -229,6 +229,10 @@ public:
/*
Whether the object's static data has been stored to a block
Note that `!isStaticAllowed() && m_static_exists` is a valid state
(though it usually doesn't persist long) and you need to be careful
about handling it.
*/
bool m_static_exists = false;
/*

View File

@ -1716,7 +1716,7 @@ u16 ServerEnvironment::addActiveObject(std::unique_ptr<ServerActiveObject> objec
{
assert(object); // Pre-condition
m_added_objects++;
u16 id = addActiveObjectRaw(std::move(object), true, 0);
u16 id = addActiveObjectRaw(std::move(object), nullptr, 0);
return id;
}
@ -1886,7 +1886,7 @@ void ServerEnvironment::getSelectedActiveObjects(
*/
u16 ServerEnvironment::addActiveObjectRaw(std::unique_ptr<ServerActiveObject> object_u,
bool set_changed, u32 dtime_s)
const StaticObject *from_static, u32 dtime_s)
{
auto object = object_u.get();
if (!m_ao_manager.registerObject(std::move(object_u))) {
@ -1899,9 +1899,29 @@ u16 ServerEnvironment::addActiveObjectRaw(std::unique_ptr<ServerActiveObject> ob
// Note that this can change the value of isStaticAllowed() in case of LuaEntitySAO
object->addedToEnvironment(dtime_s);
// Activate object
if (object->m_static_exists)
{
sanity_check(from_static);
/*
* Note: Don't check isStaticAllowed() here. If an object has static data
* when it shouldn't, we still need to activate it so the static data
* can be properly removed.
*/
auto blockpos = object->m_static_block;
MapBlock *block = m_map->emergeBlock(blockpos);
if (block) {
block->m_static_objects.setActive(object->getId(), *from_static);
} else {
warningstream << "ServerEnvironment::addActiveObjectRaw(): "
<< "object was supposed to be in block " << blockpos
<< ", but this block disappeared." << std::endl;
object->m_static_exists = false;
}
}
// Add static data to block
if (object->isStaticAllowed()) {
// Add static object to active static list of the block
else if (object->isStaticAllowed())
{
v3f objectpos = object->getBasePosition();
StaticObject s_obj(object, objectpos);
// Add to the block where the object is located in
@ -1912,9 +1932,8 @@ u16 ServerEnvironment::addActiveObjectRaw(std::unique_ptr<ServerActiveObject> ob
object->m_static_exists = true;
object->m_static_block = blockpos;
if(set_changed)
block->raiseModified(MOD_STATE_WRITE_NEEDED,
MOD_REASON_ADD_ACTIVE_OBJECT_RAW);
block->raiseModified(MOD_STATE_WRITE_NEEDED,
MOD_REASON_ADD_ACTIVE_OBJECT_RAW);
} else {
v3s16 p = floatToInt(objectpos, BS);
errorstream << "ServerEnvironment::addActiveObjectRaw(): "
@ -1928,8 +1947,6 @@ u16 ServerEnvironment::addActiveObjectRaw(std::unique_ptr<ServerActiveObject> ob
}
}
assert(object->m_static_exists == object->isStaticAllowed());
return object->getId();
}
@ -2051,18 +2068,26 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
if (!obj) {
errorstream << "ServerEnvironment::activateObjects(): "
<< "failed to create active object from static object "
<< "in block " << (s_obj.pos / BS)
<< "in block " << block->getPos()
<< " type=" << (int)s_obj.type << " data:" << std::endl;
print_hexdump(verbosestream, s_obj.data);
new_stored.push_back(s_obj);
continue;
}
verbosestream << "ServerEnvironment::activateObjects(): "
<< "activated static object pos=" << (s_obj.pos / BS)
<< " type=" << (int)s_obj.type << std::endl;
obj->m_static_exists = true;
obj->m_static_block = block->getPos();
// This will also add the object to the active static list
addActiveObjectRaw(std::move(obj), false, dtime_s);
bool ok = addActiveObjectRaw(std::move(obj), &s_obj, dtime_s) != 0;
if (ok) {
verbosestream << "ServerEnvironment::activateObjects(): "
<< "activated static object pos=" << (s_obj.pos / BS)
<< " type=" << (int)s_obj.type << std::endl;
}
// callbacks could invalidate this block
if (block->isOrphan())
return;
}
@ -2095,7 +2120,7 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
If block wasn't generated (not in memory or on disk),
*/
void ServerEnvironment::deactivateFarObjects(bool _force_delete)
void ServerEnvironment::deactivateFarObjects(const bool _force_delete)
{
auto cb_deactivate = [this, _force_delete](ServerActiveObject *obj, u16 id) {
// force_delete might be overridden per object
@ -2117,7 +2142,7 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
// If object's static data is stored in a deactivated block and object
// is actually located in an active block, re-save to the block in
// which the object is actually located in.
if (!force_delete && obj->m_static_exists &&
if (!force_delete && obj->isStaticAllowed() && obj->m_static_exists &&
!m_active_blocks.contains(obj->m_static_block) &&
m_active_blocks.contains(blockpos_o)) {
@ -2194,6 +2219,9 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
u16 store_id = pending_delete ? id : 0;
if (!saveStaticToBlock(blockpos, store_id, obj, s_obj, reason))
force_delete = true;
} else {
// If the object has static data but shouldn't we need to get rid of it.
deleteStaticFromBlock(obj, id, MOD_REASON_STATIC_DATA_REMOVED, false);
}
// Regardless of what happens to the object at this point, deactivate it first.

View File

@ -280,15 +280,6 @@ public:
*/
u16 addActiveObject(std::unique_ptr<ServerActiveObject> object);
/*
Add an active object as a static object to the corresponding
MapBlock.
Caller allocates memory, ServerEnvironment frees memory.
Return value: true if succeeded, false if failed.
(note: not used, pending removal from engine)
*/
//bool addActiveObjectAsStatic(ServerActiveObject *object);
/*
Find out what new objects have been added to
inside a radius around a position
@ -428,7 +419,7 @@ private:
Returns 0 if not added and thus deleted.
*/
u16 addActiveObjectRaw(std::unique_ptr<ServerActiveObject> object,
bool set_changed, u32 dtime_s);
const StaticObject *from_static, u32 dtime_s);
/*
Remove all objects that satisfy (isGone() && m_known_by_count==0)