1 | /* |
---|
2 | /* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> |
---|
3 | * |
---|
4 | * Thanks to the original authors: ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> |
---|
5 | * |
---|
6 | * |
---|
7 | * This program is free software; you can redistribute it and/or modify |
---|
8 | * it under the terms of the GNU General Public License as published by |
---|
9 | * the Free Software Foundation; either version 2 of the License, or |
---|
10 | * (at your option) any later version. |
---|
11 | * |
---|
12 | * This program is distributed in the hope that it will be useful, |
---|
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | * GNU General Public License for more details. |
---|
16 | * |
---|
17 | * You should have received a copy of the GNU General Public License |
---|
18 | * along with this program; if not, write to the Free Software |
---|
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
20 | */ |
---|
21 | |
---|
22 | #ifndef __InstanceSaveMgr_H |
---|
23 | #define __InstanceSaveMgr_H |
---|
24 | |
---|
25 | #include "Platform/Define.h" |
---|
26 | #include "Policies/Singleton.h" |
---|
27 | #include "zthread/Mutex.h" |
---|
28 | #include <list> |
---|
29 | #include <map> |
---|
30 | #include "Utilities/HashMap.h" |
---|
31 | #include "Database/DatabaseEnv.h" |
---|
32 | |
---|
33 | struct InstanceTemplate; |
---|
34 | struct MapEntry; |
---|
35 | class Player; |
---|
36 | class Group; |
---|
37 | |
---|
38 | /* |
---|
39 | Holds the information necessary for creating a new map for an existing instance |
---|
40 | Is referenced in three cases: |
---|
41 | - player-instance binds for solo players (not in group) |
---|
42 | - player-instance binds for permanent heroic/raid saves |
---|
43 | - group-instance binds (both solo and permanent) cache the player binds for the group leader |
---|
44 | */ |
---|
45 | class InstanceSave |
---|
46 | { |
---|
47 | friend class InstanceSaveManager; |
---|
48 | public: |
---|
49 | /* Created either when: |
---|
50 | - any new instance is being generated |
---|
51 | - the first time a player bound to InstanceId logs in |
---|
52 | - when a group bound to the instance is loaded */ |
---|
53 | InstanceSave(uint16 MapId, uint32 InstanceId, uint8 difficulty, time_t resetTime, bool canReset); |
---|
54 | |
---|
55 | /* Unloaded when m_playerList and m_groupList become empty |
---|
56 | or when the instance is reset */ |
---|
57 | ~InstanceSave(); |
---|
58 | |
---|
59 | uint8 GetPlayerCount() { return m_playerList.size(); } |
---|
60 | uint8 GetGroupCount() { return m_groupList.size(); } |
---|
61 | |
---|
62 | /* A map corresponding to the InstanceId/MapId does not always exist. |
---|
63 | InstanceSave objects may be created on player logon but the maps are |
---|
64 | created and loaded only when a player actually enters the instance. */ |
---|
65 | uint32 GetInstanceId() { return m_instanceid; } |
---|
66 | uint32 GetMapId() { return m_mapid; } |
---|
67 | |
---|
68 | /* Saved when the instance is generated for the first time */ |
---|
69 | void SaveToDB(); |
---|
70 | /* When the instance is being reset (permanently deleted) */ |
---|
71 | void DeleteFromDB(); |
---|
72 | |
---|
73 | /* for normal instances this corresponds to max(creature respawn time) + X hours |
---|
74 | for raid/heroic instances this caches the global respawn time for the map */ |
---|
75 | time_t GetResetTime() { return m_resetTime; } |
---|
76 | void SetResetTime(time_t resetTime) { m_resetTime = resetTime; } |
---|
77 | time_t GetResetTimeForDB(); |
---|
78 | |
---|
79 | InstanceTemplate const* GetTemplate(); |
---|
80 | MapEntry const* GetMapEntry(); |
---|
81 | |
---|
82 | /* online players bound to the instance (perm/solo) |
---|
83 | does not include the members of the group unless they have permanent saves */ |
---|
84 | void AddPlayer(Player *player) { m_playerList.push_back(player); } |
---|
85 | bool RemovePlayer(Player *player) { m_playerList.remove(player); return UnloadIfEmpty(); } |
---|
86 | /* all groups bound to the instance */ |
---|
87 | void AddGroup(Group *group) { m_groupList.push_back(group); } |
---|
88 | bool RemoveGroup(Group *group) { m_groupList.remove(group); return UnloadIfEmpty(); } |
---|
89 | |
---|
90 | /* instances cannot be reset (except at the global reset time) |
---|
91 | if there are players permanently bound to it |
---|
92 | this is cached for the case when those players are offline */ |
---|
93 | bool CanReset() { return m_canReset; } |
---|
94 | void SetCanReset(bool canReset) { m_canReset = canReset; } |
---|
95 | |
---|
96 | /* currently it is possible to omit this information from this structure |
---|
97 | but that would depend on a lot of things that can easily change in future */ |
---|
98 | uint8 GetDifficulty() { return m_difficulty; } |
---|
99 | |
---|
100 | typedef std::list<Player*> PlayerListType; |
---|
101 | typedef std::list<Group*> GroupListType; |
---|
102 | private: |
---|
103 | bool UnloadIfEmpty(); |
---|
104 | /* the only reason the instSave-object links are kept is because |
---|
105 | the object-instSave links need to be broken at reset time |
---|
106 | TODO: maybe it's enough to just store the number of players/groups */ |
---|
107 | PlayerListType m_playerList; |
---|
108 | GroupListType m_groupList; |
---|
109 | time_t m_resetTime; |
---|
110 | uint32 m_instanceid; |
---|
111 | uint16 m_mapid; |
---|
112 | uint8 m_difficulty; |
---|
113 | bool m_canReset; |
---|
114 | }; |
---|
115 | |
---|
116 | class TRINITY_DLL_DECL InstanceSaveManager : public Trinity::Singleton<InstanceSaveManager, Trinity::ClassLevelLockable<InstanceSaveManager, ZThread::Mutex> > |
---|
117 | { |
---|
118 | friend class InstanceSave; |
---|
119 | public: |
---|
120 | InstanceSaveManager(); |
---|
121 | ~InstanceSaveManager(); |
---|
122 | |
---|
123 | typedef std::map<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveMap; |
---|
124 | typedef HM_NAMESPACE::hash_map<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveHashMap; |
---|
125 | typedef std::map<uint32 /*mapId*/, InstanceSaveMap> InstanceSaveMapMap; |
---|
126 | |
---|
127 | /* resetTime is a global propery of each (raid/heroic) map |
---|
128 | all instances of that map reset at the same time */ |
---|
129 | struct InstResetEvent |
---|
130 | { |
---|
131 | uint8 type; |
---|
132 | uint16 mapid; |
---|
133 | uint16 instanceId; |
---|
134 | InstResetEvent(uint8 t = 0, uint16 m = 0, uint16 i = 0) : type(t), mapid(m), instanceId(i) {} |
---|
135 | bool operator == (const InstResetEvent& e) { return e.instanceId == instanceId; } |
---|
136 | }; |
---|
137 | typedef std::multimap<time_t /*resetTime*/, InstResetEvent> ResetTimeQueue; |
---|
138 | typedef std::vector<time_t /*resetTime*/> ResetTimeVector; |
---|
139 | |
---|
140 | void CleanupInstances(); |
---|
141 | void PackInstances(); |
---|
142 | |
---|
143 | void LoadResetTimes(); |
---|
144 | time_t GetResetTimeFor(uint32 mapid) { return m_resetTimeByMapId[mapid]; } |
---|
145 | void ScheduleReset(bool add, time_t time, InstResetEvent event); |
---|
146 | |
---|
147 | void Update(); |
---|
148 | |
---|
149 | InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, uint8 difficulty, time_t resetTime, bool canReset, bool load = false); |
---|
150 | void RemoveInstanceSave(uint32 InstanceId); |
---|
151 | static void DeleteInstanceFromDB(uint32 instanceid); |
---|
152 | |
---|
153 | InstanceSave *GetInstanceSave(uint32 InstanceId); |
---|
154 | |
---|
155 | /* statistics */ |
---|
156 | uint32 GetNumInstanceSaves() { return m_instanceSaveById.size(); } |
---|
157 | uint32 GetNumBoundPlayersTotal(); |
---|
158 | uint32 GetNumBoundGroupsTotal(); |
---|
159 | |
---|
160 | private: |
---|
161 | void _ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeleft); |
---|
162 | void _ResetInstance(uint32 mapid, uint32 instanceId); |
---|
163 | void _ResetSave(InstanceSaveHashMap::iterator &itr); |
---|
164 | void _DelHelper(DatabaseType &db, const char *fields, const char *table, const char *queryTail,...); |
---|
165 | // used during global instance resets |
---|
166 | bool lock_instLists; |
---|
167 | // fast lookup by instance id |
---|
168 | InstanceSaveHashMap m_instanceSaveById; |
---|
169 | // fast lookup for reset times |
---|
170 | ResetTimeVector m_resetTimeByMapId; |
---|
171 | ResetTimeQueue m_resetTimeQueue; |
---|
172 | }; |
---|
173 | |
---|
174 | #define sInstanceSaveManager Trinity::Singleton<InstanceSaveManager>::Instance() |
---|
175 | #endif |
---|