TrinityCore
InstanceLockMgr.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 InstanceLockMgr_h__
19#define InstanceLockMgr_h__
20
21#include "Define.h"
22#include "DatabaseEnvFwd.h"
23#include "Duration.h"
24#include "Hash.h"
25#include "ObjectGuid.h"
26#include "Optional.h"
27#include <shared_mutex>
28#include <unordered_map>
29
30/*
31 * - Resetting instance difficulties with reset schedule from UI seems only possible either when its completed or in group (and only with LockID)
32 * - All difficulties of all maps with ResetInterval share locks - KEY is (MapID, LockID)
33 *
34 * DATABASE
35 * character_instance_lock
36 * `guid` bigint(20) unsigned NOT NULL,
37 * `mapId` int(10) unsigned NOT NULL,
38 * `lockId` int(10) unsigned NOT NULL,
39 * `instanceId` int(10) unsigned, REFERENCES instance for instanceId based locks
40 * `difficulty` tinyint(3) unsigned,
41 * `data` text, ALWAYS FILLED (also might not match instance data for instanceId based locks)
42 * `completedEncountersMask` int(10) unsigned, ALWAYS FILLED (also might not match instance data for instanceId based locks)
43 * `entranceWorldSafeLocId` int(10) unsigned, ALWAYS FILLED (also might not match instance data for instanceId based locks)
44 * `expiryTime` bigint(20) unsigned,
45 * `extended` tinyint(1) unsigned,
46 * PRIMARY KEY (`guid`,`mapId`,`lockId`),
47 *
48 * instance
49 * `instanceId` int(10) unsigned NOT NULL,
50 * `data` text, FILLED ONLY FOR ID BASED LOCKS
51 * `completedEncountersMask` int(10) unsigned, FILLED ONLY FOR ID BASED LOCKS
52 * `entranceWorldSafeLocId` int(10) unsigned, FILLED ONLY FOR ID BASED LOCKS
53 * PRIMARY KEY (`instanceId`)
54 */
55
57struct MapEntry;
59enum Difficulty : uint8;
61
62#define INSTANCE_ID_HIGH_MASK 0x1F440000
63#define INSTANCE_ID_LFG_MASK 0x00000001
64#define INSTANCE_ID_NORMAL_MASK 0x00010000
65
66using InstanceResetTimePoint = std::chrono::system_clock::time_point;
67
69{
72
77
78 std::string Data;
81};
82
84{
85public:
86 InstanceLock(uint32 mapId, Difficulty difficultyId, InstanceResetTimePoint expiryTime, uint32 instanceId);
87 virtual ~InstanceLock();
88
89 InstanceLock(InstanceLock const&) = delete;
93
94 uint32 GetMapId() const { return _mapId; }
95
96 Difficulty GetDifficultyId() const { return _difficultyId; }
97
98 uint32 GetInstanceId() const { return _instanceId; }
99 void SetInstanceId(uint32 instanceId) { _instanceId = instanceId; }
100
101 InstanceResetTimePoint GetExpiryTime() const { return _expiryTime; }
102 void SetExpiryTime(InstanceResetTimePoint expiryTime) { _expiryTime = expiryTime; }
103 bool IsExpired() const;
104
105 bool IsExtended() const { return _extended; }
106 void SetExtended(bool extended) { _extended = extended; }
107
108 InstanceLockData* GetData() { return &_data; }
109 InstanceLockData const* GetData() const { return &_data; }
110
111 virtual InstanceLockData const* GetInstanceInitializationData() const { return &_data; }
112
113 InstanceResetTimePoint GetEffectiveExpiryTime() const;
114
115 bool IsInUse() const { return _isInUse; }
116 void SetInUse(bool inUse) { _isInUse = inUse; }
117
118 bool IsNew() const { return _isNew; }
119 void SetIsNew(bool isNew) { _isNew = isNew; }
120
121private:
125 std::chrono::system_clock::time_point _expiryTime;
129 bool _isNew;
130};
131
133{
136
141
143};
144
146{
147public:
148 SharedInstanceLock(uint32 mapId, Difficulty difficultyId, InstanceResetTimePoint expiryTime, uint32 instanceId, std::shared_ptr<SharedInstanceLockData> sharedData);
149
150 InstanceLockData const* GetInstanceInitializationData() const override { return _sharedData.get(); }
151
152 SharedInstanceLockData* GetSharedData() { return _sharedData.get(); }
153 SharedInstanceLockData const* GetSharedData() const { return _sharedData.get(); }
154
155private:
161 std::shared_ptr<SharedInstanceLockData> _sharedData;
162};
163
164using InstanceLockKey = std::pair<uint32 /*MapDifficultyEntry::MapID*/, uint32 /*MapDifficultyEntry::LockID*/>;
165
167{
168 MapDb2Entries(uint32 mapId, Difficulty difficulty);
169 MapDb2Entries(MapEntry const* map, MapDifficultyEntry const* mapDifficulty);
170
171 InstanceLockKey GetKey() const;
172 bool IsInstanceIdBound() const;
173
174 MapEntry const* Map;
176};
177
179{
180 InstanceLockUpdateEvent(uint32 instanceId, std::string newData, uint32 instanceCompletedEncountersMask, DungeonEncounterEntry const* completedEncounter,
181 Optional<uint32> entranceWorldSafeLocId) :
182 InstanceId(instanceId), NewData(std::move(newData)), InstanceCompletedEncountersMask(instanceCompletedEncountersMask), CompletedEncounter(completedEncounter),
183 EntranceWorldSafeLocId(entranceWorldSafeLocId) { }
186
190
192 std::string NewData;
196};
197
199{
200 uint32 InstanceCount = 0; // Number of existing ID-based locks
201 uint32 PlayerCount = 0; // Number of players that have any lock
202};
203
205{
206public:
207 void Load();
208 void Unload();
209
217 TransferAbortReason CanJoinInstanceLock(ObjectGuid const& playerGuid, MapDb2Entries const& entries, InstanceLock const* instanceLock) const;
218
225 InstanceLock* FindActiveInstanceLock(ObjectGuid const& playerGuid, MapDb2Entries const& entries) const;
226
232 std::vector<InstanceLock const*> GetInstanceLocksForPlayer(ObjectGuid const& playerGuid) const;
233
241 InstanceLock* CreateInstanceLockForNewInstance(ObjectGuid const& playerGuid, MapDb2Entries const& entries, uint32 instanceId);
242
251 InstanceLock* UpdateInstanceLockForPlayer(CharacterDatabaseTransaction trans, ObjectGuid const& playerGuid, MapDb2Entries const& entries, InstanceLockUpdateEvent&& updateEvent);
252
258 void UpdateSharedInstanceLock(CharacterDatabaseTransaction trans, InstanceLockUpdateEvent&& updateEvent);
259
264 void OnSharedInstanceLockDataDelete(uint32 instanceId);
265
273 std::pair<InstanceResetTimePoint, InstanceResetTimePoint> UpdateInstanceLockExtensionForPlayer(ObjectGuid const& playerGuid, MapDb2Entries const& entries, bool extended);
274
283 void ResetInstanceLocksForPlayer(ObjectGuid const& playerGuid, Optional<uint32> mapId, Optional<Difficulty> difficulty,
284 std::vector<InstanceLock const*>* locksReset, std::vector<InstanceLock const*>* locksFailedToReset);
285
290 InstanceLocksStatistics GetStatistics() const;
291
292 static InstanceLockMgr& Instance();
293
294 static InstanceResetTimePoint GetNextResetTime(MapDb2Entries const& entries);
295
296private:
298 InstanceLockMgr(InstanceLockMgr const& right) = delete;
302
304
305 using PlayerLockMap = std::unordered_map<InstanceLockKey, std::unique_ptr<InstanceLock>>;
306 using LockMap = std::unordered_map<ObjectGuid, PlayerLockMap>;
307
308 static InstanceLock* FindInstanceLock(LockMap const& locks, ObjectGuid const& playerGuid, MapDb2Entries const& entries);
309 InstanceLock* FindActiveInstanceLock(ObjectGuid const& playerGuid, MapDb2Entries const& entries, bool ignoreTemporary, bool ignoreExpired) const;
310
311 mutable std::shared_mutex _locksMutex;
312 LockMap _temporaryInstanceLocksByPlayer; // locks stored here before any boss gets killed
314 std::unordered_map<uint32, std::weak_ptr<SharedInstanceLockData>> _instanceLockDataById;
315 bool _unloading = false;
316};
317
318#define sInstanceLockMgr InstanceLockMgr::Instance()
319
320#endif // InstanceLockMgr_h__
Difficulty
Definition: DBCEnums.h:873
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
#define TC_GAME_API
Definition: Define.h:123
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
std::chrono::system_clock::time_point InstanceResetTimePoint
std::pair< uint32, uint32 > InstanceLockKey
TransferAbortReason
Definition: Map.h:86
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
LockMap _temporaryInstanceLocksByPlayer
LockMap _instanceLocksByPlayer
InstanceLockMgr & operator=(InstanceLockMgr const &right)=delete
InstanceLockMgr & operator=(InstanceLockMgr &&right)=delete
std::unordered_map< uint32, std::weak_ptr< SharedInstanceLockData > > _instanceLockDataById
std::unordered_map< InstanceLockKey, std::unique_ptr< InstanceLock > > PlayerLockMap
std::unordered_map< ObjectGuid, PlayerLockMap > LockMap
InstanceLockMgr(InstanceLockMgr const &right)=delete
InstanceLockMgr(InstanceLockMgr &&right)=delete
std::shared_mutex _locksMutex
void SetInstanceId(uint32 instanceId)
virtual InstanceLockData const * GetInstanceInitializationData() const
virtual ~InstanceLock()
std::chrono::system_clock::time_point _expiryTime
bool IsExtended() const
void SetExtended(bool extended)
Difficulty _difficultyId
void SetInUse(bool inUse)
InstanceResetTimePoint GetExpiryTime() const
Difficulty GetDifficultyId() const
void SetIsNew(bool isNew)
bool IsInUse() const
InstanceLock & operator=(InstanceLock const &)=delete
uint32 GetMapId() const
void SetExpiryTime(InstanceResetTimePoint expiryTime)
InstanceLockData _data
InstanceLock & operator=(InstanceLock &&)=delete
bool IsNew() const
InstanceLock(InstanceLock const &)=delete
InstanceLock(InstanceLock &&)=delete
InstanceLockData const * GetData() const
InstanceLockData * GetData()
uint32 GetInstanceId() const
SharedInstanceLockData const * GetSharedData() const
SharedInstanceLockData * GetSharedData()
std::shared_ptr< SharedInstanceLockData > _sharedData
InstanceLockData const * GetInstanceInitializationData() const override
STL namespace.
uint32 EntranceWorldSafeLocId
InstanceLockData(InstanceLockData const &)=delete
InstanceLockData(InstanceLockData &&)=delete
InstanceLockData & operator=(InstanceLockData const &)=delete
std::string Data
uint32 CompletedEncountersMask
InstanceLockData & operator=(InstanceLockData &&)=delete
virtual ~InstanceLockData()
InstanceLockUpdateEvent(uint32 instanceId, std::string newData, uint32 instanceCompletedEncountersMask, DungeonEncounterEntry const *completedEncounter, Optional< uint32 > entranceWorldSafeLocId)
InstanceLockUpdateEvent(InstanceLockUpdateEvent const &other)=delete
Optional< uint32 > EntranceWorldSafeLocId
InstanceLockUpdateEvent & operator=(InstanceLockUpdateEvent &&) noexcept
InstanceLockUpdateEvent & operator=(InstanceLockUpdateEvent const &)=delete
DungeonEncounterEntry const * CompletedEncounter
InstanceLockUpdateEvent(InstanceLockUpdateEvent &&other) noexcept
MapEntry const * Map
MapDifficultyEntry const * MapDifficulty
SharedInstanceLockData & operator=(SharedInstanceLockData const &)=delete
SharedInstanceLockData & operator=(SharedInstanceLockData &&)=delete
SharedInstanceLockData(SharedInstanceLockData &&)=delete
SharedInstanceLockData(SharedInstanceLockData const &)=delete