TrinityCore
Loading...
Searching...
No Matches
MapInstanced.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore 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 "MapInstanced.h"
19#include "Battleground.h"
20#include "DBCStores.h"
21#include "Group.h"
22#include "InstanceSaveMgr.h"
23#include "Log.h"
24#include "MapManager.h"
25#include "MMapFactory.h"
26#include "ObjectMgr.h"
27#include "Player.h"
28#include "ScriptMgr.h"
29#include "VMapFactory.h"
30#include "VMapManager2.h"
31#include "World.h"
32
34{
35 // fill with zero
37}
38
40{
41 if (m_InstancedMaps.empty())
42 return;
43 //initialize visibility distances for all instance copies
44 for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
45 {
46 (*i).second->InitVisibilityDistance();
47 }
48}
49
51{
52 // take care of loaded GridMaps (when unused, unload it!)
53 Map::Update(t);
54
55 // update the instanced maps
56 InstancedMaps::iterator i = m_InstancedMaps.begin();
57
58 while (i != m_InstancedMaps.end())
59 {
60 if (i->second->CanUnload(t))
61 {
62 if (!DestroyInstance(i)) // iterator incremented
63 {
64 //m_unloadTimer
65 }
66 }
67 else
68 {
69 // update only here, because it may schedule some bad things before delete
70 if (sMapMgr->GetMapUpdater()->activated())
71 sMapMgr->GetMapUpdater()->schedule_update(*i->second, t);
72 else
73 i->second->Update(t);
74 ++i;
75 }
76 }
77}
78
80{
81 for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
82 i->second->DelayedUpdate(diff);
83
84 Map::DelayedUpdate(diff); // this may be removed
85}
86
87/*
88void MapInstanced::RelocationNotify()
89{
90 for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
91 i->second->RelocationNotify();
92}
93*/
94
96{
97 // Unload instanced maps
98 for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
99 {
100 i->second->UnloadAll();
101
102 sScriptMgr->OnDestroyMap(i->second.get());
103 }
104
105 m_InstancedMaps.clear();
106
107 // Unload own grids (just dummy(placeholder) grids, neccesary to unload GridMaps!)
109}
110
111/*
112- return the right instance for the object, based on its InstanceId
113- create the instance if it's not created already
114- the player is not actually added to the instance (only in InstanceMap::Add)
115*/
116Map* MapInstanced::CreateInstanceForPlayer(uint32 mapId, Player* player, uint32 loginInstanceId /*= 0*/)
117{
118 if (GetId() != mapId || !player)
119 return nullptr;
120
121 Map* map = nullptr;
122 uint32 newInstanceId = 0; // instanceId of the resulting map
123
125 {
126 // instantiate or find existing bg map for player
127 // the instance id is set in battlegroundid
128 newInstanceId = player->GetBattlegroundId();
129 if (!newInstanceId)
130 return nullptr;
131
132 map = sMapMgr->FindMap(mapId, newInstanceId);
133 if (!map)
134 {
135 if (Battleground* bg = player->GetBattleground())
136 map = CreateBattleground(newInstanceId, bg);
137 else
138 {
139 player->TeleportToBGEntryPoint();
140 return nullptr;
141 }
142 }
143 }
144 else
145 {
146 InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficulty(IsRaid()));
147 InstanceSave* pSave = pBind ? pBind->save : nullptr;
148
149 // priority:
150 // 1. player's permanent bind
151 // 2. player's current instance id if this is at login
152 // 3. group's current bind
153 // 4. player's current bind
154 if (!pBind || !pBind->perm)
155 {
156 if (loginInstanceId) // if the player has a saved instance id on login, we either use this instance or relocate him out (return null)
157 {
158 map = FindInstanceMap(loginInstanceId);
159 if (!map && pSave && pSave->GetInstanceId() == loginInstanceId)
160 map = CreateInstance(loginInstanceId, pSave, pSave->GetDifficulty(), player->GetTeamId());
161 return map;
162 }
163
164 InstanceGroupBind* groupBind = nullptr;
165 Group* group = player->GetGroup();
166 // use the player's difficulty setting (it may not be the same as the group's)
167 if (group)
168 {
169 groupBind = group->GetBoundInstance(this);
170 if (groupBind)
171 {
172 // solo saves should be reset when entering a group's instance
173 player->UnbindInstance(GetId(), player->GetDifficulty(IsRaid()));
174 pSave = groupBind->save;
175 }
176 }
177 }
178 if (pSave)
179 {
180 // solo/perm/group
181 newInstanceId = pSave->GetInstanceId();
182 map = FindInstanceMap(newInstanceId);
183 // it is possible that the save exists but the map doesn't
184 if (!map)
185 map = CreateInstance(newInstanceId, pSave, pSave->GetDifficulty(), player->GetTeamId());
186 }
187 else
188 {
189 // if no instanceId via group members or instance saves is found
190 // the instance will be created for the first time
191 newInstanceId = sMapMgr->GenerateInstanceId();
192
193 Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid());
194 //Seems it is now possible, but I do not know if it should be allowed
195 //ASSERT(!FindInstanceMap(NewInstanceId));
196 map = FindInstanceMap(newInstanceId);
197 if (!map)
198 map = CreateInstance(newInstanceId, nullptr, diff, player->GetTeamId());
199 }
200 }
201
202 return map;
203}
204
206{
207 // load/create a map
208 std::lock_guard<std::mutex> lock(_mapLock);
209
210 // make sure we have a valid map id
211 MapEntry const* entry = sMapStore.LookupEntry(GetId());
212 if (!entry)
213 {
214 TC_LOG_ERROR("maps", "CreateInstance: no entry for map {}", GetId());
215 ABORT();
216 }
217 InstanceTemplate const* iTemplate = sObjectMgr->GetInstanceTemplate(GetId());
218 if (!iTemplate)
219 {
220 TC_LOG_ERROR("maps", "CreateInstance: no instance template for map {}", GetId());
221 ABORT();
222 }
223
224 // some instances only have one difficulty
226
227 TC_LOG_DEBUG("maps", "MapInstanced::CreateInstance: {} map instance {} for {} created with difficulty {}", save ? "" : "new ", InstanceId, GetId(), static_cast<uint32>(difficulty));
228
229 InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this, InstanceTeam);
230 ASSERT(map->IsDungeon());
231
232 map->LoadRespawnTimes();
233 map->LoadCorpseData();
234
235 bool load_data = save != nullptr;
236 map->CreateInstanceData(load_data);
237
238 if (sWorld->getBoolConfig(CONFIG_INSTANCEMAP_LOAD_GRIDS))
239 map->LoadAllCells();
240
242 ptr.reset(map);
243 map->SetWeakPtr(ptr);
244
245 sScriptMgr->OnCreateMap(map);
246 return map;
247}
248
250{
251 // load/create a map
252 std::lock_guard<std::mutex> lock(_mapLock);
253
254 TC_LOG_DEBUG("maps", "MapInstanced::CreateBattleground: map bg {} for {} created.", InstanceId, GetId());
255
256 PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), bg->GetMinLevel());
257
258 uint8 spawnMode;
259
260 if (bracketEntry)
261 spawnMode = bracketEntry->Difficulty;
262 else
263 spawnMode = REGULAR_DIFFICULTY;
264
265 BattlegroundMap* map = new BattlegroundMap(GetId(), GetGridExpiry(), InstanceId, this, spawnMode);
267 map->SetBG(bg);
268 bg->SetBgMap(map);
269
271 ptr.reset(map);
272 map->SetWeakPtr(ptr);
273
274 sScriptMgr->OnCreateMap(map);
275 return map;
276}
277
278// increments the iterator after erase
279bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr)
280{
281 itr->second->RemoveAllPlayers();
282 if (itr->second->HavePlayers())
283 {
284 ++itr;
285 return false;
286 }
287
288 itr->second->UnloadAll();
289 // should only unload VMaps if this is the last instance and grid unloading is enabled
290 if (m_InstancedMaps.size() <= 1 && sWorld->getBoolConfig(CONFIG_GRID_UNLOAD))
291 {
294 // in that case, unload grids of the base map, too
295 // so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded
297 }
298
299 sScriptMgr->OnDestroyMap(itr->second.get());
300
301 // Free up the instance id and allow it to be reused for bgs and arenas (other instances are handled in the InstanceSaveMgr)
302 if (itr->second->IsBattlegroundOrArena())
303 sMapMgr->FreeInstanceId(itr->second->GetInstanceId());
304
305 // erase map
306 m_InstancedMaps.erase(itr++);
307
308 return true;
309}
310
312{
313 //ABORT();
314 return CAN_ENTER;
315}
Difficulty
Definition DBCEnums.h:279
@ DUNGEON_DIFFICULTY_NORMAL
Definition DBCEnums.h:282
@ REGULAR_DIFFICULTY
Definition DBCEnums.h:280
MapDifficulty const * GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty)
PvPDifficultyEntry const * GetBattlegroundBracketByLevel(uint32 mapid, uint32 level)
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
uint8_t uint8
Definition Define.h:135
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
#define ABORT
Definition Errors.h:74
#define ASSERT
Definition Errors.h:68
#define MAX_NUMBER_OF_GRIDS
Definition GridDefines.h:36
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define sMapMgr
Definition MapManager.h:211
#define sObjectMgr
Definition ObjectMgr.h:1721
#define sScriptMgr
Definition ScriptMgr.h:1168
TeamId
void RemoveAllPlayers() override
Definition Map.cpp:4378
void SetBG(Battleground *bg)
Definition Map.h:929
uint32 GetMapId() const
uint32 GetMinLevel() const
void SetBgMap(BattlegroundMap *map)
Definition Group.h:165
Difficulty GetDifficulty(bool isRaid) const
Definition Group.cpp:2611
InstanceGroupBind * GetBoundInstance(Player *player)
Definition Group.cpp:2286
void CreateInstanceData(bool load)
Definition Map.cpp:4031
uint32 GetInstanceId() const
Difficulty GetDifficulty() const
static MMapManager * createOrGetMMapManager()
bool unloadMap(uint32 mapId, int32 x, int32 y)
void DelayedUpdate(uint32 diff) override
virtual void InitVisibilityDistance() override
void Update(uint32 diff) override
Map * CreateInstanceForPlayer(uint32 mapId, Player *player, uint32 loginInstanceId=0)
InstancedMaps m_InstancedMaps
Map * FindInstanceMap(uint32 instanceId) const
EnterState CannotEnter(Player *) override
void UnloadAll() override
uint16 GridMapReference[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]
MapInstanced(uint32 id, time_t expiry)
InstanceMap * CreateInstance(uint32 InstanceId, InstanceSave *save, Difficulty difficulty, TeamId InstanceTeam)
bool DestroyInstance(InstancedMaps::iterator &itr)
BattlegroundMap * CreateBattleground(uint32 InstanceId, Battleground *bg)
Definition Map.h:281
bool IsDungeon() const
Definition Map.cpp:4236
bool IsBattlegroundOrArena() const
Definition Map.cpp:4277
void SetWeakPtr(Trinity::unique_weak_ptr< Map > weakRef)
Definition Map.h:391
virtual void DelayedUpdate(uint32 diff)
Definition Map.cpp:3523
bool IsRaid() const
Definition Map.cpp:4246
virtual void UnloadAll()
Definition Map.cpp:1745
void LoadRespawnTimes()
Definition Map.cpp:4504
void LoadCorpseData()
Definition Map.cpp:4558
virtual void Update(uint32)
Definition Map.cpp:762
uint32 GetId() const
Definition Map.cpp:4216
std::mutex _mapLock
Definition Map.h:671
time_t GetGridExpiry(void) const
Definition Map.h:348
EnterState
Definition Map.h:394
@ CAN_ENTER
Definition Map.h:395
void LoadAllCells()
Definition Map.cpp:249
Difficulty GetDifficulty(bool isRaid) const
Definition Player.h:1634
void UnbindInstance(uint32 mapid, Difficulty difficulty, bool unload=false)
Definition Player.cpp:18590
TeamId GetTeamId() const
Definition Player.h:1833
bool TeleportToBGEntryPoint()
Definition Player.cpp:1766
Battleground * GetBattleground() const
Definition Player.cpp:23049
Group * GetGroup()
Definition Player.h:2171
uint32 GetBattlegroundId() const
Definition Player.h:1984
InstancePlayerBind * GetBoundInstance(uint32 mapid, Difficulty difficulty, bool withExpired=false)
Definition Player.cpp:18564
Specialized variant of std::shared_ptr that enforces unique ownership and/or std::unique_ptr with std...
static VMapManager2 * createOrGetVMapManager()
void unloadMap(unsigned int mapId, int x, int y) override
#define sWorld
Definition World.h:900
@ CONFIG_INSTANCEMAP_LOAD_GRIDS
Definition World.h:168
@ CONFIG_GRID_UNLOAD
Definition World.h:94
InstanceSave * save
Definition Group.h:155
InstanceSave * save
Definition Player.h:782