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