Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
MapInstanced.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 "Battleground.h"
7#include "Group.h"
8#include "InstanceSaveMgr.h"
9#include "MapInstanced.h"
10#include "MapManager.h"
11#include "MMapFactory.h"
12#include "ObjectMgr.h"
13#include "Player.h"
14#include "TransportMgr.h"
15#include "VMapFactory.h"
16#include "World.h"
17
18MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DIFFICULTY_NORMAL)
19{
20 // fill with zero
22}
23
25{
26 if (m_InstancedMaps.empty())
27 return;
28 //initialize visibility distances for all instance copies
29 for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
30 {
31 (*i).second->InitVisibilityDistance();
32 }
33}
34
36{
37 // take care of loaded GridMaps (when unused, unload it!)
38 Map::Update(t);
39
40 // update the instanced maps
41 InstancedMaps::iterator i = m_InstancedMaps.begin();
42
43 while (i != m_InstancedMaps.end())
44 {
45 if (i->second->CanUnload(t))
46 {
47 if (!DestroyInstance(i)) // iterator incremented
48 {
49 //m_unloadTimer
50 }
51 }
52 else
53 {
54 // update only here, because it may schedule some bad things before delete
55 if (sMapMgr->GetMapUpdater()->activated())
56 sMapMgr->GetMapUpdater()->schedule_update(*i->second, t);
57 else
58 i->second->Update(t);
59 ++i;
60 }
61 }
62}
63
65{
66 for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
67 i->second->DelayedUpdate(diff);
68
69 Map::DelayedUpdate(diff); // this may be removed
70}
71
72/*
73void MapInstanced::RelocationNotify()
74{
75 for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
76 i->second->RelocationNotify();
77}
78*/
79
81{
82 // Unload instanced maps
83 for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
84 i->second->UnloadAll();
85
86 // Delete the maps only after everything is unloaded to prevent crashes
87 for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
88 delete i->second;
89
90 m_InstancedMaps.clear();
91
92 // Unload own grids (just dummy(placeholder) grids, neccesary to unload GridMaps!)
94}
95
96/*
97- return the right instance for the object, based on its InstanceId
98- create the instance if it's not created already
99- the player is not actually added to the instance (only in InstanceMap::Add)
100*/
102{
103 if (GetId() != mapId || !player)
104 return NULL;
105
106 Map* map = NULL;
107 uint32 newInstanceId = 0; // instanceId of the resulting map
108
110 {
111 // instantiate or find existing bg map for player
112 // the instance id is set in battlegroundid
113 newInstanceId = player->GetBattlegroundId();
114 if (!newInstanceId)
115 return NULL;
116
117 map = sMapMgr->FindMap(mapId, newInstanceId);
118 if (!map)
119 {
120 if (Battleground* bg = player->GetBattleground())
121 map = CreateBattleground(newInstanceId, bg);
122 else
123 {
124 player->TeleportToBGEntryPoint();
125 return NULL;
126 }
127 }
128 }
129 else
130 {
131 InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficulty(GetEntry()));
132 InstanceSave* pSave = pBind ? pBind->save : NULL;
133
134 // the player's permanent player bind is taken into consideration first
135 // then the player's group bind and finally the solo bind.
136 if (!pBind || !pBind->perm)
137 {
138 InstanceGroupBind* groupBind = NULL;
139 Group* group = player->GetGroup();
140 // use the player's difficulty setting (it may not be the same as the group's)
141 if (group)
142 {
143 groupBind = group->GetBoundInstance(this);
144 if (groupBind)
145 {
146 // solo saves should be reset when entering a group's instance
147 player->UnbindInstance(GetId(), player->GetDifficulty(GetEntry()));
148 pSave = groupBind->save;
149 }
150 }
151 }
152 if (pSave)
153 {
154 // solo/perm/group
155 newInstanceId = pSave->GetInstanceId();
156 map = FindInstanceMap(newInstanceId);
157 // it is possible that the save exists but the map doesn't
158 if (!map)
159 map = CreateInstance(newInstanceId, pSave, pSave->GetDifficulty());
160 }
161 else
162 {
163 // if no instanceId via group members or instance saves is found
164 // the instance will be created for the first time
165 newInstanceId = sMapMgr->GenerateInstanceId();
166
167 DifficultyID diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(GetEntry()) : player->GetDifficulty(GetEntry());
168 //Seems it is now possible, but I do not know if it should be allowed
169 //ASSERT(!FindInstanceMap(NewInstanceId));
170 map = FindInstanceMap(newInstanceId);
171 if (!map)
172 map = CreateInstance(newInstanceId, NULL, diff);
173 }
174 }
175
176 return map;
177}
178
180{
181 // load/create a map
182 std::lock_guard<std::mutex> guard(Lock);
183
184 // make sure we have a valid map id
185 const MapEntry* entry = sMapStore.LookupEntry(GetId());
186 if (!entry)
187 {
188 SF_LOG_ERROR("maps", "CreateInstance: no entry for map %d", GetId());
189 ASSERT(false);
190 }
191 const InstanceTemplate* iTemplate = sObjectMgr->GetInstanceTemplate(GetId());
192 if (!iTemplate)
193 {
194 SF_LOG_ERROR("maps", "CreateInstance: no instance template for map %d", GetId());
195 ASSERT(false);
196 }
197
198 // some instances only have one difficulty
200
201 SF_LOG_DEBUG("maps", "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save ? "" : "new ", InstanceId, GetId(), difficulty ? "heroic" : "normal");
202
203 InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this);
204 ASSERT(map->IsInstance());
205
206 map->LoadRespawnTimes();
207
208 bool load_data = save != NULL;
209 map->CreateInstanceData(load_data);
210
211 m_InstancedMaps[InstanceId] = map;
212 sTransportMgr->SpawnLocalTransports(map);
213 return map;
214}
215
217{
218 // load/create a map
219 std::lock_guard<std::mutex> guard(Lock);
220
221 SF_LOG_DEBUG("maps", "MapInstanced::CreateBattleground: map bg %d for %d created.", InstanceId, GetId());
222
223 PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), bg->GetMinLevel());
224
225 uint8 spawnMode;
226
227 if (bracketEntry)
228 spawnMode = bracketEntry->difficulty;
229 else
230 spawnMode = 0;
231
232 BattlegroundMap* map = new BattlegroundMap(GetId(), GetGridExpiry(), InstanceId, this, spawnMode);
234 map->SetBG(bg);
235 bg->SetBgMap(map);
236
237 m_InstancedMaps[InstanceId] = map;
238 sTransportMgr->SpawnLocalTransports(map);
239 return map;
240}
241
242// increments the iterator after erase
243bool MapInstanced::DestroyInstance(InstancedMaps::iterator& itr)
244{
245 itr->second->RemoveAllPlayers();
246 if (itr->second->HavePlayers())
247 {
248 ++itr;
249 return false;
250 }
251
252 itr->second->UnloadAll();
253 // should only unload VMaps if this is the last instance and grid unloading is enabled
254 if (m_InstancedMaps.size() <= 1 && sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_GRID_UNLOAD))
255 {
258 // in that case, unload grids of the base map, too
259 // so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded
261 }
262
263 // Free up the instance id and allow it to be reused for bgs and arenas (other instances are handled in the InstanceSaveMgr)
264 if (itr->second->IsBattlegroundOrArena())
265 sMapMgr->FreeInstanceId(itr->second->GetInstanceId());
266
267 // erase map
268 delete itr->second;
269 m_InstancedMaps.erase(itr++);
270
271 return true;
272}
273
275{
276 //ASSERT(false);
277 return true;
278}
DifficultyID
Definition DBCEnums.h:330
@ DIFFICULTY_NORMAL
Definition DBCEnums.h:332
PvPDifficultyEntry const * GetBattlegroundBracketByLevel(uint32 mapid, uint32 level)
MapDifficulty const * GetDownscaledMapDifficultyData(uint32 mapId, DifficultyID &difficulty)
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint16_t uint16
Definition Define.h:78
#define ASSERT
Definition Errors.h:29
#define MAX_NUMBER_OF_GRIDS
Definition GridDefines.h:24
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define sMapMgr
Definition MapManager.h:145
#define sObjectMgr
Definition ObjectMgr.h:1617
#define sTransportMgr
uint32 GetMapId() const
uint32 GetMinLevel() const
void SetBgMap(BattlegroundMap *map)
void SetBG(Battleground *bg)
Definition Map.h:680
void RemoveAllPlayers() OVERRIDE
Definition Map.cpp:3170
Definition Group.h:147
DifficultyID GetDifficulty(MapEntry const *mapEntry) const
Definition Group.cpp:2710
InstanceGroupBind * GetBoundInstance(Player *player)
Definition Group.cpp:2393
void CreateInstanceData(bool load)
Definition Map.cpp:2893
DifficultyID GetDifficulty() const
uint32 GetInstanceId() const
static MMapManager * createOrGetMMapManager()
bool unloadMap(uint32 mapId, int32 x, int32 y)
bool IsBattlegroundOrArena() const
Definition Map.h:378
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map *_parent=NULL)
Definition Map.cpp:222
std::mutex Lock
Definition Map.h:538
virtual void Update(const uint32)
Definition Map.cpp:631
virtual void UnloadAll()
Definition Map.cpp:1381
virtual void DelayedUpdate(const uint32 diff)
Definition Map.cpp:2391
void LoadRespawnTimes()
Definition Map.cpp:3272
MapEntry const * GetEntry() const
Definition Map.h:244
time_t GetGridExpiry(void) const
Definition Map.h:299
uint32 GetId(void) const
Definition Map.h:300
bool IsInstance() const
Definition Map.h:368
InstanceMap * CreateInstance(uint32 InstanceId, InstanceSave *save, DifficultyID difficulty)
InstancedMaps m_InstancedMaps
void DelayedUpdate(const uint32 diff) OVERRIDE
void Update(const uint32) OVERRIDE
Map * FindInstanceMap(uint32 instanceId) const
uint16 GridMapReference[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]
bool CanEnter(Player *player) OVERRIDE
MapInstanced(uint32 id, time_t expiry)
Map * CreateInstanceForPlayer(const uint32 mapId, Player *player)
bool DestroyInstance(InstancedMaps::iterator &itr)
void UnloadAll() OVERRIDE
BattlegroundMap * CreateBattleground(uint32 InstanceId, Battleground *bg)
virtual void InitVisibilityDistance() OVERRIDE
void UnbindInstance(uint32 mapid, DifficultyID difficulty, bool unload=false)
Definition Player.cpp:13904
InstancePlayerBind * GetBoundInstance(uint32 mapid, DifficultyID difficulty)
Definition Player.cpp:13877
DifficultyID GetDifficulty(MapEntry const *mapEntry) const
Definition Player.cpp:20762
bool TeleportToBGEntryPoint()
Definition Player.cpp:2341
Battleground * GetBattleground() const
Definition Player.cpp:19212
Group * GetGroup()
Definition Player.h:2972
uint32 GetBattlegroundId() const
Definition Player.h:2697
virtual void unloadMap(unsigned int pMapId, int x, int y)=0
static IVMapManager * createOrGetVMapManager()
#define sWorld
Definition World.h:910
@ CONFIG_GRID_UNLOAD
Definition World.h:94
InstanceSave * save
Definition Group.h:137
InstanceSave * save
Definition Player.h:931
uint32 difficulty