Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
ObjectAccessor.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "CellImpl.h"
7#include "Corpse.h"
8#include "Creature.h"
9#include "DynamicObject.h"
10#include "GameObject.h"
11#include "GridNotifiers.h"
12#include "GridNotifiersImpl.h"
13#include "Item.h"
14#include "Map.h"
15#include "MapInstanced.h"
16#include "MapManager.h"
17#include "ObjectAccessor.h"
18#include "ObjectDefines.h"
19#include "ObjectMgr.h"
21#include "Opcodes.h"
22#include "Pet.h"
23#include "Player.h"
24#include "Vehicle.h"
25#include "World.h"
26#include "WorldPacket.h"
27
28#include <cmath>
29
30template<class T>
32{
33 SF_UNIQUE_GUARD writeGuard(*GetLock());
34 GetContainer()[o->GetGUID()] = o;
35}
36
37template<class T>
39{
40 SF_UNIQUE_GUARD writeGuard(*GetLock());
41 GetContainer().erase(o->GetGUID());
42}
43
44template<class T>
46{
47 SF_SHARED_GUARD readGuard(*GetLock());
48 typename MapType::iterator itr = GetContainer().find(guid);
49 return (itr != GetContainer().end()) ? itr->second : NULL;
50}
51
52template<class T>
54{
55 static MapType m_objectMap;
56 return m_objectMap;
57}
58
59template<class T>
65
67
68template class HashMapHolder<Player>;
69template class HashMapHolder<Pet>;
70template class HashMapHolder<GameObject>;
71template class HashMapHolder<DynamicObject>;
72template class HashMapHolder<Creature>;
73template class HashMapHolder<Corpse>;
74template class HashMapHolder<AreaTrigger>;
75
76
77
79
81
82template<class T> T* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, T* /*fake*/)
83{
84 T* obj = HashMapHolder<T>::Find(guid);
85 if (!obj || obj->GetMapId() != mapid)
86 return NULL;
87
89 if (!p.IsCoordValid())
90 {
91 SF_LOG_ERROR("misc", "ObjectAccessor::GetObjectInWorld: invalid coordinates supplied X:%f Y:%f grid cell [%u:%u]", x, y, p.x_coord, p.y_coord);
92 return NULL;
93 }
94
95 CellCoord q = Skyfire::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
96 if (!q.IsCoordValid())
97 {
98 SF_LOG_ERROR("misc", "ObjectAccessor::GetObjecInWorld: object (GUID: %u TypeId: %u) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUIDLow(), uint8(obj->GetTypeId()), obj->GetPositionX(), obj->GetPositionY(), q.x_coord, q.y_coord);
99 return NULL;
100 }
101
102 int32 dx = int32(p.x_coord) - int32(q.x_coord);
103 int32 dy = int32(p.y_coord) - int32(q.y_coord);
104
105 if (dx > -2 && dx < 2 && dy > -2 && dy < 2)
106 return obj;
107 else
108 return NULL;
109}
110
112{
113 Player* player = HashMapHolder<Player>::Find(guid);
114 return player && player->IsInWorld() ? player : NULL;
115}
116
118{
119 switch (GUID_HIPART(guid))
120 {
121 case HIGHGUID_PLAYER: return GetPlayer(p, guid);
124 case HIGHGUID_GAMEOBJECT: return GetGameObject(p, guid);
125 case HIGHGUID_VEHICLE:
126 case HIGHGUID_UNIT: return GetCreature(p, guid);
127 case HIGHGUID_PET: return GetPet(p, guid);
128 case HIGHGUID_DYNAMICOBJECT: return GetDynamicObject(p, guid);
129 case HIGHGUID_AREATRIGGER: return GetAreaTrigger(p, guid);
130 case HIGHGUID_CORPSE: return GetCorpse(p, guid);
131 default: return NULL;
132 }
133}
134
136{
137 switch (GUID_HIPART(guid))
138 {
139 case HIGHGUID_ITEM:
140 if (typemask & TYPEMASK_ITEM && p.GetTypeId() == TypeID::TYPEID_PLAYER)
141 return ((Player const&)p).GetItemByGuid(guid);
142 break;
143 case HIGHGUID_PLAYER:
144 if (typemask & TYPEMASK_PLAYER)
145 return GetPlayer(p, guid);
146 break;
150 if (typemask & TYPEMASK_GAMEOBJECT)
151 return GetGameObject(p, guid);
152 break;
153 case HIGHGUID_UNIT:
154 case HIGHGUID_VEHICLE:
155 if (typemask & TYPEMASK_UNIT)
156 return GetCreature(p, guid);
157 break;
158 case HIGHGUID_PET:
159 if (typemask & TYPEMASK_UNIT)
160 return GetPet(p, guid);
161 break;
163 if (typemask & TYPEMASK_DYNAMICOBJECT)
164 return GetDynamicObject(p, guid);
165 break;
167 if (typemask & TYPEMASK_AREATRIGGER)
168 return GetAreaTrigger(p, guid);
169 case HIGHGUID_CORPSE:
170 break;
171 }
172
173 return NULL;
174}
175
177{
178 return GetObjectInMap(guid, u.GetMap(), (Corpse*)NULL);
179}
180
182{
183 return GetObjectInMap(guid, u.GetMap(), (GameObject*)NULL);
184}
185
187{
189 return NULL;
190
191 return u.GetMap()->GetTransport(guid);
192}
193
198
200{
201 return GetObjectInMap(guid, u.GetMap(), (AreaTrigger*)NULL);
202}
203
205{
206 return GetObjectInMap(guid, u.GetMap(), (Unit*)NULL);
207}
208
210{
211 return GetObjectInMap(guid, u.GetMap(), (Creature*)NULL);
212}
213
215{
216 return GetObjectInMap(guid, u.GetMap(), (Pet*)NULL);
217}
218
220{
221 return GetObjectInMap(guid, u.GetMap(), (Player*)NULL);
222}
223
225{
226 if (IS_PET_GUID(guid))
227 return GetPet(u, guid);
228
229 if (IS_CRE_OR_VEH_GUID(guid))
230 return GetCreature(u, guid);
231
232 return NULL;
233}
234
236{
237 return GetObjectInWorld(guid, (Pet*)NULL);
238}
239
241{
242 return GetObjectInWorld(guid, (Player*)NULL);
243}
244
249
251{
252 return GetObjectInWorld(guid, (Unit*)NULL);
253}
254
256{
258 std::string nameStr = name;
259 std::transform(nameStr.begin(), nameStr.end(), nameStr.begin(), ::tolower);
261 for (HashMapHolder<Player>::MapType::const_iterator iter = m.begin(); iter != m.end(); ++iter)
262 {
263 if (!iter->second->IsInWorld())
264 continue;
265 std::string currentName = iter->second->GetName();
266 std::transform(currentName.begin(), currentName.end(), currentName.begin(), ::tolower);
267 if (nameStr.compare(currentName) == 0)
268 return iter->second;
269 }
270
271 return NULL;
272}
273
275{
278 for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr)
279 itr->second->SaveToDB();
280}
289
299
301{
302 SF_SHARED_GUARD readGuard(i_corpseLock);
303
304 Player2CorpsesMapType::iterator iter = i_player2corpse.find(guid);
305 if (iter == i_player2corpse.end())
306 return NULL;
307
308 ASSERT(iter->second->GetType() != CorpseType::CORPSE_BONES);
309
310 return iter->second;
311}
312
314{
315 ASSERT(corpse && corpse->GetType() != CorpseType::CORPSE_BONES);
316
318 if (Map* map = corpse->FindMap())
319 {
320 corpse->DestroyForNearbyPlayers();
321 if (corpse->IsInGrid())
322 map->RemoveFromMap(corpse, false);
323 else
324 {
325 corpse->RemoveFromWorld();
326 corpse->ResetMap();
327 }
328 }
329 else
330
331 corpse->RemoveFromWorld();
332
333 // Critical section
334 {
335 SF_UNIQUE_GUARD writeGuard(i_corpseLock);
336 Player2CorpsesMapType::iterator iter = i_player2corpse.find(corpse->GetOwnerGUID());
340 {
341 SF_LOG_ERROR("misc", "ObjectAccessor::RemoveCorpse: missing owner mapping for corpse %u owner %u after world removal.",
342 corpse->GetGUIDLow(), GUID_LOPART(corpse->GetOwnerGUID()));
343 return;
344 }
345
346 // build mapid*cellid -> guid_set map
347 CellCoord cellCoord = Skyfire::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY());
348 sObjectMgr->DeleteCorpseCellData(corpse->GetMapId(), cellCoord.GetId(), GUID_LOPART(corpse->GetOwnerGUID()));
349
350 i_player2corpse.erase(iter);
351 }
352}
353
355{
356 ASSERT(corpse && corpse->GetType() != CorpseType::CORPSE_BONES);
357
358 // Critical section
359 {
360 SF_UNIQUE_GUARD writeGuard(i_corpseLock);
361
365 i_player2corpse[corpse->GetOwnerGUID()] = corpse;
366
367 // build mapid*cellid -> guid_set map
368 CellCoord cellCoord = Skyfire::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY());
369 sObjectMgr->AddCorpseCellData(corpse->GetMapId(), cellCoord.GetId(), GUID_LOPART(corpse->GetOwnerGUID()), corpse->GetInstanceId());
370 }
371}
372
373void ObjectAccessor::AddCorpsesToGrid(GridCoord const& gridpair, GridType& grid, Map* map)
374{
375 SF_SHARED_GUARD readGuard(i_corpseLock);
376
377 for (Player2CorpsesMapType::iterator iter = i_player2corpse.begin(); iter != i_player2corpse.end(); ++iter)
378 {
379 // We need this check otherwise a corpose may be added to a grid twice
380 if (iter->second->IsInGrid())
381 continue;
382
383 if (iter->second->GetGridCoord() == gridpair)
384 {
385 // verify, if the corpse in our instance (add only corpses which are)
386 if (map->Instanceable())
387 {
388 if (iter->second->GetInstanceId() == map->GetInstanceId())
389 grid.AddWorldObject(iter->second);
390 }
391 else
392 grid.AddWorldObject(iter->second);
393 }
394 }
395}
396
397Corpse* ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia /*=false*/)
398{
399 Corpse* corpse = GetCorpseForPlayerGUID(player_guid);
400 if (!corpse)
401 {
402 //in fact this function is called from several places
403 //even when player doesn't have a corpse, not an error
404 return NULL;
405 }
406
407 SF_LOG_DEBUG("misc", "Deleting Corpse and spawned bones.");
408
409 // Map can be NULL
410 Map* map = corpse->FindMap();
411
412 // remove corpse from player_guid -> corpse map and from current map
413 RemoveCorpse(corpse);
414
415 // remove corpse from DB
416 SQLTransaction trans = CharacterDatabase.BeginTransaction();
417 corpse->DeleteFromDB(trans);
418 CharacterDatabase.CommitTransaction(trans);
419
420 Corpse* bones = NULL;
421 // create the bones only if the map and the grid is loaded at the corpse's location
422 // ignore bones creating option in case insignia
423
424 if (map && (insignia ||
426 !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY()))
427 {
428 // Create bones, don't change Corpse
429 bones = new Corpse;
430 bones->Create(corpse->GetGUIDLow(), map);
431
432 for (uint8 i = OBJECT_FIELD_TYPE + 1; i < CORPSE_END; ++i) // don't overwrite guid and object type
433 bones->SetUInt32Value(i, corpse->GetUInt32Value(i));
434
435 bones->SetGridCoord(corpse->GetGridCoord());
436 // bones->m_time = m_time; // don't overwrite time
437 // bones->m_type = m_type; // don't overwrite type
438 bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation());
439 bones->SetPhaseMask(corpse->GetPhaseMask(), false);
440
443
444 for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
445 {
446 if (corpse->GetUInt32Value(CORPSE_FIELD_ITEMS + i))
447 bones->SetUInt32Value(CORPSE_FIELD_ITEMS + i, 0);
448 }
449
450 // add bones in grid store if grid loaded where corpse placed
451 map->AddToMap(bones);
452 }
453
454 // all references to the corpse should be removed at this point
455 delete corpse;
456
457 return bones;
458}
459
461{
462 time_t now = time(NULL);
463 Player2CorpsesMapType::iterator next;
464 for (Player2CorpsesMapType::iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); itr = next)
465 {
466 next = itr;
467 ++next;
468
469 if (!itr->second->IsExpired(now))
470 continue;
471
472 ConvertCorpseForPlayer(itr->first);
473 }
474}
475
477{
478 UpdateDataMapType update_players;
479
480 for (;;)
481 {
482 Object* obj = NULL;
483 {
484 SF_UNIQUE_GUARD writeGuard(i_objectLock);
488 break;
489
490 obj = *i_objects.begin();
491 i_objects.erase(i_objects.begin());
492 }
493
495 obj->BuildUpdate(update_players);
496 }
497
498 WorldPacket packet; // here we allocate a std::vector with a size of 0x10000
499 for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
500 {
501 iter->second.BuildPacket(&packet);
502 iter->first->GetSession()->SendPacket(&packet);
503 packet.clear(); // clean the string
504 }
505}
506
508{
509 SF_UNIQUE_GUARD writeGuard(i_corpseLock);
513 return;
514
515 for (Player2CorpsesMapType::const_iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); ++itr)
516 {
517 itr->second->RemoveFromWorld();
518 delete itr->second;
519 }
520
521 i_player2corpse.clear();
522}
523
525
527template <class T> typename SF_SHARED_MUTEX HashMapHolder<T>::i_lock;
528
529
530template Player* ObjectAccessor::GetObjectInWorld<Player>(uint32 mapid, float x, float y, uint64 guid, Player* /*fake*/);
531template Pet* ObjectAccessor::GetObjectInWorld<Pet>(uint32 mapid, float x, float y, uint64 guid, Pet* /*fake*/);
532template Creature* ObjectAccessor::GetObjectInWorld<Creature>(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/);
533template Corpse* ObjectAccessor::GetObjectInWorld<Corpse>(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/);
534template GameObject* ObjectAccessor::GetObjectInWorld<GameObject>(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/);
535template DynamicObject* ObjectAccessor::GetObjectInWorld<DynamicObject>(uint32 mapid, float x, float y, uint64 guid, DynamicObject* /*fake*/);
@ CORPSE_BONES
Definition Corpse.h:16
@ CORPSE_FLAG_BONES
Definition Corpse.h:28
@ CORPSE_FLAG_UNK2
Definition Corpse.h:30
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
#define ASSERT
Definition Errors.h:29
CoordPair< MAX_NUMBER_OF_GRIDS > GridCoord
CoordPair< TOTAL_NUMBER_OF_CELLS_PER_MAP > CellCoord
Grid< Player, AllWorldObjectTypes, AllGridObjectTypes > GridType
Definition GridDefines.h:68
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
@ TYPEID_PLAYER
Definition Object.h:55
UNORDERED_MAP< Player *, UpdateData > UpdateDataMapType
Definition Object.h:107
@ TYPEMASK_ITEM
Definition Object.h:38
@ TYPEMASK_DYNAMICOBJECT
Definition Object.h:43
@ TYPEMASK_UNIT
Definition Object.h:40
@ TYPEMASK_GAMEOBJECT
Definition Object.h:42
@ TYPEMASK_PLAYER
Definition Object.h:41
@ TYPEMASK_AREATRIGGER
Definition Object.h:45
uint32 GUID_LOPART(uint64 x)
bool IS_PET_GUID(uint64 guid)
bool IS_CRE_OR_VEH_GUID(uint64 guid)
@ HIGHGUID_PET
@ HIGHGUID_AREATRIGGER
@ HIGHGUID_DYNAMICOBJECT
@ HIGHGUID_GAMEOBJECT
@ HIGHGUID_TRANSPORT
@ HIGHGUID_CORPSE
@ HIGHGUID_PLAYER
@ HIGHGUID_MO_TRANSPORT
@ HIGHGUID_UNIT
@ HIGHGUID_ITEM
@ HIGHGUID_VEHICLE
uint32 GUID_HIPART(uint64 guid)
#define sObjectMgr
Definition ObjectMgr.h:1617
@ EQUIPMENT_SLOT_END
Definition Player.h:708
#define SF_UNIQUE_GUARD
Definition SharedMutex.h:18
#define SF_SHARED_MUTEX
Definition SharedMutex.h:16
#define SF_SHARED_GUARD
Definition SharedMutex.h:17
Skyfire::AutoPtr< Transaction, Skyfire::Mutex > SQLTransaction
Definition Transaction.h:42
#define UNORDERED_MAP
@ CORPSE_FIELD_FLAGS
@ CORPSE_END
@ CORPSE_FIELD_OWNER
@ CORPSE_FIELD_ITEMS
@ OBJECT_FIELD_TYPE
void clear()
Definition ByteBuffer.h:141
void RemoveFromWorld()
Definition Corpse.cpp:35
void DeleteFromDB(SQLTransaction &trans)
Definition Corpse.cpp:122
void SetGridCoord(GridCoord const &gridCoord)
Definition Corpse.h:61
bool Create(uint32 guidlow, Map *map)
Definition Corpse.cpp:44
uint64 GetOwnerGUID() const
Definition Corpse.h:54
CorpseType GetType() const
Definition Corpse.h:58
GridCoord const & GetGridCoord() const
Definition Corpse.h:60
void AddWorldObject(SPECIFIC_OBJECT *obj)
Definition Grid.h:45
bool IsInGrid() const
Definition Object.h:556
static SF_SHARED_MUTEX * GetLock()
static T * Find(uint64 guid)
static void Remove(T *o)
static MapType m_objectMap
static MapType & GetContainer()
UNORDERED_MAP< uint64, T * > MapType
static void Insert(T *o)
static SF_SHARED_MUTEX i_lock
Definition Map.h:238
bool IsBattlegroundOrArena() const
Definition Map.h:378
Transport * GetTransport(uint64 guid)
Definition Map.cpp:3189
bool AddToMap(T *)
Definition Map.cpp:504
bool IsRemovalGrid(float x, float y) const
Definition Map.h:277
bool Instanceable() const
Definition Map.h:367
uint32 GetInstanceId() const
Definition Map.h:357
static Creature * GetCreature(WorldObject const &u, uint64 guid)
static AreaTrigger * GetAreaTrigger(WorldObject const &u, uint64 guid)
static void SaveAllPlayers()
SF_SHARED_MUTEX i_objectLock
static Pet * FindPet(uint64)
static Creature * GetCreatureOrPetOrVehicle(WorldObject const &, uint64)
static Player * FindPlayerByName(std::string const &name)
void AddCorpse(Corpse *corpse)
static T * GetObjectInMap(uint64 guid, Map *map, T *)
static Object * GetObjectByTypeMask(WorldObject const &, uint64, uint32 typemask)
static Transport * GetTransport(WorldObject const &u, uint64 guid)
static Player * FindPlayerInOrOutOfWorld(uint64)
void RemoveCorpse(Corpse *corpse)
static Player * GetPlayer(WorldObject const &, uint64 guid)
void AddUpdateObject(Object *obj)
SF_SHARED_MUTEX i_corpseLock
void RemoveUpdateObject(Object *obj)
static WorldObject * GetWorldObject(WorldObject const &, uint64)
static GameObject * GetGameObject(WorldObject const &u, uint64 guid)
static Unit * GetUnit(WorldObject const &, uint64 guid)
static HashMapHolder< Player >::MapType const & GetPlayers()
std::set< Object * > i_objects
static Corpse * GetCorpse(WorldObject const &u, uint64 guid)
static T * GetObjectInWorld(uint64 guid, T *)
Corpse * ConvertCorpseForPlayer(uint64 player_guid, bool insignia=false)
void Update(uint32 diff)
Player2CorpsesMapType i_player2corpse
void AddCorpsesToGrid(GridCoord const &gridpair, GridType &grid, Map *map)
static Player * FindPlayer(uint64)
static DynamicObject * GetDynamicObject(WorldObject const &u, uint64 guid)
static Unit * FindUnit(uint64)
Corpse * GetCorpseForPlayerGUID(uint64 guid)
static Pet * GetPet(WorldObject const &, uint64 guid)
static T * GetObjectInOrOutOfWorld(uint64 guid, T *)
uint32 GetUInt32Value(uint16 index) const
Definition Object.cpp:325
bool IsInWorld() const
Definition Object.h:114
uint32 GetGUIDLow() const
Definition Object.h:120
TypeID GetTypeId() const
Definition Object.h:131
virtual void BuildUpdate(UpdateDataMapType &)
Definition Object.h:195
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:1038
void SetUInt64Value(uint16 index, uint64 value)
Definition Object.cpp:1079
Definition Pet.h:28
Definition Unit.h:1367
uint32 GetMapId() const
Definition Object.h:546
virtual void SetPhaseMask(uint32 newPhaseMask, bool update)
Definition Object.cpp:3219
uint32 GetPhaseMask() const
Definition Object.h:643
Map * GetMap() const
Definition Object.h:740
virtual void ResetMap()
Definition Object.cpp:2532
Map * FindMap() const
Definition Object.h:741
uint32 GetInstanceId() const
Definition Object.h:638
void DestroyForNearbyPlayers()
Definition Object.cpp:3453
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition Main.cpp:41
#define sWorld
Definition World.h:910
@ CONFIG_DEATH_BONES_WORLD
Definition World.h:121
@ CONFIG_DEATH_BONES_BG_OR_ARENA
Definition World.h:122
ObjectUpdateQueueDrainAction GetUpdateObjectQueueDrainAction(bool empty)
ObjectCorpseStorageUnloadAction GetCorpseStorageUnloadAction(bool empty)
bool CanBuildUpdateForQueuedObject(bool hasObject, bool isInWorld)
ObjectCorpseOwnerRemoveAction GetCorpseOwnerMappingRemoveAction(bool mapped)
ObjectCorpseOwnerAddAction GetCorpseOwnerMappingAddAction(bool alreadyMapped)
ObjectUpdateQueueRemoveAction GetUpdateObjectQueueRemoveAction(bool queued)
ObjectUpdateQueueAddAction GetUpdateObjectQueueAddAction(bool alreadyQueued)
CellCoord ComputeCellCoord(float x, float y)
bool IsCoordValid() const
uint32 x_coord
uint32 y_coord
uint32 GetId() const
float GetPositionZ() const
Definition Object.h:330
float GetOrientation() const
Definition Object.h:331
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329
void Relocate(float x, float y)
Definition Object.h:302