2 // SPDX-License-Identifier: LGPL-2.1-or-later
3 // Copyright (C) 2010-2018 nerzhul, Loic BLOT <loic.blot@unix-experience.fr>
8 #include "activeobjectmgr.h"
13 ActiveObjectMgr::~ActiveObjectMgr()
15 if (!m_active_objects
.empty()) {
16 warningstream
<< "server::ActiveObjectMgr::~ActiveObjectMgr(): not cleared."
22 void ActiveObjectMgr::clearIf(const std::function
<bool(ServerActiveObject
*, u16
)> &cb
)
24 for (auto &it
: m_active_objects
.iter()) {
27 if (cb(it
.second
.get(), it
.first
)) {
28 // Remove reference from m_active_objects
29 m_active_objects
.remove(it
.first
);
34 void ActiveObjectMgr::step(
35 float dtime
, const std::function
<void(ServerActiveObject
*)> &f
)
39 for (auto &ao_it
: m_active_objects
.iter()) {
43 f(ao_it
.second
.get());
46 g_profiler
->avg("ActiveObjectMgr: SAO count [#]", count
);
49 bool ActiveObjectMgr::registerObject(std::unique_ptr
<ServerActiveObject
> obj
)
51 assert(obj
); // Pre-condition
52 if (obj
->getId() == 0) {
53 u16 new_id
= getFreeId();
55 errorstream
<< "Server::ActiveObjectMgr::addActiveObjectRaw(): "
56 << "no free id available" << std::endl
;
61 verbosestream
<< "Server::ActiveObjectMgr::addActiveObjectRaw(): "
62 << "supplied with id " << obj
->getId() << std::endl
;
65 if (!isFreeId(obj
->getId())) {
66 errorstream
<< "Server::ActiveObjectMgr::addActiveObjectRaw(): "
67 << "id is not free (" << obj
->getId() << ")" << std::endl
;
71 if (objectpos_over_limit(obj
->getBasePosition())) {
72 v3f p
= obj
->getBasePosition();
73 warningstream
<< "Server::ActiveObjectMgr::addActiveObjectRaw(): "
74 << "object position (" << p
.X
<< "," << p
.Y
<< "," << p
.Z
75 << ") outside maximum range" << std::endl
;
79 auto obj_id
= obj
->getId();
80 m_active_objects
.put(obj_id
, std::move(obj
));
82 auto new_size
= m_active_objects
.size();
83 verbosestream
<< "Server::ActiveObjectMgr::addActiveObjectRaw(): "
84 << "Added id=" << obj_id
<< "; there are now ";
85 if (new_size
== decltype(m_active_objects
)::unknown
)
86 verbosestream
<< "???";
88 verbosestream
<< new_size
;
89 verbosestream
<< " active objects." << std::endl
;
93 void ActiveObjectMgr::removeObject(u16 id
)
95 verbosestream
<< "Server::ActiveObjectMgr::removeObject(): "
96 << "id=" << id
<< std::endl
;
98 // this will take the object out of the map and then destruct it
99 bool ok
= m_active_objects
.remove(id
);
101 infostream
<< "Server::ActiveObjectMgr::removeObject(): "
102 << "id=" << id
<< " not found" << std::endl
;
106 void ActiveObjectMgr::invalidateActiveObjectObserverCaches()
108 for (auto &active_object
: m_active_objects
.iter()) {
109 ServerActiveObject
*obj
= active_object
.second
.get();
112 obj
->invalidateEffectiveObservers();
116 void ActiveObjectMgr::getObjectsInsideRadius(const v3f
&pos
, float radius
,
117 std::vector
<ServerActiveObject
*> &result
,
118 std::function
<bool(ServerActiveObject
*obj
)> include_obj_cb
)
120 float r2
= radius
* radius
;
121 for (auto &activeObject
: m_active_objects
.iter()) {
122 ServerActiveObject
*obj
= activeObject
.second
.get();
125 const v3f
&objectpos
= obj
->getBasePosition();
126 if (objectpos
.getDistanceFromSQ(pos
) > r2
)
129 if (!include_obj_cb
|| include_obj_cb(obj
))
130 result
.push_back(obj
);
134 void ActiveObjectMgr::getObjectsInArea(const aabb3f
&box
,
135 std::vector
<ServerActiveObject
*> &result
,
136 std::function
<bool(ServerActiveObject
*obj
)> include_obj_cb
)
138 for (auto &activeObject
: m_active_objects
.iter()) {
139 ServerActiveObject
*obj
= activeObject
.second
.get();
142 const v3f
&objectpos
= obj
->getBasePosition();
143 if (!box
.isPointInside(objectpos
))
146 if (!include_obj_cb
|| include_obj_cb(obj
))
147 result
.push_back(obj
);
151 void ActiveObjectMgr::getAddedActiveObjectsAroundPos(
152 const v3f
&player_pos
, const std::string
&player_name
,
153 f32 radius
, f32 player_radius
,
154 const std::set
<u16
> ¤t_objects
,
155 std::vector
<u16
> &added_objects
)
158 Go through the object list,
159 - discard removed/deactivated objects,
160 - discard objects that are too far away,
161 - discard objects that are found in current_objects,
162 - discard objects that are not observed by the player.
163 - add remaining objects to added_objects
165 for (auto &ao_it
: m_active_objects
.iter()) {
166 u16 id
= ao_it
.first
;
169 ServerActiveObject
*object
= ao_it
.second
.get();
173 if (object
->isGone())
176 f32 distance_f
= object
->getBasePosition().getDistanceFrom(player_pos
);
177 if (object
->getType() == ACTIVEOBJECT_TYPE_PLAYER
) {
178 // Discard if too far
179 if (distance_f
> player_radius
&& player_radius
!= 0)
181 } else if (distance_f
> radius
)
184 if (!object
->isEffectivelyObservedBy(player_name
))
187 // Discard if already on current_objects
188 auto n
= current_objects
.find(id
);
189 if (n
!= current_objects
.end())
191 // Add to added_objects
192 added_objects
.push_back(id
);
196 } // namespace server