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