OregonCore  revision be9e804-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 <https://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  //Other requirements
163  if (!player->Satisfy(sObjectMgr.GetAccessRequirement(mapid), mapid, true))
165 
166  InstanceTemplate const* instance = sObjectMgr.GetInstanceTemplate(mapid);
167  if (!instance)
169 
170  //The player has a heroic mode and tries to enter into instance which has no a heroic mode
171  if (!entry->SupportsHeroicMode() && player->GetDifficulty() == DIFFICULTY_HEROIC)
173 
174  //Bypass checks for GMs
175  if (player->IsGameMaster())
176  return Map::CAN_ENTER;
177 
178  const char* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()];
179 
180  Group* group = player->GetGroup();
181  if (entry->IsRaid()) // can only enter in a raid group
182  if ((!group || !group->isRaidGroup()) && !sWorld.getConfig(CONFIG_INSTANCE_IGNORE_RAID))
184 
185 
186  if (!player->IsAlive())
187  {
188  if (Corpse* corpse = player->GetCorpse())
189  {
190  // let enter in ghost mode in instance that connected to inner instance with corpse
191  uint32 instance_map = corpse->GetMapId();
192  do
193  {
194  if (instance_map == mapid)
195  break;
196 
197  InstanceTemplate const* instance = sObjectMgr.GetInstanceTemplate(instance_map);
198  instance_map = instance ? instance->parent : 0;
199  }
200  while (instance_map);
201 
202  if (!instance_map)
204 
205  sLog.outDebug("MAP: Player '%s' has corpse in instance '%s' and can enter", player->GetName(), mapName);
206  }
207  else
208  sLog.outDebug("Map::CanEnter - player '%s' is dead but doesn't have a corpse!", player->GetName());
209  }
210 
211  //Get instance where player's group is bound & its map
212  if (!loginCheck && group)
213  {
214  InstanceGroupBind* boundInstance = group->GetBoundInstance(entry);
215  if (boundInstance && boundInstance->save)
216  if (Map* boundMap = MapManager::Instance().FindMap(mapid, boundInstance->save->GetInstanceId()))
217  if (Map::EnterState denyReason = boundMap->CannotEnter(player))
218  return denyReason;
219  }
220 
221  // @todo Implement 5 dungeons per hour limit
222 
223  return Map::CAN_ENTER;
224 }
225 
226 void MapManager::Update(time_t diff)
227 {
228  i_timer.Update(diff);
229  if (!i_timer.Passed())
230  return;
231 
232  MapMapType::iterator iter = i_maps.begin();
233  for (; iter != i_maps.end(); ++iter)
234  {
235  if (m_updater.activated())
236  m_updater.schedule_update(*iter->second, i_timer.GetCurrent());
237  else
238  iter->second->Update(i_timer.GetCurrent());
239  }
240  if (m_updater.activated())
241  m_updater.wait();
242 
243  for (iter = i_maps.begin(); iter != i_maps.end(); ++iter)
244  iter->second->DelayedUpdate(uint32(i_timer.GetCurrent()));
245 
247  for (TransportSet::iterator iter = m_Transports.begin(); iter != m_Transports.end(); ++iter)
248  (*iter)->Update(i_timer.GetCurrent());
249 
250  i_timer.SetCurrent(0);
251 }
252 
254 {
255 }
256 
257 bool MapManager::ExistMapAndVMap(uint32 mapid, float x, float y)
258 {
260 
261  int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord;
262  int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord;
263 
264  return Map::ExistMap(mapid, gx, gy) && Map::ExistVMap(mapid, gx, gy);
265 }
266 
268 {
269  MapEntry const* mEntry = sMapStore.LookupEntry(mapid);
270  return mEntry && (!mEntry->Instanceable() || sObjectMgr.GetInstanceTemplate(mapid));
271 }
272 
274 {
275  for (MapMapType::iterator iter = i_maps.begin(); iter != i_maps.end(); ++iter)
276  iter->second->UnloadAll();
277 
278  while (!i_maps.empty())
279  {
280  delete i_maps.begin()->second;
281  i_maps.erase(i_maps.begin());
282  }
283 
284  if (m_updater.activated())
286 }
287 
289 {
290  i_MaxInstanceId = 0;
291 
292  QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT MAX(id) FROM instance");
293  if (result)
294  i_MaxInstanceId = result->Fetch()[0].GetUInt32();
295 }
296 
298 {
299  Guard guard(*this);
300 
301  uint32 ret = 0;
302  for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr)
303  {
304  Map* map = itr->second;
305  if (!map->Instanceable())
306  continue;
307  MapInstanced::InstancedMaps& maps = ((MapInstanced*)map)->GetInstancedMaps();
308  for (MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr)
309  if (mitr->second->IsDungeon()) ret++;
310  }
311  return ret;
312 }
313 
315 {
316  Guard guard(*this);
317 
318  uint32 ret = 0;
319  for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr)
320  {
321  Map* map = itr->second;
322  if (!map->Instanceable())
323  continue;
324  MapInstanced::InstancedMaps& maps = ((MapInstanced*)map)->GetInstancedMaps();
325  for (MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr)
326  if (mitr->second->IsDungeon())
327  ret += ((InstanceMap*)mitr->second)->GetPlayers().getSize();
328  }
329  return ret;
330 }
331 
InstanceSave * save
Definition: Group.h:145
Group * GetGroup()
Definition: Player.h:2577
Definition: Corpse.h:48
INSTANTIATE_CLASS_MUTEX(MapManager, ACE_Thread_Mutex)
int deactivate()
Definition: MapUpdater.cpp:84
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:79
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:91
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:101
uint32 GetNumPlayersInInstances()
Definition: MapManager.cpp:314
static bool ExistMapAndVMap(uint32 mapid, float x, float y)
Definition: MapManager.cpp:257
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:1010
uint32 x_coord
Definition: GridDefines.h:141
LocaleConstant GetSessionDbcLocale() const
Definition: WorldSession.h:233
DungeonDifficulty GetDifficulty()
Definition: Player.h:1873
#define sObjectMgr
Definition: ObjectMgr.h:1317
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:192
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:226
bool IsAlive() const
Definition: Unit.h:1336
void Update(uint32 diff)
INSTANTIATE_SINGLETON_2(MapManager, CLASS_LOCK)
bool IsDungeon() const
Definition: DBCStructure.h:550
Corpse * GetCorpse() const
Definition: Player.cpp:4321
void UnloadAll()
Definition: MapManager.cpp:273
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:680
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:253
uint32 GetNumInstances()
Definition: MapManager.cpp:297
bool Satisfy(AccessRequirement const *, uint32 target_map, bool report=false)
Definition: Player.cpp:16053
#define ASSERT
Definition: Errors.h:29
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:1947
#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
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:923
bool activated()
Definition: MapUpdater.cpp:118
char * name[16]
Definition: DBCStructure.h:518
static bool IsValidMAP(uint32 mapid)
Definition: MapManager.cpp:267
void InitMaxInstanceId()
Definition: MapManager.cpp:288
IntervalTimer i_timer
Definition: MapManager.h:168
Definition: Group.h:154
GridCoord ComputeGridCoord(float x, float y)
Definition: GridDefines.h:162