OregonCore  revision 3611e8a-git
Your Favourite TBC server
ObjectAccessor.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "ObjectAccessor.h"
19 #include "ObjectMgr.h"
20 #include "Player.h"
21 #include "Creature.h"
22 #include "GameObject.h"
23 #include "DynamicObject.h"
24 #include "Corpse.h"
25 #include "WorldSession.h"
26 #include "WorldPacket.h"
27 #include "Item.h"
28 #include "GridNotifiers.h"
29 #include "Map.h"
30 #include "ObjectGuid.h"
31 #include "World.h"
32 
33 #define CLASS_LOCK Oregon::ClassLevelLockable<ObjectAccessor, ACE_Thread_Mutex>
35 INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ACE_Thread_Mutex);
36 
38 {
39 }
40 
42 {
43  for (Player2CorpsesMapType::const_iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); ++itr)
44  {
45  itr->second->RemoveFromWorld();
46  delete itr->second;
47  }
48 }
49 
51 {
52  switch (GUID_HIPART(guid))
53  {
54  case HIGHGUID_PLAYER: return GetPlayer(p, guid);
55  case HIGHGUID_TRANSPORT:
57  case HIGHGUID_GAMEOBJECT: return GetGameObject(p, guid);
58  case HIGHGUID_UNIT: return GetCreature(p, guid);
59  case HIGHGUID_PET: return GetPet(p, guid);
60  case HIGHGUID_DYNAMICOBJECT: return GetDynamicObject(p, guid);
61  case HIGHGUID_CORPSE: return GetCorpse(p, guid);
62  default: return NULL;
63  }
64 }
65 
67 {
68  switch (GUID_HIPART(guid))
69  {
70  case HIGHGUID_ITEM:
71  if (typemask & TYPEMASK_ITEM && p.GetTypeId() == TYPEID_PLAYER)
72  return ((Player const&)p).GetItemByGuid(guid);
73  break;
74  case HIGHGUID_PLAYER:
75  if (typemask & TYPEMASK_PLAYER)
76  return GetPlayer(p, guid);
77  break;
79  if (typemask & TYPEMASK_GAMEOBJECT)
80  return GetGameObject(p, guid);
81  break;
82  case HIGHGUID_UNIT:
83  if (typemask & TYPEMASK_UNIT)
84  return GetCreature(p, guid);
85  break;
86  case HIGHGUID_PET:
87  if (typemask & TYPEMASK_UNIT)
88  return GetPet(p, guid);
89  break;
91  if (typemask & TYPEMASK_DYNAMICOBJECT)
92  return GetDynamicObject(p, guid);
93  break;
94  case HIGHGUID_TRANSPORT:
95  case HIGHGUID_CORPSE:
97  break;
98  }
99 
100  return NULL;
101 }
102 
104 {
105  return GetObjectInMap(guid, u.GetMap(), (Corpse*)NULL);
106 }
107 
109 {
110  return GetObjectInMap(guid, u.GetMap(), (GameObject*)NULL);
111 }
112 
114 {
115  return GetObjectInMap(guid, u.GetMap(), (DynamicObject*)NULL);
116 }
117 
119 {
120  return GetObjectInMap(guid, u.GetMap(), (Unit*)NULL);
121 }
122 
124 {
125  return GetObjectInMap(guid, u.GetMap(), (Creature*)NULL);
126 }
127 
129 {
130  return GetObjectInMap(guid, u.GetMap(), (Pet*)NULL);
131 }
132 
134 {
135  return GetObjectInMap(guid, u.GetMap(), (Player*)NULL);
136 }
137 
139 {
140  if (IS_PET_GUID(guid))
141  return GetPet(u, guid);
142 
143  if (IS_CREATURE_GUID(guid))
144  return GetCreature(u, guid);
145 
146  return NULL;
147 }
148 
150 {
151  return GetObjectInWorld(guid, (Pet*)NULL);
152 }
153 
155 {
156  if (!force)
157  return GetObjectInWorld(guid, (Player*)NULL);
158 
160 
162  for (HashMapHolder<Player>::MapType::iterator iter = m.begin(); iter != m.end(); ++iter)
163  if (iter->second->GetGUID() == guid)
164  return iter->second;
165 
166  return NULL;
167 }
168 
170 {
171  return GetObjectInWorld(guid, (Unit*)NULL);
172 }
173 
174 Player* ObjectAccessor::FindPlayerByName(const char* name, bool force)
175 {
177 
179  for (HashMapHolder<Player>::MapType::iterator iter = m.begin(); iter != m.end(); ++iter)
180  if (!strcmp(name, iter->second->GetName()) && (iter->second->IsInWorld() || force))
181  return iter->second;
182 
183  return NULL;
184 }
185 
187 {
190  for (HashMapHolder<Player>::MapType::iterator iter = m.begin(); iter != m.end(); ++iter)
191  if (iter->second->GetSession()->GetAccountId() == Id && (iter->second->IsInWorld() || force))
192  return iter->second;
193 
194  return NULL;
195 }
196 
198 {
201  for (HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr)
202  itr->second->SaveToDB();
203 }
204 
206 {
207  Guard guard(i_corpseGuard);
208 
209  Player2CorpsesMapType::iterator iter = i_player2corpse.find(guid);
210  if (iter == i_player2corpse.end())
211  return NULL;
212 
213  ASSERT(iter->second->GetType() != CORPSE_BONES);
214 
215  return iter->second;
216 }
217 
219 {
220  ASSERT(corpse && corpse->GetType() != CORPSE_BONES);
221 
222  if (corpse->FindMap())
223  {
224  corpse->DestroyForNearbyPlayers();
225  corpse->FindMap()->RemoveFromMap(corpse, false);
226  }
227  else
228  corpse->RemoveFromWorld();
229 
230  // Critical section
231  {
232  Guard guard(i_corpseGuard);
233 
234  Player2CorpsesMapType::iterator iter = i_player2corpse.find(corpse->GetOwnerGUID());
235  if (iter == i_player2corpse.end())
236  return;
237 
238  // build mapid*cellid -> guid_set map
239  CellCoord cellCoord = Oregon::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY());
240  sObjectMgr.DeleteCorpseCellData(corpse->GetMapId(), cellCoord.GetId(), GUID_LOPART(corpse->GetOwnerGUID()));
241 
242  i_player2corpse.erase(iter);
243  }
244 }
245 
247 {
248  ASSERT(corpse && corpse->GetType() != CORPSE_BONES);
249 
250  // Critical section
251  {
252  Guard guard(i_corpseGuard);
253 
254  ASSERT(i_player2corpse.find(corpse->GetOwnerGUID()) == i_player2corpse.end());
255  i_player2corpse[corpse->GetOwnerGUID()] = corpse;
256 
257  // build mapid*cellid -> guid_set map
258  CellCoord cellCoord = Oregon::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY());
259  sObjectMgr.AddCorpseCellData(corpse->GetMapId(), cellCoord.GetId(), GUID_LOPART(corpse->GetOwnerGUID()), corpse->GetInstanceId());
260  }
261 }
262 
263 void ObjectAccessor::AddCorpsesToGrid(GridCoord const& gridpair, GridType& grid, Map* map)
264 {
265  Guard guard(i_corpseGuard);
266 
267  for (Player2CorpsesMapType::iterator iter = i_player2corpse.begin(); iter != i_player2corpse.end(); ++iter)
268  {
269  if (iter->second->IsInGrid())
270  {
271  //TODO: add this assert later
272  //ASSERT(iter->second->GetGridCoord() == gridpair);
273  continue;
274  }
275 
276  if (iter->second->GetGridCoord() == gridpair)
277  {
278  // verify, if the corpse in our instance (add only corpses which are)
279  if (map->Instanceable())
280  {
281  if (iter->second->GetInstanceId() == map->GetInstanceId())
282  grid.AddWorldObject(iter->second);
283  }
284  else
285  grid.AddWorldObject(iter->second);
286  }
287  }
288 }
289 
291 {
292  Corpse* corpse = GetCorpseForPlayerGUID(player_guid);
293  if (!corpse)
294  {
295  //in fact this function is called from several places
296  //even when player doesn't have a corpse, not an error
297  //sLog.outError("Try remove corpse that not in map for GUID %ul", player_guid);
298  return NULL;
299  }
300 
301  float corpseX = corpse->GetPositionX();
302  float corpseY = corpse->GetPositionY();
303  float corpseZ = corpse->GetPositionZ();
304  float corpseO = corpse->GetOrientation();
305 
309 
310  DEBUG_LOG("Deleting Corpse and spawned bones.");
311 
312  Map* map = corpse->FindMap();
313 
314  // remove corpse from player_guid -> corpse map
315  RemoveCorpse(corpse);
316 
317  // remove corpse from DB
318  corpse->DeleteFromDB();
319 
320  Corpse* bones = NULL;
321  // create the bones only if the map and the grid is loaded at the corpse's location
322  // ignore bones creating option in case insignia
323  if (map && (insignia ||
325  !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY()))
326  {
327  // Create bones, don't change Corpse
328  bones = new Corpse;
329  bones->Create(corpse->GetGUIDLow(), map);
330 
331  for (int i = 3; i < CORPSE_END; ++i) // don't overwrite guid and object type
332  bones->SetUInt32Value(i, corpse->GetUInt32Value(i));
333 
334  bones->SetGridCoord(corpse->GetGridCoord());
335  // bones->m_time = m_time; // don't overwrite time
336  // bones->m_inWorld = m_inWorld; // don't overwrite in-world state
337  // bones->m_type = m_type; // don't overwrite type
338  bones->Relocate(corpseX, corpseY, corpseZ, corpseO);
339 
342 
343  for (int i = 0; i < EQUIPMENT_SLOT_END; ++i)
344  {
345  if (corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i))
346  bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0);
347  }
348 
349  // add bones in grid store if grid loaded where corpse placed
350  map->AddToMap(bones);
351  }
352 
353  // all references to the corpse should be removed at this point
354  delete corpse;
355 
356  return bones;
357 }
358 
360 {
361  time_t now = time(NULL);
362  Player2CorpsesMapType::iterator next;
363  for (Player2CorpsesMapType::iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); itr = next)
364  {
365  next = itr;
366  ++next;
367 
368  if (!itr->second->IsExpired(now))
369  continue;
370 
371  ConvertCorpseForPlayer(itr->first);
372  }
373 }
374 
376 {
377  UpdateDataMapType update_players;
378 
379  // Critical section
380  {
381  Guard guard(i_updateGuard);
382 
383  while (!i_objects.empty())
384  {
385  Object* obj = *i_objects.begin();
386  ASSERT(obj && obj->IsInWorld());
387  i_objects.erase(i_objects.begin());
388  obj->BuildUpdate(update_players);
389  }
390  }
391 
392  WorldPacket packet; // here we allocate a std::vector with a size of 0x10000
393  for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
394  {
395  iter->second.BuildPacket(&packet);
396  iter->first->GetSession()->SendPacket(&packet);
397  packet.clear(); // clean the string
398  }
399 }
400 
401 // Define the static members of HashMapHolder
402 
403 template <class T> UNORDERED_MAP< uint64, T* > HashMapHolder<T>::m_objectMap;
404 template <class T> ACE_Thread_Mutex HashMapHolder<T>::i_lock;
405 
406 // Global definitions for the hashmap storage
407 
408 template class HashMapHolder<Player>;
409 template class HashMapHolder<Pet>;
410 template class HashMapHolder<GameObject>;
411 template class HashMapHolder<DynamicObject>;
412 template class HashMapHolder<Creature>;
413 template class HashMapHolder<Corpse>;
414 
415 template Player* ObjectAccessor::GetObjectInWorld<Player>(uint32 mapid, float x, float y, uint64 guid, Player* /*fake*/);
416 template Pet* ObjectAccessor::GetObjectInWorld<Pet>(uint32 mapid, float x, float y, uint64 guid, Pet* /*fake*/);
417 template Creature* ObjectAccessor::GetObjectInWorld<Creature>(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/);
418 template Corpse* ObjectAccessor::GetObjectInWorld<Corpse>(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/);
419 template GameObject* ObjectAccessor::GetObjectInWorld<GameObject>(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/);
420 template DynamicObject* ObjectAccessor::GetObjectInWorld<DynamicObject>(uint32 mapid, float x, float y, uint64 guid, DynamicObject* /*fake*/);
421 
Definition: Object.h:124
void AddCorpsesToGrid(GridCoord const &gridpair, GridType &grid, Map *map)
bool IsBattlegroundOrArena() const
Definition: Map.h:447
bool AddToMap(T *)
Definition: Map.cpp:424
Definition: Corpse.h:48
void RemoveCorpse(Corpse *corpse)
void DeleteFromDB()
Definition: Corpse.cpp:148
const uint32 & GetUInt32Value(uint16 index) const
Definition: Object.h:228
#define GUID_LOPART(x)
Definition: ObjectGuid.h:110
static MapType & GetContainer()
std::set< Object * > i_objects
Map * GetMap() const
Definition: Object.h:829
static WorldObject * GetWorldObject(WorldObject const &, uint64)
static Object * GetObjectByTypeMask(WorldObject const &, uint64, uint32 typemask)
static Unit * FindUnit(uint64)
INSTANTIATE_SINGLETON_2(ObjectAccessor, CLASS_LOCK)
virtual void BuildUpdate(UpdateDataMapType &)
Definition: Object.h:380
void RemoveFromWorld() override
Definition: Corpse.cpp:55
void RemoveFromMap(T *, bool)
Definition: Map.cpp:688
static Pet * FindPet(uint64)
void SetUInt32Value(uint16 index, uint32 value)
Definition: Object.cpp:779
static DynamicObject * GetDynamicObject(WorldObject const &u, uint64 guid)
Definition: Grid.h:45
static Creature * GetCreatureOrPet(WorldObject const &, uint64)
UNORDERED_MAP< uint64, T * > MapType
#define GUID_HIPART(x)
Definition: ObjectGuid.h:82
uint32 GetGUIDLow() const
Definition: Object.h:160
static Player * GetPlayer(WorldObject const &, uint64 guid)
#define sObjectMgr
Definition: ObjectMgr.h:1285
#define IS_PET_GUID(Guid)
Definition: ObjectGuid.h:67
#define CLASS_LOCK
Player2CorpsesMapType i_player2corpse
CorpseType GetType() const
Definition: Corpse.h:79
Player * FindPlayerByAccountId(uint64 Id, bool force=false)
uint8 GetTypeId() const
Definition: Object.h:204
float GetOrientation() const
Definition: Position.h:100
void Relocate(float x, float y)
Definition: Position.h:65
static T * GetObjectInWorld(uint64 guid, T *)
const bool & IsInWorld() const
Definition: Object.h:129
#define IS_CREATURE_GUID(Guid)
Definition: ObjectGuid.h:66
static Creature * GetCreature(WorldObject const &u, uint64 guid)
bool Create(uint32 guidlow, Map *map)
Definition: Corpse.cpp:64
Map * FindMap() const
Definition: Object.h:830
void AddCorpse(Corpse *corpse)
void Update(uint32 diff)
float GetPositionY() const
Definition: Position.h:98
static Player * FindPlayer(uint64, bool force=false)
uint32 GetInstanceId() const
Definition: Object.h:682
float GetPositionZ() const
Definition: Position.h:99
#define DEBUG_LOG(...)
Definition: Log.h:194
INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ACE_Thread_Mutex)
uint32 GetMapId() const
Definition: Object.h:585
UNORDERED_MAP< Player *, UpdateData > UpdateDataMapType
Definition: Object.h:120
Definition: Map.h:266
void SetUInt64Value(uint16 index, const uint64 &value)
Definition: Object.cpp:798
CellCoord ComputeCellCoord(float x, float y)
Definition: GridDefines.h:167
Corpse * GetCorpseForPlayerGUID(uint64 guid)
LockType i_corpseGuard
ACE_UINT64 uint64
Definition: Define.h:70
static Pet * GetPet(WorldObject const &, uint64 guid)
uint64 const & GetOwnerGUID() const
Definition: Corpse.h:66
LockType i_updateGuard
static GameObject * GetGameObject(WorldObject const &u, uint64 guid)
GridCoord const & GetGridCoord() const
Definition: Corpse.h:84
#define ASSERT
Definition: Errors.h:33
bool Instanceable() const
Definition: Map.h:422
static Unit * GetUnit(WorldObject const &, uint64 guid)
void DestroyForNearbyPlayers()
Definition: Object.cpp:2554
#define sWorld
Definition: World.h:860
bool IsRemovalGrid(float x, float y) const
Definition: Map.h:301
Player * FindPlayerByName(const char *name, bool force=false)
static T * GetObjectInMap(uint64 guid, Map *map, T *)
ACE_UINT32 uint32
Definition: Define.h:71
float GetPositionX() const
Definition: Position.h:97
static Corpse * GetCorpse(WorldObject const &u, uint64 guid)
Definition: Unit.h:884
Corpse * ConvertCorpseForPlayer(uint64 player_guid, bool insignia=false)
Definition: Player.h:922
uint32 GetInstanceId() const
Definition: Map.h:390
void clear()
Definition: ByteBuffer.h:73
uint32 GetId() const
Definition: GridDefines.h:136
Definition: Pet.h:146
void AddWorldObject(SPECIFIC_OBJECT *obj)
Definition: Grid.h:58
void SetGridCoord(GridCoord const &grid)
Definition: Corpse.h:88