diff options
author | Loïc Blot <nerzhul@users.noreply.github.com> | 2018-12-13 20:18:54 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-13 20:18:54 +0100 |
commit | eda35100b6c6f7d9b01c257557147545b563dc74 (patch) | |
tree | e70929e401c91b4af4a40954c4af45ef59708832 /src/client | |
parent | 839e935ba0572c592a791cc4dd4df4a9f6d2d260 (diff) | |
download | minetest-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/client')
-rw-r--r-- | src/client/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/client/activeobjectmgr.cpp | 106 | ||||
-rw-r--r-- | src/client/activeobjectmgr.h | 41 | ||||
-rw-r--r-- | src/client/clientenvironment.cpp | 109 | ||||
-rw-r--r-- | src/client/clientenvironment.h | 20 |
5 files changed, 188 insertions, 89 deletions
diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index e24b73e80..140814911 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -25,6 +25,7 @@ set(client_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/render/plain.cpp ${CMAKE_CURRENT_SOURCE_DIR}/render/sidebyside.cpp ${CMAKE_CURRENT_SOURCE_DIR}/render/stereo.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/activeobjectmgr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/camera.cpp ${CMAKE_CURRENT_SOURCE_DIR}/client.cpp ${CMAKE_CURRENT_SOURCE_DIR}/clientenvironment.cpp diff --git a/src/client/activeobjectmgr.cpp b/src/client/activeobjectmgr.cpp new file mode 100644 index 000000000..4ed98d79b --- /dev/null +++ b/src/client/activeobjectmgr.cpp @@ -0,0 +1,106 @@ +/* +Minetest +Copyright (C) 2010-2018 nerzhul, Loic BLOT <loic.blot@unix-experience.fr> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include <log.h> +#include "profiler.h" +#include "activeobjectmgr.h" + +namespace client +{ + +void ActiveObjectMgr::clear() +{ + // delete active objects + for (auto &active_object : m_active_objects) { + delete active_object.second; + } +} + +void ActiveObjectMgr::step( + float dtime, const std::function<void(ClientActiveObject *)> &f) +{ + g_profiler->avg("Client::ActiveObjectMgr: num of objects", + m_active_objects.size()); + for (auto &ao_it : m_active_objects) { + f(ao_it.second); + } +} + +// clang-format off +bool ActiveObjectMgr::registerObject(ClientActiveObject *obj) +{ + assert(obj); // Pre-condition + if (obj->getId() == 0) { + u16 new_id = getFreeId(); + if (new_id == 0) { + infostream << "Client::ActiveObjectMgr::registerObject(): " + << "no free id available" << std::endl; + + delete obj; + return false; + } + obj->setId(new_id); + } + + 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; + return true; +} + +void ActiveObjectMgr::removeObject(u16 id) +{ + verbosestream << "Client::ActiveObjectMgr::removeObject(): " + << "id=" << id << std::endl; + ClientActiveObject *obj = getActiveObject(id); + if (!obj) { + infostream << "Client::ActiveObjectMgr::removeObject(): " + << "id=" << id << " not found" << std::endl; + return; + } + + m_active_objects.erase(id); + + obj->removeFromScene(true); + delete obj; +} + +// clang-format on +void ActiveObjectMgr::getActiveObjects(const v3f &origin, f32 max_d, + std::vector<DistanceSortedActiveObject> &dest) +{ + for (auto &ao_it : m_active_objects) { + ClientActiveObject *obj = ao_it.second; + + f32 d = (obj->getPosition() - origin).getLength(); + + if (d > max_d) + continue; + + dest.emplace_back(obj, d); + } +} + +} // namespace client diff --git a/src/client/activeobjectmgr.h b/src/client/activeobjectmgr.h new file mode 100644 index 000000000..510b2d6e3 --- /dev/null +++ b/src/client/activeobjectmgr.h @@ -0,0 +1,41 @@ +/* +Minetest +Copyright (C) 2010-2018 nerzhul, Loic BLOT <loic.blot@unix-experience.fr> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#include <functional> +#include <vector> +#include "../activeobjectmgr.h" +#include "clientobject.h" + +namespace client +{ +class ActiveObjectMgr : public ::ActiveObjectMgr<ClientActiveObject> +{ +public: + void clear(); + void step(float dtime, + const std::function<void(ClientActiveObject *)> &f) override; + bool registerObject(ClientActiveObject *obj) override; + void removeObject(u16 id) override; + + void getActiveObjects(const v3f &origin, f32 max_d, + std::vector<DistanceSortedActiveObject> &dest); +}; +} // namespace client diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index e2f24aaa3..7c2ec099c 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -53,10 +53,7 @@ ClientEnvironment::ClientEnvironment(ClientMap *map, ClientEnvironment::~ClientEnvironment() { - // delete active objects - for (auto &active_object : m_active_objects) { - delete active_object.second; - } + m_ao_manager.clear(); for (auto &simple_object : m_simple_objects) { delete simple_object; @@ -262,12 +259,10 @@ void ClientEnvironment::step(float dtime) Step active objects and update lighting of them */ - g_profiler->avg("CEnv: num of objects", m_active_objects.size()); bool update_lighting = m_active_object_light_update_interval.step(dtime, 0.21); - for (auto &ao_it : m_active_objects) { - ClientActiveObject* obj = ao_it.second; + auto cb_state = [this, dtime, update_lighting, day_night_ratio] (ClientActiveObject *cao) { // Step object - obj->step(dtime, this); + cao->step(dtime, this); if (update_lighting) { // Update lighting @@ -275,16 +270,18 @@ void ClientEnvironment::step(float dtime) bool pos_ok; // Get node at head - v3s16 p = obj->getLightPosition(); - MapNode n = m_map->getNodeNoEx(p, &pos_ok); + v3s16 p = cao->getLightPosition(); + MapNode n = this->m_map->getNodeNoEx(p, &pos_ok); if (pos_ok) light = n.getLightBlend(day_night_ratio, m_client->ndef()); else light = blend_light(day_night_ratio, LIGHT_SUN, 0); - obj->updateLight(light); + cao->updateLight(light); } - } + }; + + m_ao_manager.step(dtime, cb_state); /* Step and handle simple objects @@ -319,14 +316,6 @@ GenericCAO* ClientEnvironment::getGenericCAO(u16 id) return NULL; } -ClientActiveObject* ClientEnvironment::getActiveObject(u16 id) -{ - auto n = m_active_objects.find(id); - if (n == m_active_objects.end()) - return NULL; - return n->second; -} - bool isFreeClientActiveObjectId(const u16 id, ClientActiveObjectMap &objects) { @@ -336,7 +325,7 @@ bool isFreeClientActiveObjectId(const u16 id, u16 getFreeClientActiveObjectId(ClientActiveObjectMap &objects) { - //try to reuse id's as late as possible + // try to reuse id's as late as possible static u16 last_used_id = 0; u16 startid = last_used_id; for(;;) { @@ -351,43 +340,25 @@ u16 getFreeClientActiveObjectId(ClientActiveObjectMap &objects) u16 ClientEnvironment::addActiveObject(ClientActiveObject *object) { - assert(object); // Pre-condition - if(object->getId() == 0) - { - u16 new_id = getFreeClientActiveObjectId(m_active_objects); - if(new_id == 0) - { - infostream<<"ClientEnvironment::addActiveObject(): " - <<"no free ids available"<<std::endl; - delete object; - return 0; - } - object->setId(new_id); - } - if (!isFreeClientActiveObjectId(object->getId(), m_active_objects)) { - infostream<<"ClientEnvironment::addActiveObject(): " - <<"id is not free ("<<object->getId()<<")"<<std::endl; - delete object; + // Register object. If failed return zero id + if (!m_ao_manager.registerObject(object)) return 0; - } - infostream<<"ClientEnvironment::addActiveObject(): " - <<"added (id="<<object->getId()<<")"<<std::endl; - m_active_objects[object->getId()] = object; + object->addToScene(m_texturesource); - { // Update lighting immediately - u8 light = 0; - bool pos_ok; - // Get node at head - v3s16 p = object->getLightPosition(); - MapNode n = m_map->getNodeNoEx(p, &pos_ok); - if (pos_ok) - light = n.getLightBlend(getDayNightRatio(), m_client->ndef()); - else - light = blend_light(getDayNightRatio(), LIGHT_SUN, 0); + // Update lighting immediately + u8 light = 0; + bool pos_ok; - object->updateLight(light); - } + // Get node at head + v3s16 p = object->getLightPosition(); + MapNode n = m_map->getNodeNoEx(p, &pos_ok); + if (pos_ok) + light = n.getLightBlend(getDayNightRatio(), m_client->ndef()); + else + light = blend_light(getDayNightRatio(), LIGHT_SUN, 0); + + object->updateLight(light); return object->getId(); } @@ -423,21 +394,6 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, addActiveObject(obj); } -void ClientEnvironment::removeActiveObject(u16 id) -{ - verbosestream<<"ClientEnvironment::removeActiveObject(): " - <<"id="<<id<<std::endl; - ClientActiveObject* obj = getActiveObject(id); - if (obj == NULL) { - infostream<<"ClientEnvironment::removeActiveObject(): " - <<"id="<<id<<" not found"<<std::endl; - return; - } - obj->removeFromScene(true); - delete obj; - m_active_objects.erase(id); -} - void ClientEnvironment::processActiveObjectMessage(u16 id, const std::string &data) { ClientActiveObject *obj = getActiveObject(id); @@ -485,21 +441,6 @@ void ClientEnvironment::damageLocalPlayer(u8 damage, bool handle_hp) Client likes to call these */ -void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d, - std::vector<DistanceSortedActiveObject> &dest) -{ - for (auto &ao_it : m_active_objects) { - ClientActiveObject* obj = ao_it.second; - - f32 d = (obj->getPosition() - origin).getLength(); - - if (d > max_d) - continue; - - dest.emplace_back(obj, d); - } -} - ClientEnvEvent ClientEnvironment::getClientEnvEvent() { FATAL_ERROR_IF(m_client_event_queue.empty(), diff --git a/src/client/clientenvironment.h b/src/client/clientenvironment.h index 606070e3a..d167902d1 100644 --- a/src/client/clientenvironment.h +++ b/src/client/clientenvironment.h @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <ISceneManager.h> #include "clientobject.h" #include "util/numeric.h" +#include "activeobjectmgr.h" class ClientSimpleObject; class ClientMap; @@ -87,7 +88,10 @@ public: */ GenericCAO* getGenericCAO(u16 id); - ClientActiveObject* getActiveObject(u16 id); + ClientActiveObject* getActiveObject(u16 id) + { + return m_ao_manager.getActiveObject(id); + } /* Adds an active object to the environment. @@ -100,7 +104,10 @@ public: u16 addActiveObject(ClientActiveObject *object); void addActiveObject(u16 id, u8 type, const std::string &init_data); - void removeActiveObject(u16 id); + void removeActiveObject(u16 id) + { + m_ao_manager.removeObject(id); + } void processActiveObjectMessage(u16 id, const std::string &data); @@ -115,8 +122,11 @@ public: */ // Get all nearby objects - void getActiveObjects(v3f origin, f32 max_d, - std::vector<DistanceSortedActiveObject> &dest); + void getActiveObjects(const v3f &origin, f32 max_d, + std::vector<DistanceSortedActiveObject> &dest) + { + return m_ao_manager.getActiveObjects(origin, max_d, dest); + } bool hasClientEnvEvents() const { return !m_client_event_queue.empty(); } @@ -142,7 +152,7 @@ private: ITextureSource *m_texturesource; Client *m_client; ClientScripting *m_script = nullptr; - ClientActiveObjectMap m_active_objects; + client::ActiveObjectMgr m_ao_manager; std::vector<ClientSimpleObject*> m_simple_objects; std::queue<ClientEnvEvent> m_client_event_queue; IntervalLimiter m_active_object_light_update_interval; |