TrinityCore
Loading...
Searching...
No Matches
InstanceSaveMgr.h
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#ifndef _INSTANCESAVEMGR_H
19#define _INSTANCESAVEMGR_H
20
21#include <list>
22#include <map>
23#include <mutex>
24#include <unordered_map>
25
26#include "Define.h"
27#include "DatabaseEnvFwd.h"
28#include "DBCEnums.h"
29#include "ObjectDefines.h"
30
31struct InstanceTemplate;
32struct MapEntry;
33class Player;
34class Group;
35
36/*
37 Holds the information necessary for creating a new map for an existing instance
38 Is referenced in three cases:
39 - player-instance binds for solo players (not in group)
40 - player-instance binds for permanent heroic/raid saves
41 - group-instance binds (both solo and permanent) cache the player binds for the group leader
42*/
44{
45 friend class InstanceSaveManager;
46 public:
47 /* Created either when:
48 - any new instance is being generated
49 - the first time a player bound to InstanceId logs in
50 - when a group bound to the instance is loaded */
51 InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset);
52
53 /* Unloaded when m_playerList and m_groupList become empty
54 or when the instance is reset */
56
57 uint8 GetPlayerCount() const { return m_playerList.size(); }
58 uint8 GetGroupCount() const { return m_groupList.size(); }
59
60 /* A map corresponding to the InstanceId/MapId does not always exist.
61 InstanceSave objects may be created on player logon but the maps are
62 created and loaded only when a player actually enters the instance. */
63 uint32 GetInstanceId() const { return m_instanceid; }
64 uint32 GetMapId() const { return m_mapid; }
65
66 /* Saved when the instance is generated for the first time */
67 void SaveToDB();
68 /* When the instance is being reset (permanently deleted) */
69 void DeleteFromDB();
70
71 /* for normal instances this corresponds to max(creature respawn time) + X hours
72 for raid/heroic instances this caches the global respawn time for the map */
73 time_t GetResetTime() const { return m_resetTime; }
74 void SetResetTime(time_t resetTime) { m_resetTime = resetTime; }
75 time_t GetResetTimeForDB();
76
77 InstanceTemplate const* GetTemplate();
78 MapEntry const* GetMapEntry();
79
80 /* online players bound to the instance (perm/solo)
81 does not include the members of the group unless they have permanent saves */
82 void AddPlayer(Player* player)
83 {
84 std::lock_guard<std::mutex> lock(_playerListLock);
85 m_playerList.push_back(player);
86 }
87
88 bool RemovePlayer(Player* player)
89 {
90 _playerListLock.lock();
91 m_playerList.remove(player);
92 bool isStillValid = UnloadIfEmpty();
93 _playerListLock.unlock();
94
95 //delete here if needed, after releasing the lock
96 if (m_toDelete)
97 delete this;
98
99 return isStillValid;
100 }
101 /* all groups bound to the instance */
102 void AddGroup(Group* group) { m_groupList.push_back(group); }
103 bool RemoveGroup(Group* group)
104 {
105 m_groupList.remove(group);
106 bool isStillValid = UnloadIfEmpty();
107 if (m_toDelete)
108 delete this;
109 return isStillValid;
110 }
111
112 /* instances cannot be reset (except at the global reset time)
113 if there are players permanently bound to it
114 this is cached for the case when those players are offline */
115 bool CanReset() const { return m_canReset; }
116 void SetCanReset(bool canReset) { m_canReset = canReset; }
117
118 /* currently it is possible to omit this information from this structure
119 but that would depend on a lot of things that can easily change in future */
120 Difficulty GetDifficulty() const { return m_difficulty; }
121
122 typedef std::list<Player*> PlayerListType;
123 typedef std::list<Group*> GroupListType;
124 private:
125 bool UnloadIfEmpty();
126 /* used to flag the InstanceSave as to be deleted, so the caller can delete it */
127 void SetToDelete(bool toDelete)
128 {
129 m_toDelete = toDelete;
130 }
131
132 /* the only reason the instSave-object links are kept is because
133 the object-instSave links need to be broken at reset time */
143
144 std::mutex _playerListLock;
145};
146
147typedef std::unordered_map<uint32 /*PAIR32(map, difficulty)*/, time_t /*resetTime*/> ResetTimeByMapDifficultyMap;
148
150{
151 friend class InstanceSave;
152
153 private:
154 InstanceSaveManager() : lock_instLists(false) { };
156
157 public:
158 typedef std::unordered_map<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveHashMap;
159
160 static InstanceSaveManager* instance();
161
162 void Unload();
163
164 /* resetTime is a global propery of each (raid/heroic) map
165 all instances of that map reset at the same time */
167 {
172
173 InstResetEvent() : type(0), difficulty(DUNGEON_DIFFICULTY_NORMAL), mapid(0), instanceId(0) { }
174 InstResetEvent(uint8 t, uint32 _mapid, Difficulty d, uint16 _instanceid)
175 : type(t), difficulty(d), mapid(_mapid), instanceId(_instanceid) { }
176 bool operator==(InstResetEvent const& e) const { return e.instanceId == instanceId; }
177 };
178 typedef std::multimap<time_t /*resetTime*/, InstResetEvent> ResetTimeQueue;
179
180 void LoadInstances();
181
182 void LoadResetTimes();
183 time_t GetResetTimeFor(uint32 mapid, Difficulty d) const
184 {
185 ResetTimeByMapDifficultyMap::const_iterator itr = m_resetTimeByMapDifficulty.find(MAKE_PAIR32(mapid, d));
186 return itr != m_resetTimeByMapDifficulty.end() ? itr->second : 0;
187 }
188 time_t GetSubsequentResetTime(uint32 mapid, Difficulty difficulty, time_t resetTime) const;
189
190 // Use this on startup when initializing reset times
191 void InitializeResetTimeFor(uint32 mapid, Difficulty d, time_t t)
192 {
193 m_resetTimeByMapDifficulty[MAKE_PAIR32(mapid, d)] = t;
194 }
195
196 // Use this only when updating existing reset times
197 void SetResetTimeFor(uint32 mapid, Difficulty d, time_t t);
198
200 {
201 return m_resetTimeByMapDifficulty;
202 }
203 void ScheduleReset(bool add, time_t time, InstResetEvent event);
204 void ForceGlobalReset(uint32 mapId, Difficulty difficulty);
205
206 void Update();
207
208 InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime,
209 bool canReset, bool load = false);
210 void RemoveInstanceSave(uint32 InstanceId);
211 void UnloadInstanceSave(uint32 InstanceId);
212 static void DeleteInstanceFromDB(uint32 instanceid);
213
214 InstanceSave* GetInstanceSave(uint32 InstanceId);
215
216 /* statistics */
217 uint32 GetNumInstanceSaves() const { return uint32(m_instanceSaveById.size()); }
218 uint32 GetNumBoundPlayersTotal() const;
219 uint32 GetNumBoundGroupsTotal() const;
220
221 protected:
222 static uint16 ResetTimeDelay[];
223
224 private:
225 void _ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, time_t resetTime);
226 void _ResetInstance(uint32 mapid, uint32 instanceId);
227 void _ResetSave(InstanceSaveHashMap::iterator &itr);
228 // used during global instance resets
230 // fast lookup by instance id
232 // fast lookup for reset times (always use existed functions for access/set)
235};
236
237#define sInstanceSaveMgr InstanceSaveManager::instance()
238#endif
Difficulty
Definition DBCEnums.h:279
@ DUNGEON_DIFFICULTY_NORMAL
Definition DBCEnums.h:282
#define TC_GAME_API
Definition Define.h:114
uint8_t uint8
Definition Define.h:135
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
std::unordered_map< uint32, time_t > ResetTimeByMapDifficultyMap
uint32 MAKE_PAIR32(uint16 l, uint16 h)
static void SaveToDB(QuestPool const &pool, CharacterDatabaseTransaction trans)
Definition Group.h:165
std::multimap< time_t, InstResetEvent > ResetTimeQueue
std::unordered_map< uint32, InstanceSave * > InstanceSaveHashMap
InstanceSaveHashMap m_instanceSaveById
ResetTimeByMapDifficultyMap const & GetResetTimeMap() const
ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty
uint32 GetNumInstanceSaves() const
time_t GetResetTimeFor(uint32 mapid, Difficulty d) const
void InitializeResetTimeFor(uint32 mapid, Difficulty d, time_t t)
ResetTimeQueue m_resetTimeQueue
void AddPlayer(Player *player)
bool RemovePlayer(Player *player)
uint8 GetPlayerCount() const
bool RemoveGroup(Group *group)
uint8 GetGroupCount() const
void SetCanReset(bool canReset)
void SetResetTime(time_t resetTime)
uint32 GetInstanceId() const
std::list< Group * > GroupListType
uint32 GetMapId() const
Difficulty GetDifficulty() const
Difficulty m_difficulty
void AddGroup(Group *group)
bool CanReset() const
PlayerListType m_playerList
std::list< Player * > PlayerListType
GroupListType m_groupList
time_t GetResetTime() const
void SetToDelete(bool toDelete)
std::mutex _playerListLock
bool operator==(InstResetEvent const &e) const
InstResetEvent(uint8 t, uint32 _mapid, Difficulty d, uint16 _instanceid)