OregonCore  revision 3611e8a-git
Your Favourite TBC server
MapManager.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 "MapManager.h"
19 #include "InstanceSaveMgr.h"
20 #include "Database/DatabaseEnv.h"
21 #include "Log.h"
22 #include "ObjectAccessor.h"
23 #include "Transports.h"
24 #include "GridDefines.h"
25 #include "MapInstanced.h"
26 #include "World.h"
27 #include "Corpse.h"
28 #include "ObjectMgr.h"
29 
30 #define CLASS_LOCK Oregon::ClassLevelLockable<MapManager, ACE_Thread_Mutex>
32 INSTANTIATE_CLASS_MUTEX(MapManager, ACE_Thread_Mutex);
33 
34 extern GridState* si_GridStates[]; // debugging code, should be deleted some day
35 
37 {
40 }
41 
43 {
44  for (MapMapType::iterator iter = i_maps.begin(); iter != i_maps.end(); ++iter)
45  delete iter->second;
46 
47  for (TransportSet::iterator i = m_Transports.begin(); i != m_Transports.end(); ++i)
48  delete *i;
49 
51 }
52 
54 {
56 
57  // debugging code, should be deleted some day
58  {
59  for (uint8 i = 0; i < MAX_GRID_STATE; ++i)
60  i_GridStates[i] = si_GridStates[i];
61 
63  }
64  int num_threads(sWorld.getConfig(CONFIG_NUMTHREADS));
65  // Start mtmaps if needed.
66  if (num_threads > 0 && m_updater.activate(num_threads) == -1)
67  abort();
68 
70 }
71 
73 {
74  for (MapMapType::iterator iter = i_maps.begin(); iter != i_maps.end(); ++iter)
75  (*iter).second->InitVisibilityDistance();
76 }
77 
78 // debugging code, should be deleted some day
80 {
81  bool ok = true;
82  for (int i = 0; i < MAX_GRID_STATE; i++)
83  {
84  if (i_GridStates[i] != si_GridStates[i])
85  {
86  sLog.outError("MapManager::checkGridStates(), GridState: si_GridStates is currupt !!!");
87  ok = false;
88  si_GridStates[i] = i_GridStates[i];
89  }
90  #if 0 // OREGON_DEBUG
91  // inner class checking only when compiled with debug
92  if (!si_GridStates[i]->checkMagic())
93  {
94  ok = false;
95  si_GridStates[i]->setMagic();
96  }
97  #endif
98  }
99  if (!ok)
101  if (i_GridStateErrorCount > 2)
102  ASSERT(false); // force a crash. Too many errors
103 }
104 
106 {
107  Map* m = _findMap(id);
108 
109  if (m == NULL)
110  {
111  Guard guard(*this);
112 
113  const MapEntry* entry = sMapStore.LookupEntry(id);
114  if (entry && entry->Instanceable())
115  m = new MapInstanced(id, i_gridCleanUpDelay);
116  else
117  m = new Map(id, i_gridCleanUpDelay, 0, DIFFICULTY_NORMAL);
118  i_maps[id] = m;
119  }
120 
121  ASSERT(m != NULL);
122  return m;
123 }
124 
125 Map* MapManager::CreateMap(uint32 id, const WorldObject* obj, uint32 loginInstanceId)
126 {
127  ASSERT(obj);
128  //if (!obj->IsInWorld()) sLog.outError("GetMap: called for map %d with object (typeid %d, guid %d, mapid %d, instanceid %d) who is not in world!", id, obj->GetTypeId(), obj->GetGUIDLow(), obj->GetMapId(), obj->GetInstanceId());
129  Map* m = _createBaseMap(id);
130 
131  if (m && (obj->GetTypeId() == TYPEID_PLAYER) && m->Instanceable())
132  m = ((MapInstanced*)m)->CreateInstanceForPlayer(id, (Player*)obj, loginInstanceId);
133 
134  return m;
135 }
136 
137 Map* MapManager::FindMap(uint32 mapid, uint32 instanceId) const
138 {
139  Map* map = _findMap(mapid);
140  if (!map)
141  return NULL;
142 
143  if (!map->Instanceable())
144  return instanceId == 0 ? map : NULL;
145 
146  return ((MapInstanced*)map)->FindInstanceMap(instanceId);
147 }
148 
149 /*
150  checks that do not require a map to be created
151  will send transfer error messages on fail
152 */
154 {
155  const MapEntry* entry = sMapStore.LookupEntry(mapid);
156  if (!entry)
158 
159  if (!entry->IsDungeon())
160  return Map::CAN_ENTER;
161 
162  InstanceTemplate const* instance = sObjectMgr.GetInstanceTemplate(mapid);
163  if (!instance)
165 
166  //The player has a heroic mode and tries to enter into instance which has no a heroic mode
167  if (!entry->SupportsHeroicMode() && player->GetDifficulty() == DIFFICULTY_HEROIC)
169 
170  //Bypass checks for GMs
171  if (player->IsGameMaster())
172  return Map::CAN_ENTER;
173 
174  const char* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()];
175 
176  Group* group = player->GetGroup();
177  if (entry->IsRaid()) // can only enter in a raid group
178  if ((!group || !group->isRaidGroup()) && !sWorld.getConfig(CONFIG_INSTANCE_IGNORE_RAID))
180 
181 
182  if (!player->IsAlive())
183  {
184  if (Corpse* corpse = player->GetCorpse())
185  {
186  // let enter in ghost mode in instance that connected to inner instance with corpse
187  uint32 instance_map = corpse->GetMapId();
188  do
189  {
190  if (instance_map == mapid)
191  break;
192 
193  InstanceTemplate const* instance = sObjectMgr.GetInstanceTemplate(instance_map);
194  instance_map = instance ? instance->parent : 0;
195  }
196  while (instance_map);
197 
198  if (!instance_map)
200 
201  sLog.outDebug("MAP: Player '%s' has corpse in instance '%s' and can enter", player->GetName(), mapName);
202  }
203  else
204  sLog.outDebug("Map::CanEnter - player '%s' is dead but doesn't have a corpse!", player->GetName());
205  }
206 
207  //Get instance where player's group is bound & its map
208  if (!loginCheck && group)
209  {
210  InstanceGroupBind* boundInstance = group->GetBoundInstance(entry);
211  if (boundInstance && boundInstance->save)
212  if (Map* boundMap = MapManager::Instance().FindMap(mapid, boundInstance->save->GetInstanceId()))
213  if (Map::EnterState denyReason = boundMap->CannotEnter(player))
214  return denyReason;
215  }
216 
217  // @todo Implement 5 dungeons per hour limit
218 
219  if (player->Satisfy(sObjectMgr.GetAccessRequirement(instance->access_id), mapid, true))
220  return Map::CAN_ENTER;
221  else
223 }
224 
225 void MapManager::Update(time_t diff)
226 {
227  i_timer.Update(diff);
228  if (!i_timer.Passed())
229  return;
230 
231  MapMapType::iterator iter = i_maps.begin();
232  for (; iter != i_maps.end(); ++iter)
233  {
234  if (m_updater.activated())
235  m_updater.schedule_update(*iter->second, i_timer.GetCurrent());
236  else
237  iter->second->Update(i_timer.GetCurrent());
238  }
239  if (m_updater.activated())
240  m_updater.wait();
241 
242  for (iter = i_maps.begin(); iter != i_maps.end(); ++iter)
243  iter->second->DelayedUpdate(uint32(i_timer.GetCurrent()));
244 
246  for (TransportSet::iterator iter = m_Transports.begin(); iter != m_Transports.end(); ++iter)
247  (*iter)->Update(i_timer.GetCurrent());
248 
249  i_timer.SetCurrent(0);
250 }
251 
253 {
254 }
255 
256 bool MapManager::ExistMapAndVMap(uint32 mapid, float x, float y)
257 {
259 
260  int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord;
261  int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord;
262 
263  return Map::ExistMap(mapid, gx, gy) && Map::ExistVMap(mapid, gx, gy);
264 }
265 
267 {
268  MapEntry const* mEntry = sMapStore.LookupEntry(mapid);
269  return mEntry && (!mEntry->Instanceable() || sObjectMgr.GetInstanceTemplate(mapid));
270 }
271 
273 {
274  for (MapMapType::iterator iter = i_maps.begin(); iter != i_maps.end(); ++iter)
275  iter->second->UnloadAll();
276 
277  while (!i_maps.empty())
278  {
279  delete i_maps.begin()->second;
280  i_maps.erase(i_maps.begin());
281  }
282 
283  if (m_updater.activated())
285 }
286 
288 {
289  i_MaxInstanceId = 0;
290 
291  QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT MAX(id) FROM instance");
292  if (result)
293  i_MaxInstanceId = result->Fetch()[0].GetUInt32();
294 }
295 
297 {
298  Guard guard(*this);
299 
300  uint32 ret = 0;
301  for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr)
302  {
303  Map* map = itr->second;
304  if (!map->Instanceable())
305  continue;
306  MapInstanced::InstancedMaps& maps = ((MapInstanced*)map)->GetInstancedMaps();
307  for (MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr)
308  if (mitr->second->IsDungeon()) ret++;
309  }
310  return ret;
311 }
312 
314 {
315  Guard guard(*this);
316 
317  uint32 ret = 0;
318  for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr)
319  {
320  Map* map = itr->second;
321  if (!map->Instanceable())
322  continue;
323  MapInstanced::InstancedMaps& maps = ((MapInstanced*)map)->GetInstancedMaps();
324  for (MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr)
325  if (mitr->second->IsDungeon())
326  ret += ((InstanceMap*)mitr->second)->GetPlayers().getSize();
327  }
328  return ret;
329 }
330 
InstanceSave * save
Definition: Group.h:145
Group * GetGroup()
Definition: Player.h:2589
Definition: Corpse.h:48
INSTANTIATE_CLASS_MUTEX(MapManager, ACE_Thread_Mutex)
int deactivate()
Definition: MapUpdater.cpp:92
static bool ExistVMap(uint32 mapid, int gx, int gy)
Definition: Map.cpp:84
Map::EnterState PlayerCannotEnter(uint32 mapid, Player *player, bool loginCheck=false)
Definition: MapManager.cpp:153
int activate(size_t num_threads)
Definition: MapUpdater.cpp:87
bool isRaidGroup() const
Definition: Group.h:210
static void DeleteStateMachine()
Definition: Map.cpp:194
GridState * si_GridStates[]
Definition: Map.cpp:38
int wait()
Definition: MapUpdater.cpp:99
time_t GetCurrent() const
Definition: Timer.h:130
bool Instanceable() const
Definition: DBCStructure.h:554
uint32 i_MaxInstanceId
Definition: MapManager.h:170
GridState * i_GridStates[MAX_GRID_STATE]
Definition: MapManager.h:149
UNORDERED_MAP< uint32, Map * > InstancedMaps
Definition: MapInstanced.h:28
void Update(time_t diff)
Definition: Timer.h:104
Map * _findMap(uint32 id) const
Definition: MapManager.h:159
#define sLog
Log class singleton.
Definition: Log.h:187
uint32 getSize() const
Definition: LinkedList.h:115
#define MAX_NUMBER_OF_GRIDS
Definition: GridDefines.h:33
QueryResult_AutoPtr Query(const char *sql)
Definition: Database.cpp:383
int schedule_update(Map &map, ACE_UINT32 diff)
Definition: MapUpdater.cpp:109
uint32 GetNumPlayersInInstances()
Definition: MapManager.cpp:313
static bool ExistMapAndVMap(uint32 mapid, float x, float y)
Definition: MapManager.cpp:256
bool Passed()
Definition: Timer.h:109
uint32 i_gridCleanUpDelay
Definition: MapManager.h:166
uint32 y_coord
Definition: GridDefines.h:142
bool IsGameMaster() const
Definition: Player.h:1009
uint32 x_coord
Definition: GridDefines.h:141
LocaleConstant GetSessionDbcLocale() const
Definition: WorldSession.h:233
DungeonDifficulty GetDifficulty()
Definition: Player.h:1884
#define sObjectMgr
Definition: ObjectMgr.h:1285
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
void SetInterval(time_t interval)
Definition: Timer.h:122
MapMapType i_maps
Definition: MapManager.h:167
void InitializeVisibilityDistanceInfo()
Definition: MapManager.cpp:72
uint8 GetTypeId() const
Definition: Object.h:204
MapUpdater m_updater
Definition: MapManager.h:171
ACE_UINT8 uint8
Definition: Define.h:73
uint32 GetInstanceId()
#define CLASS_LOCK
Definition: MapManager.cpp:30
void Update(time_t)
Definition: MapManager.cpp:225
bool IsAlive() const
Definition: Unit.h:1433
void Update(uint32 diff)
INSTANTIATE_SINGLETON_2(MapManager, CLASS_LOCK)
bool IsDungeon() const
Definition: DBCStructure.h:550
Corpse * GetCorpse() const
Definition: Player.cpp:4386
void UnloadAll()
Definition: MapManager.cpp:272
Definition: Map.h:266
Map * FindMap(uint32 mapid, uint32 instanceId=0) const
Definition: MapManager.cpp:137
bool IsRaid() const
Definition: DBCStructure.h:558
void checkAndCorrectGridStatesArray()
Definition: MapManager.cpp:79
uint32 parent
Definition: Map.h:233
const char * GetName() const
Definition: Object.h:692
Map * CreateMap(uint32 mapId, const WorldObject *obj, uint32 loginInstanceId=0)
Definition: MapManager.cpp:125
int i_GridStateErrorCount
Definition: MapManager.h:150
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
void DoDelayedMovesAndRemoves()
Definition: MapManager.cpp:252
uint32 GetNumInstances()
Definition: MapManager.cpp:296
bool Satisfy(AccessRequirement const *, uint32 target_map, bool report=false)
Definition: Player.cpp:16034
#define ASSERT
Definition: Errors.h:33
bool Instanceable() const
Definition: Map.h:422
static bool ExistMap(uint32 mapid, int gx, int gy)
Definition: Map.cpp:57
void Initialize(void)
Definition: MapManager.cpp:53
TransportSet m_Transports
Definition: MapManager.h:127
EnterState
Definition: Map.h:399
WorldSession * GetSession() const
Definition: Player.h:1959
#define sWorld
Definition: World.h:860
void SetCurrent(time_t current)
Definition: Timer.h:118
InstanceGroupBind * GetBoundInstance(Player *player)
Definition: Group.cpp:1591
DatabaseType CharacterDatabase
Accessor to the character database.
Definition: Main.cpp:54
uint32 access_id
Definition: Map.h:236
ACE_UINT32 uint32
Definition: Define.h:71
Map * _createBaseMap(uint32 id)
Definition: MapManager.cpp:105
static void InitStateMachine()
Definition: Map.cpp:186
bool SupportsHeroicMode() const
Definition: DBCStructure.h:574
Definition: Player.h:922
bool activated()
Definition: MapUpdater.cpp:126
char * name[16]
Definition: DBCStructure.h:518
static bool IsValidMAP(uint32 mapid)
Definition: MapManager.cpp:266
void InitMaxInstanceId()
Definition: MapManager.cpp:287
IntervalTimer i_timer
Definition: MapManager.h:168
Definition: Group.h:154
GridCoord ComputeGridCoord(float x, float y)
Definition: GridDefines.h:162