summaryrefslogtreecommitdiff
path: root/src/serverenvironment.cpp
diff options
context:
space:
mode:
authorLoïc Blot <nerzhul@users.noreply.github.com>2018-12-13 20:18:54 +0100
committerGitHub <noreply@github.com>2018-12-13 20:18:54 +0100
commiteda35100b6c6f7d9b01c257557147545b563dc74 (patch)
treee70929e401c91b4af4a40954c4af45ef59708832 /src/serverenvironment.cpp
parent839e935ba0572c592a791cc4dd4df4a9f6d2d260 (diff)
downloadminetest-eda35100b6c6f7d9b01c257557147545b563dc74.tar.gz
minetest-eda35100b6c6f7d9b01c257557147545b563dc74.tar.bz2
minetest-eda35100b6c6f7d9b01c257557147545b563dc74.zip
Add an activeobject manager to hold active objects (#7939)
* Add an activeobject manager to hold active objects * Add unittests
Diffstat (limited to 'src/serverenvironment.cpp')
-rw-r--r--src/serverenvironment.cpp272
1 files changed, 58 insertions, 214 deletions
diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp
index efb93b9a2..4837449e6 100644
--- a/src/serverenvironment.cpp
+++ b/src/serverenvironment.cpp
@@ -1047,29 +1047,13 @@ bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n)
return true;
}
-void ServerEnvironment::getObjectsInsideRadius(std::vector<u16> &objects, v3f pos,
- float radius)
-{
- for (auto &activeObject : m_active_objects) {
- ServerActiveObject* obj = activeObject.second;
- u16 id = activeObject.first;
- v3f objectpos = obj->getBasePosition();
- if (objectpos.getDistanceFrom(pos) > radius)
- continue;
- objects.push_back(id);
- }
-}
-
void ServerEnvironment::clearObjects(ClearObjectsMode mode)
{
infostream << "ServerEnvironment::clearObjects(): "
<< "Removing all active objects" << std::endl;
- std::vector<u16> objects_to_remove;
- for (auto &it : m_active_objects) {
- u16 id = it.first;
- ServerActiveObject* obj = it.second;
+ auto cb_removal = [this] (ServerActiveObject *obj, u16 id) {
if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
- continue;
+ return false;
// Delete static object if block is loaded
deleteStaticFromBlock(obj, id, MOD_REASON_CLEAR_ALL_OBJECTS, true);
@@ -1077,7 +1061,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode)
// If known by some client, don't delete immediately
if (obj->m_known_by_count > 0) {
obj->m_pending_removal = true;
- continue;
+ return false;
}
// Tell the object about removal
@@ -1088,14 +1072,11 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode)
// Delete active object
if (obj->environmentDeletes())
delete obj;
- // Id to be removed from m_active_objects
- objects_to_remove.push_back(id);
- }
- // Remove references from m_active_objects
- for (u16 i : objects_to_remove) {
- m_active_objects.erase(i);
- }
+ return true;
+ };
+
+ m_ao_manager.clear(cb_removal);
// Get list of loaded blocks
std::vector<v3s16> loaded_blocks;
@@ -1386,32 +1367,28 @@ void ServerEnvironment::step(float dtime)
*/
{
ScopeProfiler sp(g_profiler, "SEnv: step act. objs avg", SPT_AVG);
- //TimeTaker timer("Step active objects");
-
- g_profiler->avg("SEnv: num of objects", m_active_objects.size());
// This helps the objects to send data at the same time
bool send_recommended = false;
m_send_recommended_timer += dtime;
- if(m_send_recommended_timer > getSendRecommendedInterval())
- {
+ if (m_send_recommended_timer > getSendRecommendedInterval()) {
m_send_recommended_timer -= getSendRecommendedInterval();
send_recommended = true;
}
- for (auto &ao_it : m_active_objects) {
- ServerActiveObject* obj = ao_it.second;
+ auto cb_state = [this, dtime, send_recommended] (ServerActiveObject *obj) {
if (obj->isGone())
- continue;
+ return;
// Step object
obj->step(dtime, send_recommended);
// Read messages from object
while (!obj->m_messages_out.empty()) {
- m_active_object_messages.push(obj->m_messages_out.front());
+ this->m_active_object_messages.push(obj->m_messages_out.front());
obj->m_messages_out.pop();
}
- }
+ };
+ m_ao_manager.step(dtime, cb_state);
}
/*
@@ -1484,44 +1461,6 @@ void ServerEnvironment::deleteParticleSpawner(u32 id, bool remove_from_object)
}
}
-ServerActiveObject* ServerEnvironment::getActiveObject(u16 id)
-{
- ServerActiveObjectMap::const_iterator n = m_active_objects.find(id);
- return (n != m_active_objects.end() ? n->second : NULL);
-}
-
-/**
- * Verify if id is a free active object id
- * @param id
- * @return true if slot is free
- */
-bool ServerEnvironment::isFreeServerActiveObjectId(u16 id) const
-{
- if (id == 0)
- return false;
-
- return m_active_objects.find(id) == m_active_objects.end();
-}
-
-/**
- * Retrieve the first free ActiveObject ID
- * @return free activeobject ID or 0 if none was found
- */
-u16 ServerEnvironment::getFreeServerActiveObjectId()
-{
- // try to reuse id's as late as possible
- static u16 last_used_id = 0;
- u16 startid = last_used_id;
- for (;;) {
- last_used_id++;
- if (isFreeServerActiveObjectId(last_used_id))
- return last_used_id;
-
- if (last_used_id == startid)
- return 0;
- }
-}
-
u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
{
assert(object); // Pre-condition
@@ -1542,43 +1481,11 @@ void ServerEnvironment::getAddedActiveObjects(PlayerSAO *playersao, s16 radius,
f32 radius_f = radius * BS;
f32 player_radius_f = player_radius * BS;
- if (player_radius_f < 0)
- player_radius_f = 0;
- /*
- Go through the object list,
- - discard removed/deactivated objects,
- - discard objects that are too far away,
- - discard objects that are found in current_objects.
- - add remaining objects to added_objects
- */
- for (auto &ao_it : m_active_objects) {
- u16 id = ao_it.first;
-
- // Get object
- ServerActiveObject *object = ao_it.second;
- if (object == NULL)
- continue;
+ if (player_radius_f < 0.0f)
+ player_radius_f = 0.0f;
- if (object->isGone())
- continue;
-
- f32 distance_f = object->getBasePosition().
- getDistanceFrom(playersao->getBasePosition());
- if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
- // Discard if too far
- if (distance_f > player_radius_f && player_radius_f != 0)
- continue;
- } else if (distance_f > radius_f)
- continue;
-
- // Discard if already on current_objects
- std::set<u16>::iterator n;
- n = current_objects.find(id);
- if(n != current_objects.end())
- continue;
- // Add to added_objects
- added_objects.push(id);
- }
+ m_ao_manager.getAddedActiveObjectsAroundPos(playersao->getBasePosition(), radius_f,
+ player_radius_f, current_objects, added_objects);
}
/*
@@ -1639,8 +1546,8 @@ void ServerEnvironment::setStaticForActiveObjectsInBlock(
for (auto &so_it : block->m_static_objects.m_active) {
// Get the ServerActiveObject counterpart to this StaticObject
- ServerActiveObjectMap::const_iterator ao_it = m_active_objects.find(so_it.first);
- if (ao_it == m_active_objects.end()) {
+ ServerActiveObject *sao = m_ao_manager.getActiveObject(so_it.first);
+ if (!sao) {
// If this ever happens, there must be some kind of nasty bug.
errorstream << "ServerEnvironment::setStaticForObjectsInBlock(): "
"Object from MapBlock::m_static_objects::m_active not found "
@@ -1648,7 +1555,6 @@ void ServerEnvironment::setStaticForActiveObjectsInBlock(
continue;
}
- ServerActiveObject *sao = ao_it->second;
sao->m_static_exists = static_exists;
sao->m_static_block = static_block;
}
@@ -1703,60 +1609,17 @@ void ServerEnvironment::getSelectedActiveObjects(
u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
bool set_changed, u32 dtime_s)
{
- assert(object); // Pre-condition
- if(object->getId() == 0){
- u16 new_id = getFreeServerActiveObjectId();
- if(new_id == 0)
- {
- errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
- <<"no free ids available"<<std::endl;
- if(object->environmentDeletes())
- delete object;
- return 0;
- }
- object->setId(new_id);
- }
- else{
- verbosestream<<"ServerEnvironment::addActiveObjectRaw(): "
- <<"supplied with id "<<object->getId()<<std::endl;
- }
-
- if(!isFreeServerActiveObjectId(object->getId())) {
- errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
- <<"id is not free ("<<object->getId()<<")"<<std::endl;
- if(object->environmentDeletes())
- delete object;
- return 0;
- }
-
- if (objectpos_over_limit(object->getBasePosition())) {
- v3f p = object->getBasePosition();
- warningstream << "ServerEnvironment::addActiveObjectRaw(): "
- << "object position (" << p.X << "," << p.Y << "," << p.Z
- << ") outside maximum range" << std::endl;
- if (object->environmentDeletes())
- delete object;
+ if (!m_ao_manager.registerObject(object)) {
return 0;
}
- /*infostream<<"ServerEnvironment::addActiveObjectRaw(): "
- <<"added (id="<<object->getId()<<")"<<std::endl;*/
-
- m_active_objects[object->getId()] = object;
-
- verbosestream<<"ServerEnvironment::addActiveObjectRaw(): "
- <<"Added id="<<object->getId()<<"; there are now "
- <<m_active_objects.size()<<" active objects."
- <<std::endl;
-
// Register reference in scripting api (must be done before post-init)
m_script->addObjectReference(object);
// Post-initialize object
object->addedToEnvironment(dtime_s);
// Add static data to block
- if(object->isStaticAllowed())
- {
+ if (object->isStaticAllowed()) {
// Add static object to active static list of the block
v3f objectpos = object->getBasePosition();
StaticObject s_obj(object, objectpos);
@@ -1787,24 +1650,19 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
*/
void ServerEnvironment::removeRemovedObjects()
{
- std::vector<u16> objects_to_remove;
- for (auto &ao_it : m_active_objects) {
- u16 id = ao_it.first;
- ServerActiveObject* obj = ao_it.second;
-
+ auto clear_cb = [this] (ServerActiveObject *obj, u16 id) {
// This shouldn't happen but check it
if (!obj) {
errorstream << "ServerEnvironment::removeRemovedObjects(): "
<< "NULL object found. id=" << id << std::endl;
- objects_to_remove.push_back(id);
- continue;
+ return true;
}
/*
We will handle objects marked for removal or deactivation
*/
if (!obj->isGone())
- continue;
+ return false;
/*
Delete static data from block if removed
@@ -1815,7 +1673,7 @@ void ServerEnvironment::removeRemovedObjects()
// If still known by clients, don't actually remove. On some future
// invocation this will be 0, which is when removal will continue.
if(obj->m_known_by_count > 0)
- continue;
+ return false;
/*
Move static data from active to stored if deactivated
@@ -1823,8 +1681,7 @@ void ServerEnvironment::removeRemovedObjects()
if (!obj->m_pending_removal && obj->m_static_exists) {
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
if (block) {
- std::map<u16, StaticObject>::iterator i =
- block->m_static_objects.m_active.find(id);
+ const auto i = block->m_static_objects.m_active.find(id);
if (i != block->m_static_objects.m_active.end()) {
block->m_static_objects.m_stored.push_back(i->second);
block->m_static_objects.m_active.erase(id);
@@ -1848,15 +1705,13 @@ void ServerEnvironment::removeRemovedObjects()
m_script->removeObjectReference(obj);
// Delete
- if(obj->environmentDeletes())
+ if (obj->environmentDeletes())
delete obj;
- objects_to_remove.push_back(id);
- }
- // Remove references from m_active_objects
- for (u16 i : objects_to_remove) {
- m_active_objects.erase(i);
- }
+ return true;
+ };
+
+ m_ao_manager.clear(clear_cb);
}
static void print_hexdump(std::ostream &o, const std::string &data)
@@ -1976,24 +1831,19 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
*/
void ServerEnvironment::deactivateFarObjects(bool _force_delete)
{
- std::vector<u16> objects_to_remove;
- for (auto &ao_it : m_active_objects) {
+ auto cb_deactivate = [this, _force_delete] (ServerActiveObject *obj, u16 id) {
// force_delete might be overriden per object
bool force_delete = _force_delete;
- ServerActiveObject* obj = ao_it.second;
- assert(obj);
-
// Do not deactivate if static data creation not allowed
- if(!force_delete && !obj->isStaticAllowed())
- continue;
+ if (!force_delete && !obj->isStaticAllowed())
+ return false;
// removeRemovedObjects() is responsible for these
- if(!force_delete && obj->isGone())
- continue;
+ if (!force_delete && obj->isGone())
+ return false;
- u16 id = ao_it.first;
- v3f objectpos = obj->getBasePosition();
+ const v3f &objectpos = obj->getBasePosition();
// The block in which the object resides in
v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
@@ -2001,11 +1851,9 @@ 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 &&
- !m_active_blocks.contains(obj->m_static_block) &&
- m_active_blocks.contains(blockpos_o))
- {
+ if (!force_delete && obj->m_static_exists &&
+ !m_active_blocks.contains(obj->m_static_block) &&
+ m_active_blocks.contains(blockpos_o)) {
// Delete from block where object was located
deleteStaticFromBlock(obj, id, MOD_REASON_STATIC_DATA_REMOVED, false);
@@ -2013,16 +1861,16 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
// Save to block where object is located
saveStaticToBlock(blockpos_o, id, obj, s_obj, MOD_REASON_STATIC_DATA_ADDED);
- continue;
+ return false;
}
// If block is still active, don't remove
- if(!force_delete && m_active_blocks.contains(blockpos_o))
- continue;
+ if (!force_delete && m_active_blocks.contains(blockpos_o))
+ return false;
verbosestream << "ServerEnvironment::deactivateFarObjects(): "
- << "deactivating object id=" << id << " on inactive block "
- << PP(blockpos_o) << std::endl;
+ << "deactivating object id=" << id << " on inactive block "
+ << PP(blockpos_o) << std::endl;
// If known by some client, don't immediately delete.
bool pending_delete = (obj->m_known_by_count > 0 && !force_delete);
@@ -2045,8 +1893,7 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
if (block) {
- std::map<u16, StaticObject>::iterator n =
- block->m_static_objects.m_active.find(id);
+ const auto n = block->m_static_objects.m_active.find(id);
if (n != block->m_static_objects.m_active.end()) {
StaticObject static_old = n->second;
@@ -2085,18 +1932,18 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
If known by some client, set pending deactivation.
Otherwise delete it immediately.
*/
- if(pending_delete && !force_delete)
- {
+ if (pending_delete && !force_delete) {
verbosestream << "ServerEnvironment::deactivateFarObjects(): "
- << "object id=" << id << " is known by clients"
- << "; not deleting yet" << std::endl;
+ << "object id=" << id << " is known by clients"
+ << "; not deleting yet" << std::endl;
obj->m_pending_deactivation = true;
- continue;
+ return false;
}
+
verbosestream << "ServerEnvironment::deactivateFarObjects(): "
- << "object id=" << id << " is not known by clients"
- << "; deleting" << std::endl;
+ << "object id=" << id << " is not known by clients"
+ << "; deleting" << std::endl;
// Tell the object about removal
obj->removingFromEnvironment();
@@ -2104,16 +1951,13 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
m_script->removeObjectReference(obj);
// Delete active object
- if(obj->environmentDeletes())
+ if (obj->environmentDeletes())
delete obj;
- // Id to be removed from m_active_objects
- objects_to_remove.push_back(id);
- }
- // Remove references from m_active_objects
- for (u16 i : objects_to_remove) {
- m_active_objects.erase(i);
- }
+ return true;
+ };
+
+ m_ao_manager.clear(cb_deactivate);
}
void ServerEnvironment::deleteStaticFromBlock(