mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 10:03:45 +01:00
ActiveObjectMgr fixes (#13560)
This commit is contained in:
parent
929a13a9a0
commit
11ec75c2ad
@ -20,7 +20,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "debug.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include "util/basic_macros.h"
|
||||
|
||||
class TestClientActiveObjectMgr;
|
||||
class TestServerActiveObjectMgr;
|
||||
@ -32,14 +36,40 @@ class ActiveObjectMgr
|
||||
friend class ::TestServerActiveObjectMgr;
|
||||
|
||||
public:
|
||||
ActiveObjectMgr() = default;
|
||||
DISABLE_CLASS_COPY(ActiveObjectMgr);
|
||||
|
||||
virtual ~ActiveObjectMgr()
|
||||
{
|
||||
SANITY_CHECK(m_active_objects.empty());
|
||||
// Note: Do not call clear() here. The derived class is already half
|
||||
// destructed.
|
||||
}
|
||||
|
||||
virtual void step(float dtime, const std::function<void(T *)> &f) = 0;
|
||||
virtual bool registerObject(T *obj) = 0;
|
||||
virtual bool registerObject(std::unique_ptr<T> obj) = 0;
|
||||
virtual void removeObject(u16 id) = 0;
|
||||
|
||||
void clear()
|
||||
{
|
||||
while (!m_active_objects.empty())
|
||||
removeObject(m_active_objects.begin()->first);
|
||||
}
|
||||
|
||||
T *getActiveObject(u16 id)
|
||||
{
|
||||
auto n = m_active_objects.find(id);
|
||||
return (n != m_active_objects.end() ? n->second : nullptr);
|
||||
auto it = m_active_objects.find(id);
|
||||
return it != m_active_objects.end() ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
std::vector<u16> getAllIds() const
|
||||
{
|
||||
std::vector<u16> ids;
|
||||
ids.reserve(m_active_objects.size());
|
||||
for (auto &it : m_active_objects) {
|
||||
ids.push_back(it.first);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -61,5 +91,8 @@ protected:
|
||||
return id != 0 && m_active_objects.find(id) == m_active_objects.end();
|
||||
}
|
||||
|
||||
std::map<u16, T *> m_active_objects; // ordered to fix #10985
|
||||
// ordered to fix #10985
|
||||
// Note: ActiveObjects can access the ActiveObjectMgr. Only erase objects using
|
||||
// removeObject()!
|
||||
std::map<u16, std::unique_ptr<T>> m_active_objects;
|
||||
};
|
||||
|
@ -25,28 +25,33 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
namespace client
|
||||
{
|
||||
|
||||
void ActiveObjectMgr::clear()
|
||||
ActiveObjectMgr::~ActiveObjectMgr()
|
||||
{
|
||||
// delete active objects
|
||||
for (auto &active_object : m_active_objects) {
|
||||
delete active_object.second;
|
||||
// Object must be marked as gone when children try to detach
|
||||
active_object.second = nullptr;
|
||||
if (!m_active_objects.empty()) {
|
||||
warningstream << "client::ActiveObjectMgr::~ActiveObjectMgr(): not cleared."
|
||||
<< std::endl;
|
||||
clear();
|
||||
}
|
||||
m_active_objects.clear();
|
||||
}
|
||||
|
||||
void ActiveObjectMgr::step(
|
||||
float dtime, const std::function<void(ClientActiveObject *)> &f)
|
||||
{
|
||||
g_profiler->avg("ActiveObjectMgr: CAO count [#]", m_active_objects.size());
|
||||
for (auto &ao_it : m_active_objects) {
|
||||
f(ao_it.second);
|
||||
|
||||
// Same as in server activeobjectmgr.
|
||||
std::vector<u16> ids = getAllIds();
|
||||
|
||||
for (u16 id : ids) {
|
||||
auto it = m_active_objects.find(id);
|
||||
if (it == m_active_objects.end())
|
||||
continue; // obj was removed
|
||||
f(it->second.get());
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
bool ActiveObjectMgr::registerObject(ClientActiveObject *obj)
|
||||
bool ActiveObjectMgr::registerObject(std::unique_ptr<ClientActiveObject> obj)
|
||||
{
|
||||
assert(obj); // Pre-condition
|
||||
if (obj->getId() == 0) {
|
||||
@ -55,7 +60,6 @@ bool ActiveObjectMgr::registerObject(ClientActiveObject *obj)
|
||||
infostream << "Client::ActiveObjectMgr::registerObject(): "
|
||||
<< "no free id available" << std::endl;
|
||||
|
||||
delete obj;
|
||||
return false;
|
||||
}
|
||||
obj->setId(new_id);
|
||||
@ -64,12 +68,11 @@ bool ActiveObjectMgr::registerObject(ClientActiveObject *obj)
|
||||
if (!isFreeId(obj->getId())) {
|
||||
infostream << "Client::ActiveObjectMgr::registerObject(): "
|
||||
<< "id is not free (" << obj->getId() << ")" << std::endl;
|
||||
delete obj;
|
||||
return false;
|
||||
}
|
||||
infostream << "Client::ActiveObjectMgr::registerObject(): "
|
||||
<< "added (id=" << obj->getId() << ")" << std::endl;
|
||||
m_active_objects[obj->getId()] = obj;
|
||||
m_active_objects[obj->getId()] = std::move(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -77,17 +80,17 @@ void ActiveObjectMgr::removeObject(u16 id)
|
||||
{
|
||||
verbosestream << "Client::ActiveObjectMgr::removeObject(): "
|
||||
<< "id=" << id << std::endl;
|
||||
ClientActiveObject *obj = getActiveObject(id);
|
||||
if (!obj) {
|
||||
auto it = m_active_objects.find(id);
|
||||
if (it == m_active_objects.end()) {
|
||||
infostream << "Client::ActiveObjectMgr::removeObject(): "
|
||||
<< "id=" << id << " not found" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
m_active_objects.erase(id);
|
||||
std::unique_ptr<ClientActiveObject> obj = std::move(it->second);
|
||||
m_active_objects.erase(it);
|
||||
|
||||
obj->removeFromScene(true);
|
||||
delete obj;
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
@ -96,7 +99,7 @@ void ActiveObjectMgr::getActiveObjects(const v3f &origin, f32 max_d,
|
||||
{
|
||||
f32 max_d2 = max_d * max_d;
|
||||
for (auto &ao_it : m_active_objects) {
|
||||
ClientActiveObject *obj = ao_it.second;
|
||||
ClientActiveObject *obj = ao_it.second.get();
|
||||
|
||||
f32 d2 = (obj->getPosition() - origin).getLengthSQ();
|
||||
|
||||
@ -114,7 +117,7 @@ std::vector<DistanceSortedActiveObject> ActiveObjectMgr::getActiveSelectableObje
|
||||
v3f dir = shootline.getVector().normalize();
|
||||
|
||||
for (auto &ao_it : m_active_objects) {
|
||||
ClientActiveObject *obj = ao_it.second;
|
||||
ClientActiveObject *obj = ao_it.second.get();
|
||||
|
||||
aabb3f selection_box;
|
||||
if (!obj->getSelectionBox(&selection_box))
|
||||
|
@ -26,13 +26,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
namespace client
|
||||
{
|
||||
class ActiveObjectMgr : public ::ActiveObjectMgr<ClientActiveObject>
|
||||
class ActiveObjectMgr final : public ::ActiveObjectMgr<ClientActiveObject>
|
||||
{
|
||||
public:
|
||||
void clear();
|
||||
~ActiveObjectMgr() override;
|
||||
|
||||
void step(float dtime,
|
||||
const std::function<void(ClientActiveObject *)> &f) override;
|
||||
bool registerObject(ClientActiveObject *obj) override;
|
||||
bool registerObject(std::unique_ptr<ClientActiveObject> obj) override;
|
||||
void removeObject(u16 id) override;
|
||||
|
||||
void getActiveObjects(const v3f &origin, f32 max_d,
|
||||
|
@ -364,26 +364,26 @@ GenericCAO* ClientEnvironment::getGenericCAO(u16 id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
|
||||
u16 ClientEnvironment::addActiveObject(std::unique_ptr<ClientActiveObject> object)
|
||||
{
|
||||
auto obj = object.get();
|
||||
// Register object. If failed return zero id
|
||||
if (!m_ao_manager.registerObject(object))
|
||||
if (!m_ao_manager.registerObject(std::move(object)))
|
||||
return 0;
|
||||
|
||||
object->addToScene(m_texturesource, m_client->getSceneManager());
|
||||
obj->addToScene(m_texturesource, m_client->getSceneManager());
|
||||
|
||||
// Update lighting immediately
|
||||
object->updateLight(getDayNightRatio());
|
||||
return object->getId();
|
||||
obj->updateLight(getDayNightRatio());
|
||||
return obj->getId();
|
||||
}
|
||||
|
||||
void ClientEnvironment::addActiveObject(u16 id, u8 type,
|
||||
const std::string &init_data)
|
||||
{
|
||||
ClientActiveObject* obj =
|
||||
std::unique_ptr<ClientActiveObject> obj =
|
||||
ClientActiveObject::create((ActiveObjectType) type, m_client, this);
|
||||
if(obj == NULL)
|
||||
{
|
||||
if (!obj) {
|
||||
infostream<<"ClientEnvironment::addActiveObject(): "
|
||||
<<"id="<<id<<" type="<<type<<": Couldn't create object"
|
||||
<<std::endl;
|
||||
@ -392,12 +392,9 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
|
||||
|
||||
obj->setId(id);
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
obj->initialize(init_data);
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
} catch(SerializationError &e) {
|
||||
errorstream<<"ClientEnvironment::addActiveObject():"
|
||||
<<" id="<<id<<" type="<<type
|
||||
<<": SerializationError in initialize(): "
|
||||
@ -406,12 +403,12 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
|
||||
<<std::endl;
|
||||
}
|
||||
|
||||
u16 new_id = addActiveObject(obj);
|
||||
u16 new_id = addActiveObject(std::move(obj));
|
||||
// Object initialized:
|
||||
if ((obj = getActiveObject(new_id))) {
|
||||
if (ClientActiveObject *obj2 = getActiveObject(new_id)) {
|
||||
// Final step is to update all children which are already known
|
||||
// Data provided by AO_CMD_SPAWN_INFANT
|
||||
const auto &children = obj->getAttachmentChildIds();
|
||||
const auto &children = obj2->getAttachmentChildIds();
|
||||
for (auto c_id : children) {
|
||||
if (auto *o = getActiveObject(c_id))
|
||||
o->updateAttachments();
|
||||
|
@ -101,7 +101,7 @@ public:
|
||||
Returns the id of the object.
|
||||
Returns 0 if not added and thus deleted.
|
||||
*/
|
||||
u16 addActiveObject(ClientActiveObject *object);
|
||||
u16 addActiveObject(std::unique_ptr<ClientActiveObject> object);
|
||||
|
||||
void addActiveObject(u16 id, u8 type, const std::string &init_data);
|
||||
void removeActiveObject(u16 id);
|
||||
|
@ -38,7 +38,7 @@ ClientActiveObject::~ClientActiveObject()
|
||||
removeFromScene(true);
|
||||
}
|
||||
|
||||
ClientActiveObject* ClientActiveObject::create(ActiveObjectType type,
|
||||
std::unique_ptr<ClientActiveObject> ClientActiveObject::create(ActiveObjectType type,
|
||||
Client *client, ClientEnvironment *env)
|
||||
{
|
||||
// Find factory function
|
||||
@ -47,11 +47,11 @@ ClientActiveObject* ClientActiveObject::create(ActiveObjectType type,
|
||||
// If factory is not found, just return.
|
||||
warningstream << "ClientActiveObject: No factory for type="
|
||||
<< (int)type << std::endl;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Factory f = n->second;
|
||||
ClientActiveObject *object = (*f)(client, env);
|
||||
std::unique_ptr<ClientActiveObject> object = (*f)(client, env);
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "activeobject.h"
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
@ -78,8 +79,8 @@ public:
|
||||
virtual void initialize(const std::string &data) {}
|
||||
|
||||
// Create a certain type of ClientActiveObject
|
||||
static ClientActiveObject *create(ActiveObjectType type, Client *client,
|
||||
ClientEnvironment *env);
|
||||
static std::unique_ptr<ClientActiveObject> create(ActiveObjectType type,
|
||||
Client *client, ClientEnvironment *env);
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
virtual bool directReportPunch(v3f dir, const ItemStack *punchitem = nullptr,
|
||||
@ -87,7 +88,7 @@ public:
|
||||
|
||||
protected:
|
||||
// Used for creating objects based on type
|
||||
typedef ClientActiveObject *(*Factory)(Client *client, ClientEnvironment *env);
|
||||
typedef std::unique_ptr<ClientActiveObject> (*Factory)(Client *client, ClientEnvironment *env);
|
||||
static void registerType(u16 type, Factory f);
|
||||
Client *m_client;
|
||||
ClientEnvironment *m_env;
|
||||
|
@ -199,7 +199,7 @@ public:
|
||||
return ACTIVEOBJECT_TYPE_TEST;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(Client *client, ClientEnvironment *env);
|
||||
static std::unique_ptr<ClientActiveObject> create(Client *client, ClientEnvironment *env);
|
||||
|
||||
void addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr);
|
||||
void removeFromScene(bool permanent);
|
||||
@ -227,9 +227,9 @@ TestCAO::TestCAO(Client *client, ClientEnvironment *env):
|
||||
ClientActiveObject::registerType(getType(), create);
|
||||
}
|
||||
|
||||
ClientActiveObject* TestCAO::create(Client *client, ClientEnvironment *env)
|
||||
std::unique_ptr<ClientActiveObject> TestCAO::create(Client *client, ClientEnvironment *env)
|
||||
{
|
||||
return new TestCAO(client, env);
|
||||
return std::make_unique<TestCAO>(client, env);
|
||||
}
|
||||
|
||||
void TestCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
|
||||
@ -326,7 +326,7 @@ void TestCAO::processMessage(const std::string &data)
|
||||
GenericCAO::GenericCAO(Client *client, ClientEnvironment *env):
|
||||
ClientActiveObject(0, client, env)
|
||||
{
|
||||
if (client == NULL) {
|
||||
if (!client) {
|
||||
ClientActiveObject::registerType(getType(), create);
|
||||
} else {
|
||||
m_client = client;
|
||||
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "itemgroup.h"
|
||||
#include "constants.h"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
class Camera;
|
||||
class Client;
|
||||
@ -139,9 +140,9 @@ public:
|
||||
|
||||
~GenericCAO();
|
||||
|
||||
static ClientActiveObject* create(Client *client, ClientEnvironment *env)
|
||||
static std::unique_ptr<ClientActiveObject> create(Client *client, ClientEnvironment *env)
|
||||
{
|
||||
return new GenericCAO(client, env);
|
||||
return std::make_unique<GenericCAO>(client, env);
|
||||
}
|
||||
|
||||
inline ActiveObjectType getType() const override
|
||||
|
@ -611,8 +611,10 @@ int ModApiEnv::l_add_entity(lua_State *L)
|
||||
const char *name = luaL_checkstring(L, 2);
|
||||
std::string staticdata = readParam<std::string>(L, 3, "");
|
||||
|
||||
ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, staticdata);
|
||||
int objectid = env->addActiveObject(obj);
|
||||
std::unique_ptr<ServerActiveObject> obj_u =
|
||||
std::make_unique<LuaEntitySAO>(env, pos, name, staticdata);
|
||||
auto obj = obj_u.get();
|
||||
int objectid = env->addActiveObject(std::move(obj_u));
|
||||
// If failed to add, return nothing (reads as nil)
|
||||
if (objectid == 0)
|
||||
return 0;
|
||||
|
@ -25,16 +25,30 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
namespace server
|
||||
{
|
||||
|
||||
void ActiveObjectMgr::clear(const std::function<bool(ServerActiveObject *, u16)> &cb)
|
||||
ActiveObjectMgr::~ActiveObjectMgr()
|
||||
{
|
||||
// make a defensive copy in case the
|
||||
// passed callback changes the set of active objects
|
||||
auto cloned_map(m_active_objects);
|
||||
if (!m_active_objects.empty()) {
|
||||
warningstream << "server::ActiveObjectMgr::~ActiveObjectMgr(): not cleared."
|
||||
<< std::endl;
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &it : cloned_map) {
|
||||
if (cb(it.second, it.first)) {
|
||||
// Remove reference from m_active_objects
|
||||
m_active_objects.erase(it.first);
|
||||
void ActiveObjectMgr::clearIf(const std::function<bool(ServerActiveObject *, u16)> &cb)
|
||||
{
|
||||
// Make a defensive copy of the ids in case the passed callback changes the
|
||||
// set of active objects.
|
||||
// The callback is called for newly added objects iff they happen to reuse
|
||||
// an old id.
|
||||
std::vector<u16> ids = getAllIds();
|
||||
|
||||
for (u16 id : ids) {
|
||||
auto it = m_active_objects.find(id);
|
||||
if (it == m_active_objects.end())
|
||||
continue; // obj was already removed
|
||||
if (cb(it->second.get(), id)) {
|
||||
// erase by id, `it` can be invalid now
|
||||
removeObject(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -43,13 +57,20 @@ void ActiveObjectMgr::step(
|
||||
float dtime, const std::function<void(ServerActiveObject *)> &f)
|
||||
{
|
||||
g_profiler->avg("ActiveObjectMgr: SAO count [#]", m_active_objects.size());
|
||||
for (auto &ao_it : m_active_objects) {
|
||||
f(ao_it.second);
|
||||
|
||||
// See above.
|
||||
std::vector<u16> ids = getAllIds();
|
||||
|
||||
for (u16 id : ids) {
|
||||
auto it = m_active_objects.find(id);
|
||||
if (it == m_active_objects.end())
|
||||
continue; // obj was removed
|
||||
f(it->second.get());
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
bool ActiveObjectMgr::registerObject(ServerActiveObject *obj)
|
||||
bool ActiveObjectMgr::registerObject(std::unique_ptr<ServerActiveObject> obj)
|
||||
{
|
||||
assert(obj); // Pre-condition
|
||||
if (obj->getId() == 0) {
|
||||
@ -57,8 +78,6 @@ bool ActiveObjectMgr::registerObject(ServerActiveObject *obj)
|
||||
if (new_id == 0) {
|
||||
errorstream << "Server::ActiveObjectMgr::addActiveObjectRaw(): "
|
||||
<< "no free id available" << std::endl;
|
||||
if (obj->environmentDeletes())
|
||||
delete obj;
|
||||
return false;
|
||||
}
|
||||
obj->setId(new_id);
|
||||
@ -70,8 +89,6 @@ bool ActiveObjectMgr::registerObject(ServerActiveObject *obj)
|
||||
if (!isFreeId(obj->getId())) {
|
||||
errorstream << "Server::ActiveObjectMgr::addActiveObjectRaw(): "
|
||||
<< "id is not free (" << obj->getId() << ")" << std::endl;
|
||||
if (obj->environmentDeletes())
|
||||
delete obj;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -80,15 +97,14 @@ bool ActiveObjectMgr::registerObject(ServerActiveObject *obj)
|
||||
warningstream << "Server::ActiveObjectMgr::addActiveObjectRaw(): "
|
||||
<< "object position (" << p.X << "," << p.Y << "," << p.Z
|
||||
<< ") outside maximum range" << std::endl;
|
||||
if (obj->environmentDeletes())
|
||||
delete obj;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_active_objects[obj->getId()] = obj;
|
||||
auto obj_p = obj.get();
|
||||
m_active_objects[obj->getId()] = std::move(obj);
|
||||
|
||||
verbosestream << "Server::ActiveObjectMgr::addActiveObjectRaw(): "
|
||||
<< "Added id=" << obj->getId() << "; there are now "
|
||||
<< "Added id=" << obj_p->getId() << "; there are now "
|
||||
<< m_active_objects.size() << " active objects." << std::endl;
|
||||
return true;
|
||||
}
|
||||
@ -97,15 +113,17 @@ void ActiveObjectMgr::removeObject(u16 id)
|
||||
{
|
||||
verbosestream << "Server::ActiveObjectMgr::removeObject(): "
|
||||
<< "id=" << id << std::endl;
|
||||
ServerActiveObject *obj = getActiveObject(id);
|
||||
if (!obj) {
|
||||
auto it = m_active_objects.find(id);
|
||||
if (it == m_active_objects.end()) {
|
||||
infostream << "Server::ActiveObjectMgr::removeObject(): "
|
||||
<< "id=" << id << " not found" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
m_active_objects.erase(id);
|
||||
delete obj;
|
||||
// Delete the obj before erasing, as the destructor may indirectly access
|
||||
// m_active_objects.
|
||||
it->second.reset();
|
||||
m_active_objects.erase(id); // `it` can be invalid now
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
@ -115,7 +133,7 @@ void ActiveObjectMgr::getObjectsInsideRadius(const v3f &pos, float radius,
|
||||
{
|
||||
float r2 = radius * radius;
|
||||
for (auto &activeObject : m_active_objects) {
|
||||
ServerActiveObject *obj = activeObject.second;
|
||||
ServerActiveObject *obj = activeObject.second.get();
|
||||
const v3f &objectpos = obj->getBasePosition();
|
||||
if (objectpos.getDistanceFromSQ(pos) > r2)
|
||||
continue;
|
||||
@ -130,7 +148,7 @@ void ActiveObjectMgr::getObjectsInArea(const aabb3f &box,
|
||||
std::function<bool(ServerActiveObject *obj)> include_obj_cb)
|
||||
{
|
||||
for (auto &activeObject : m_active_objects) {
|
||||
ServerActiveObject *obj = activeObject.second;
|
||||
ServerActiveObject *obj = activeObject.second.get();
|
||||
const v3f &objectpos = obj->getBasePosition();
|
||||
if (!box.isPointInside(objectpos))
|
||||
continue;
|
||||
@ -155,7 +173,7 @@ void ActiveObjectMgr::getAddedActiveObjectsAroundPos(const v3f &player_pos, f32
|
||||
u16 id = ao_it.first;
|
||||
|
||||
// Get object
|
||||
ServerActiveObject *object = ao_it.second;
|
||||
ServerActiveObject *object = ao_it.second.get();
|
||||
if (!object)
|
||||
continue;
|
||||
|
||||
|
@ -26,13 +26,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
namespace server
|
||||
{
|
||||
class ActiveObjectMgr : public ::ActiveObjectMgr<ServerActiveObject>
|
||||
class ActiveObjectMgr final : public ::ActiveObjectMgr<ServerActiveObject>
|
||||
{
|
||||
public:
|
||||
void clear(const std::function<bool(ServerActiveObject *, u16)> &cb);
|
||||
~ActiveObjectMgr() override;
|
||||
|
||||
// If cb returns true, the obj will be deleted
|
||||
void clearIf(const std::function<bool(ServerActiveObject *, u16)> &cb);
|
||||
void step(float dtime,
|
||||
const std::function<void(ServerActiveObject *)> &f) override;
|
||||
bool registerObject(ServerActiveObject *obj) override;
|
||||
bool registerObject(std::unique_ptr<ServerActiveObject> obj) override;
|
||||
void removeObject(u16 id) override;
|
||||
|
||||
void getObjectsInsideRadius(const v3f &pos, float radius,
|
||||
|
@ -67,10 +67,6 @@ public:
|
||||
virtual void addedToEnvironment(u32 dtime_s){};
|
||||
// Called before removing from environment
|
||||
virtual void removingFromEnvironment(){};
|
||||
// Returns true if object's deletion is the job of the
|
||||
// environment
|
||||
virtual bool environmentDeletes() const
|
||||
{ return true; }
|
||||
|
||||
// Safely mark the object for removal or deactivation
|
||||
void markForRemoval();
|
||||
|
@ -633,9 +633,9 @@ void ServerEnvironment::savePlayer(RemotePlayer *player)
|
||||
PlayerSAO *ServerEnvironment::loadPlayer(RemotePlayer *player, bool *new_player,
|
||||
session_t peer_id, bool is_singleplayer)
|
||||
{
|
||||
PlayerSAO *playersao = new PlayerSAO(this, player, peer_id, is_singleplayer);
|
||||
auto playersao = std::make_unique<PlayerSAO>(this, player, peer_id, is_singleplayer);
|
||||
// Create player if it doesn't exist
|
||||
if (!m_player_database->loadPlayer(player, playersao)) {
|
||||
if (!m_player_database->loadPlayer(player, playersao.get())) {
|
||||
*new_player = true;
|
||||
// Set player position
|
||||
infostream << "Server: Finding spawn place for player \""
|
||||
@ -662,12 +662,13 @@ PlayerSAO *ServerEnvironment::loadPlayer(RemotePlayer *player, bool *new_player,
|
||||
player->clearHud();
|
||||
|
||||
/* Add object to environment */
|
||||
addActiveObject(playersao);
|
||||
PlayerSAO *ret = playersao.get();
|
||||
addActiveObject(std::move(playersao));
|
||||
|
||||
// Update active blocks quickly for a bit so objects in those blocks appear on the client
|
||||
m_fast_active_block_divider = 10;
|
||||
|
||||
return playersao;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ServerEnvironment::saveMeta()
|
||||
@ -1230,13 +1231,10 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode)
|
||||
m_script->removeObjectReference(obj);
|
||||
|
||||
// Delete active object
|
||||
if (obj->environmentDeletes())
|
||||
delete obj;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
m_ao_manager.clear(cb_removal);
|
||||
m_ao_manager.clearIf(cb_removal);
|
||||
|
||||
// Get list of loaded blocks
|
||||
std::vector<v3s16> loaded_blocks;
|
||||
@ -1675,11 +1673,11 @@ void ServerEnvironment::deleteParticleSpawner(u32 id, bool remove_from_object)
|
||||
}
|
||||
}
|
||||
|
||||
u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
|
||||
u16 ServerEnvironment::addActiveObject(std::unique_ptr<ServerActiveObject> object)
|
||||
{
|
||||
assert(object); // Pre-condition
|
||||
m_added_objects++;
|
||||
u16 id = addActiveObjectRaw(object, true, 0);
|
||||
u16 id = addActiveObjectRaw(std::move(object), true, 0);
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -1831,10 +1829,11 @@ void ServerEnvironment::getSelectedActiveObjects(
|
||||
************ Private methods *************
|
||||
*/
|
||||
|
||||
u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||
u16 ServerEnvironment::addActiveObjectRaw(std::unique_ptr<ServerActiveObject> object_u,
|
||||
bool set_changed, u32 dtime_s)
|
||||
{
|
||||
if (!m_ao_manager.registerObject(object)) {
|
||||
auto object = object_u.get();
|
||||
if (!m_ao_manager.registerObject(std::move(object_u))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1925,13 +1924,10 @@ void ServerEnvironment::removeRemovedObjects()
|
||||
m_script->removeObjectReference(obj);
|
||||
|
||||
// Delete
|
||||
if (obj->environmentDeletes())
|
||||
delete obj;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
m_ao_manager.clear(clear_cb);
|
||||
m_ao_manager.clearIf(clear_cb);
|
||||
}
|
||||
|
||||
static void print_hexdump(std::ostream &o, const std::string &data)
|
||||
@ -1968,12 +1964,12 @@ static void print_hexdump(std::ostream &o, const std::string &data)
|
||||
}
|
||||
}
|
||||
|
||||
ServerActiveObject* ServerEnvironment::createSAO(ActiveObjectType type, v3f pos,
|
||||
const std::string &data)
|
||||
std::unique_ptr<ServerActiveObject> ServerEnvironment::createSAO(ActiveObjectType type,
|
||||
v3f pos, const std::string &data)
|
||||
{
|
||||
switch (type) {
|
||||
case ACTIVEOBJECT_TYPE_LUAENTITY:
|
||||
return new LuaEntitySAO(this, pos, data);
|
||||
return std::make_unique<LuaEntitySAO>(this, pos, data);
|
||||
default:
|
||||
warningstream << "ServerActiveObject: No factory for type=" << type << std::endl;
|
||||
}
|
||||
@ -1995,7 +1991,7 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
|
||||
std::vector<StaticObject> new_stored;
|
||||
for (const StaticObject &s_obj : block->m_static_objects.getAllStored()) {
|
||||
// Create an active object from the data
|
||||
ServerActiveObject *obj =
|
||||
std::unique_ptr<ServerActiveObject> obj =
|
||||
createSAO((ActiveObjectType)s_obj.type, s_obj.pos, s_obj.data);
|
||||
// If couldn't create object, store static data back.
|
||||
if (!obj) {
|
||||
@ -2012,7 +2008,7 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
|
||||
<< "activated static object pos=" << (s_obj.pos / BS)
|
||||
<< " type=" << (int)s_obj.type << std::endl;
|
||||
// This will also add the object to the active static list
|
||||
addActiveObjectRaw(obj, false, dtime_s);
|
||||
addActiveObjectRaw(std::move(obj), false, dtime_s);
|
||||
if (block->isOrphan())
|
||||
return;
|
||||
}
|
||||
@ -2168,13 +2164,10 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
|
||||
m_script->removeObjectReference(obj);
|
||||
|
||||
// Delete active object
|
||||
if (obj->environmentDeletes())
|
||||
delete obj;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
m_ao_manager.clear(cb_deactivate);
|
||||
m_ao_manager.clearIf(cb_deactivate);
|
||||
}
|
||||
|
||||
void ServerEnvironment::deleteStaticFromBlock(
|
||||
|
@ -277,7 +277,7 @@ public:
|
||||
Returns the id of the object.
|
||||
Returns 0 if not added and thus deleted.
|
||||
*/
|
||||
u16 addActiveObject(ServerActiveObject *object);
|
||||
u16 addActiveObject(std::unique_ptr<ServerActiveObject> object);
|
||||
|
||||
/*
|
||||
Add an active object as a static object to the corresponding
|
||||
@ -422,7 +422,8 @@ private:
|
||||
Returns the id of the object.
|
||||
Returns 0 if not added and thus deleted.
|
||||
*/
|
||||
u16 addActiveObjectRaw(ServerActiveObject *object, bool set_changed, u32 dtime_s);
|
||||
u16 addActiveObjectRaw(std::unique_ptr<ServerActiveObject> object,
|
||||
bool set_changed, u32 dtime_s);
|
||||
|
||||
/*
|
||||
Remove all objects that satisfy (isGone() && m_known_by_count==0)
|
||||
@ -518,5 +519,6 @@ private:
|
||||
MetricGaugePtr m_active_block_gauge;
|
||||
MetricGaugePtr m_active_object_gauge;
|
||||
|
||||
ServerActiveObject* createSAO(ActiveObjectType type, v3f pos, const std::string &data);
|
||||
std::unique_ptr<ServerActiveObject> createSAO(ActiveObjectType type, v3f pos,
|
||||
const std::string &data);
|
||||
};
|
||||
|
@ -90,8 +90,9 @@ void TestClientActiveObjectMgr::testFreeID()
|
||||
// Register basic objects, ensure we never found
|
||||
for (u8 i = 0; i < UINT8_MAX; i++) {
|
||||
// Register an object
|
||||
auto tcao = new TestClientActiveObject();
|
||||
caomgr.registerObject(tcao);
|
||||
auto tcao_u = std::make_unique<TestClientActiveObject>();
|
||||
auto tcao = tcao_u.get();
|
||||
caomgr.registerObject(std::move(tcao_u));
|
||||
aoids.push_back(tcao->getId());
|
||||
|
||||
// Ensure next id is not in registered list
|
||||
@ -105,8 +106,9 @@ void TestClientActiveObjectMgr::testFreeID()
|
||||
void TestClientActiveObjectMgr::testRegisterObject()
|
||||
{
|
||||
client::ActiveObjectMgr caomgr;
|
||||
auto tcao = new TestClientActiveObject();
|
||||
UASSERT(caomgr.registerObject(tcao));
|
||||
auto tcao_u = std::make_unique<TestClientActiveObject>();
|
||||
auto tcao = tcao_u.get();
|
||||
UASSERT(caomgr.registerObject(std::move(tcao_u)));
|
||||
|
||||
u16 id = tcao->getId();
|
||||
|
||||
@ -114,8 +116,9 @@ void TestClientActiveObjectMgr::testRegisterObject()
|
||||
UASSERT(tcaoToCompare->getId() == id);
|
||||
UASSERT(tcaoToCompare == tcao);
|
||||
|
||||
tcao = new TestClientActiveObject();
|
||||
UASSERT(caomgr.registerObject(tcao));
|
||||
tcao_u = std::make_unique<TestClientActiveObject>();
|
||||
tcao = tcao_u.get();
|
||||
UASSERT(caomgr.registerObject(std::move(tcao_u)));
|
||||
UASSERT(caomgr.getActiveObject(tcao->getId()) == tcao);
|
||||
UASSERT(caomgr.getActiveObject(tcao->getId()) != tcaoToCompare);
|
||||
|
||||
@ -125,8 +128,9 @@ void TestClientActiveObjectMgr::testRegisterObject()
|
||||
void TestClientActiveObjectMgr::testRemoveObject()
|
||||
{
|
||||
client::ActiveObjectMgr caomgr;
|
||||
auto tcao = new TestClientActiveObject();
|
||||
UASSERT(caomgr.registerObject(tcao));
|
||||
auto tcao_u = std::make_unique<TestClientActiveObject>();
|
||||
auto tcao = tcao_u.get();
|
||||
UASSERT(caomgr.registerObject(std::move(tcao_u)));
|
||||
|
||||
u16 id = tcao->getId();
|
||||
UASSERT(caomgr.getActiveObject(id) != nullptr)
|
||||
@ -140,8 +144,10 @@ void TestClientActiveObjectMgr::testRemoveObject()
|
||||
void TestClientActiveObjectMgr::testGetActiveSelectableObjects()
|
||||
{
|
||||
client::ActiveObjectMgr caomgr;
|
||||
auto obj = new TestSelectableClientActiveObject({v3f{-1, -1, -1}, v3f{1, 1, 1}});
|
||||
UASSERT(caomgr.registerObject(obj));
|
||||
auto obj_u = std::make_unique<TestSelectableClientActiveObject>(
|
||||
aabb3f{v3f{-1, -1, -1}, v3f{1, 1, 1}});
|
||||
auto obj = obj_u.get();
|
||||
UASSERT(caomgr.registerObject(std::move(obj_u)));
|
||||
|
||||
auto assert_obj_selected = [&] (v3f a, v3f b) {
|
||||
auto actual = caomgr.getActiveSelectableObjects({a, b});
|
||||
|
@ -53,15 +53,6 @@ void TestServerActiveObjectMgr::runTests(IGameDef *gamedef)
|
||||
TEST(testGetAddedActiveObjectsAroundPos);
|
||||
}
|
||||
|
||||
void clearSAOMgr(server::ActiveObjectMgr *saomgr)
|
||||
{
|
||||
auto clear_cb = [](ServerActiveObject *obj, u16 id) {
|
||||
delete obj;
|
||||
return true;
|
||||
};
|
||||
saomgr->clear(clear_cb);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TestServerActiveObjectMgr::testFreeID()
|
||||
@ -78,8 +69,9 @@ void TestServerActiveObjectMgr::testFreeID()
|
||||
// Register basic objects, ensure we never found
|
||||
for (u8 i = 0; i < UINT8_MAX; i++) {
|
||||
// Register an object
|
||||
auto sao = new MockServerActiveObject();
|
||||
saomgr.registerObject(sao);
|
||||
auto sao_u = std::make_unique<MockServerActiveObject>();
|
||||
auto sao = sao_u.get();
|
||||
saomgr.registerObject(std::move(sao_u));
|
||||
aoids.push_back(sao->getId());
|
||||
|
||||
// Ensure next id is not in registered list
|
||||
@ -87,14 +79,15 @@ void TestServerActiveObjectMgr::testFreeID()
|
||||
aoids.end());
|
||||
}
|
||||
|
||||
clearSAOMgr(&saomgr);
|
||||
saomgr.clear();
|
||||
}
|
||||
|
||||
void TestServerActiveObjectMgr::testRegisterObject()
|
||||
{
|
||||
server::ActiveObjectMgr saomgr;
|
||||
auto sao = new MockServerActiveObject();
|
||||
UASSERT(saomgr.registerObject(sao));
|
||||
auto sao_u = std::make_unique<MockServerActiveObject>();
|
||||
auto sao = sao_u.get();
|
||||
UASSERT(saomgr.registerObject(std::move(sao_u)));
|
||||
|
||||
u16 id = sao->getId();
|
||||
|
||||
@ -102,19 +95,21 @@ void TestServerActiveObjectMgr::testRegisterObject()
|
||||
UASSERT(saoToCompare->getId() == id);
|
||||
UASSERT(saoToCompare == sao);
|
||||
|
||||
sao = new MockServerActiveObject();
|
||||
UASSERT(saomgr.registerObject(sao));
|
||||
sao_u = std::make_unique<MockServerActiveObject>();
|
||||
sao = sao_u.get();
|
||||
UASSERT(saomgr.registerObject(std::move(sao_u)));
|
||||
UASSERT(saomgr.getActiveObject(sao->getId()) == sao);
|
||||
UASSERT(saomgr.getActiveObject(sao->getId()) != saoToCompare);
|
||||
|
||||
clearSAOMgr(&saomgr);
|
||||
saomgr.clear();
|
||||
}
|
||||
|
||||
void TestServerActiveObjectMgr::testRemoveObject()
|
||||
{
|
||||
server::ActiveObjectMgr saomgr;
|
||||
auto sao = new MockServerActiveObject();
|
||||
UASSERT(saomgr.registerObject(sao));
|
||||
auto sao_u = std::make_unique<MockServerActiveObject>();
|
||||
auto sao = sao_u.get();
|
||||
UASSERT(saomgr.registerObject(std::move(sao_u)));
|
||||
|
||||
u16 id = sao->getId();
|
||||
UASSERT(saomgr.getActiveObject(id) != nullptr)
|
||||
@ -122,7 +117,7 @@ void TestServerActiveObjectMgr::testRemoveObject()
|
||||
saomgr.removeObject(sao->getId());
|
||||
UASSERT(saomgr.getActiveObject(id) == nullptr);
|
||||
|
||||
clearSAOMgr(&saomgr);
|
||||
saomgr.clear();
|
||||
}
|
||||
|
||||
void TestServerActiveObjectMgr::testGetObjectsInsideRadius()
|
||||
@ -137,7 +132,7 @@ void TestServerActiveObjectMgr::testGetObjectsInsideRadius()
|
||||
};
|
||||
|
||||
for (const auto &p : sao_pos) {
|
||||
saomgr.registerObject(new MockServerActiveObject(nullptr, p));
|
||||
saomgr.registerObject(std::make_unique<MockServerActiveObject>(nullptr, p));
|
||||
}
|
||||
|
||||
std::vector<ServerActiveObject *> result;
|
||||
@ -160,7 +155,7 @@ void TestServerActiveObjectMgr::testGetObjectsInsideRadius()
|
||||
saomgr.getObjectsInsideRadius(v3f(), 750000, result, include_obj_cb);
|
||||
UASSERTCMP(int, ==, result.size(), 4);
|
||||
|
||||
clearSAOMgr(&saomgr);
|
||||
saomgr.clear();
|
||||
}
|
||||
|
||||
void TestServerActiveObjectMgr::testGetAddedActiveObjectsAroundPos()
|
||||
@ -175,7 +170,7 @@ void TestServerActiveObjectMgr::testGetAddedActiveObjectsAroundPos()
|
||||
};
|
||||
|
||||
for (const auto &p : sao_pos) {
|
||||
saomgr.registerObject(new MockServerActiveObject(nullptr, p));
|
||||
saomgr.registerObject(std::make_unique<MockServerActiveObject>(nullptr, p));
|
||||
}
|
||||
|
||||
std::queue<u16> result;
|
||||
@ -188,5 +183,5 @@ void TestServerActiveObjectMgr::testGetAddedActiveObjectsAroundPos()
|
||||
saomgr.getAddedActiveObjectsAroundPos(v3f(), 740, 50, cur_objects, result);
|
||||
UASSERTCMP(int, ==, result.size(), 2);
|
||||
|
||||
clearSAOMgr(&saomgr);
|
||||
saomgr.clear();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user