AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
InstanceSaveMgr Class Reference

#include "InstanceSaveMgr.h"

Classes

struct  InstResetEvent
 

Public Types

typedef std::unordered_map< uint32, InstanceSave * > InstanceSaveHashMap
 
typedef std::multimap< time_t, InstResetEventResetTimeQueue
 

Public Member Functions

void LoadInstances ()
 
void LoadResetTimes ()
 
void LoadInstanceSaves ()
 
void LoadCharacterBinds ()
 
InstanceMapLoadRows LoadInstanceSavesAndBindsForMapIDs (std::vector< uint32 > const &mapIDs)
 
void MergeWithNewInstanceSaves (InstanceMapLoadRows const &loadResult)
 
time_t GetResetTimeFor (uint32 mapid, Difficulty d) const
 
time_t GetExtendedResetTimeFor (uint32 mapid, Difficulty d) const
 
void SetResetTimeFor (uint32 mapid, Difficulty d, time_t t)
 
void SetExtendedResetTimeFor (uint32 mapid, Difficulty d, time_t t)
 
ResetTimeByMapDifficultyMap const & GetResetTimeMap () const
 
void ScheduleReset (time_t time, InstResetEvent event)
 
void Update ()
 
InstanceSaveAddInstanceSave (uint32 mapId, uint32 instanceId, Difficulty difficulty, bool startup=false)
 
bool DeleteInstanceSaveIfNeeded (uint32 InstanceId, bool skipMapCheck)
 
bool DeleteInstanceSaveIfNeeded (InstanceSave *save, bool skipMapCheck, bool deleteSave=true)
 
InstanceSaveGetInstanceSave (uint32 InstanceId)
 
InstancePlayerBindPlayerBindToInstance (ObjectGuid guid, InstanceSave *save, bool permanent, Player *player=nullptr)
 
void PlayerUnbindInstance (ObjectGuid guid, uint32 mapid, Difficulty difficulty, bool deleteFromDB, Player *player=nullptr)
 
void PlayerUnbindInstanceNotExtended (ObjectGuid guid, uint32 mapid, Difficulty difficulty, Player *player=nullptr)
 
InstancePlayerBindPlayerGetBoundInstance (ObjectGuid guid, uint32 mapid, Difficulty difficulty)
 
bool PlayerIsPermBoundToInstance (ObjectGuid guid, uint32 mapid, Difficulty difficulty)
 
BoundInstancesMap const & PlayerGetBoundInstances (ObjectGuid guid, Difficulty difficulty)
 
void PlayerCreateBoundInstancesMaps (ObjectGuid guid)
 
InstanceSavePlayerGetInstanceSave (ObjectGuid guid, uint32 mapid, Difficulty difficulty)
 
uint32 PlayerGetDestinationInstanceId (Player *player, uint32 mapid, Difficulty difficulty)
 
void CopyBinds (ObjectGuid from, ObjectGuid to, Player *toPlr=nullptr)
 
void UnbindAllFor (InstanceSave *save)
 
void SanitizeInstanceSavedData ()
 
void DeleteInstanceSavedData (uint32 instanceId)
 

Static Public Member Functions

static InstanceSaveMgrinstance ()
 

Static Protected Attributes

static uint16 ResetTimeDelay [] = {3600, 900, 300, 60, 0}
 
static PlayerBindStorage playerBindStorage
 
static BoundInstancesMap emptyBoundInstancesMap
 

Private Member Functions

 InstanceSaveMgr ()=default
 
 ~InstanceSaveMgr ()
 
void _ResetOrWarnAll (uint32 mapid, Difficulty difficulty, bool warn, time_t resetTime)
 
void _ResetSave (InstanceSaveHashMap::iterator &itr)
 

Private Attributes

bool lock_instLists {false}
 
InstanceSaveHashMap m_instanceSaveById
 
ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty
 
ResetTimeByMapDifficultyMap m_resetExtendedTimeByMapDifficulty
 
ResetTimeQueue m_resetTimeQueue
 

Friends

class InstanceSave
 

Detailed Description

Member Typedef Documentation

◆ InstanceSaveHashMap

◆ ResetTimeQueue

typedef std::multimap<time_t , InstResetEvent> InstanceSaveMgr::ResetTimeQueue

Constructor & Destructor Documentation

◆ InstanceSaveMgr()

InstanceSaveMgr::InstanceSaveMgr ( )
privatedefault

◆ ~InstanceSaveMgr()

InstanceSaveMgr::~InstanceSaveMgr ( )
private
43{
44 lock_instLists = true;
45 // pussywizard: crashes on calling function in destructor (PlayerUnbindInstance), completely not needed anyway
46 /*for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr)
47 {
48 InstanceSave* save = itr->second;
49
50 InstanceSave::PlayerListType &pList = save->m_playerList;
51 while (!pList.empty())
52 PlayerUnbindInstance(*(pList.begin()), save->GetMapId(), save->GetDifficulty(), false);
53
54 delete save;
55 }*/
56}
bool lock_instLists
Definition InstanceSaveMgr.h:226

References lock_instLists.

Member Function Documentation

◆ _ResetOrWarnAll()

void InstanceSaveMgr::_ResetOrWarnAll ( uint32  mapid,
Difficulty  difficulty,
bool  warn,
time_t  resetTime 
)
private
717{
718 // global reset for all instances of the given map
719 MapEntry const* mapEntry = sMapStore.LookupEntry(mapid);
720 if (!mapEntry->Instanceable())
721 return;
722
723 time_t now = GameTime::GetGameTime().count();
724
725 if (!warn)
726 {
727 MapDifficulty const* mapDiff = GetMapDifficultyData(mapid, difficulty);
728 if (!mapDiff || !mapDiff->resetTime)
729 {
730 LOG_ERROR("instance.save", "InstanceSaveMgr::ResetOrWarnAll: not valid difficulty or no reset delay for map {}", mapid);
731 return;
732 }
733
734 // calculate the next reset time
735 uint32 diff = sWorld->getIntConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
736
737 uint32 period = uint32(((mapDiff->resetTime * sWorld->getRate(RATE_INSTANCE_RESET_TIME)) / DAY) * DAY);
738 if (period < DAY)
739 period = DAY;
740
741 uint32 next_reset = uint32(((resetTime + MINUTE) / DAY * DAY) + period + diff);
742 SetResetTimeFor(mapid, difficulty, next_reset);
743 SetExtendedResetTimeFor(mapid, difficulty, next_reset + period);
744 ScheduleReset(time_t(next_reset - 3600), InstResetEvent(1, mapid, difficulty));
745
746 // update it in the DB
748 stmt->SetData(0, next_reset);
749 stmt->SetData(1, uint16(mapid));
750 stmt->SetData(2, uint8(difficulty));
751 CharacterDatabase.Execute(stmt);
752
753 // remove all binds to instances of the given map and delete from db (delete per instance id, no mass deletion!)
754 // do this after new reset time is calculated
755 for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(), itr2; itr != m_instanceSaveById.end(); )
756 {
757 itr2 = itr++;
758 if (itr2->second->GetMapId() == mapid && itr2->second->GetDifficulty() == difficulty)
759 _ResetSave(itr2);
760 }
761 }
762
763 // now loop all existing maps to warn / reset
764 Map const* map = sMapMgr->CreateBaseMap(mapid);
765 MapInstanced::InstancedMaps& instMaps = ((MapInstanced*)map)->GetInstancedMaps();
766 MapInstanced::InstancedMaps::iterator mitr;
767 uint32 timeLeft;
768
769 for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr)
770 {
771 Map* map2 = mitr->second;
772 if (!map2->IsDungeon() || map2->GetDifficulty() != difficulty)
773 continue;
774
775 if (warn)
776 {
777 if (now >= resetTime)
778 timeLeft = 0;
779 else
780 timeLeft = uint32(resetTime - now);
781
782 map2->ToInstanceMap()->SendResetWarnings(timeLeft);
783 }
784 else
785 {
787 map2->ToInstanceMap()->Reset(INSTANCE_RESET_GLOBAL, (save ? & (save->m_playerList) : nullptr));
788 }
789 }
790}
@ CHAR_UPD_GLOBAL_INSTANCE_RESETTIME
Definition CharacterDatabase.h:305
constexpr auto DAY
Definition Common.h:49
constexpr auto HOUR
Definition Common.h:48
constexpr auto MINUTE
Definition Common.h:47
MapDifficulty const * GetMapDifficultyData(uint32 mapId, Difficulty difficulty)
Definition DBCStores.cpp:761
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition DatabaseEnv.cpp:21
std::uint8_t uint8
Definition Define.h:109
std::uint32_t uint32
Definition Define.h:107
std::uint16_t uint16
Definition Define.h:108
#define LOG_ERROR(filterType__,...)
Definition Log.h:145
#define sMapMgr
Definition MapMgr.h:220
@ INSTANCE_RESET_GLOBAL
Definition Map.h:718
@ RATE_INSTANCE_RESET_TIME
Definition WorldConfig.h:495
@ CONFIG_INSTANCE_RESET_TIME_HOUR
Definition WorldConfig.h:208
void SendResetWarnings(uint32 timeLeft) const
Definition Map.cpp:2303
bool Reset(uint8 method, GuidList *globalSkipList=nullptr)
Definition Map.cpp:2205
InstanceSave * GetInstanceSave(uint32 InstanceId)
Definition InstanceSaveMgr.cpp:109
void ScheduleReset(time_t time, InstResetEvent event)
Definition InstanceSaveMgr.cpp:612
void _ResetSave(InstanceSaveHashMap::iterator &itr)
Definition InstanceSaveMgr.cpp:664
void SetResetTimeFor(uint32 mapid, Difficulty d, time_t t)
Definition InstanceSaveMgr.h:179
InstanceSaveHashMap m_instanceSaveById
Definition InstanceSaveMgr.h:227
void SetExtendedResetTimeFor(uint32 mapid, Difficulty d, time_t t)
Definition InstanceSaveMgr.h:184
Definition InstanceSaveMgr.h:57
GuidList m_playerList
Definition InstanceSaveMgr.h:92
Definition MapInstanced.h:26
std::unordered_map< uint32, Map * > InstancedMaps
Definition MapInstanced.h:29
Definition Map.h:168
bool IsDungeon() const
Definition Map.h:299
InstanceMap * ToInstanceMap()
Definition Map.h:390
Difficulty GetDifficulty() const
Definition Map.h:294
uint32 GetInstanceId() const
Definition Map.h:270
Acore::Types::is_default< T > SetData(const uint8 index, T value)
Definition PreparedStatement.h:77
Definition PreparedStatement.h:157
#define sWorld
Definition World.h:318
Seconds GetGameTime()
Definition GameTime.cpp:38
Definition DBCStructure.h:2222
uint32 resetTime
Definition DBCStructure.h:2226
Definition DBCStructure.h:1325
bool Instanceable() const
Definition DBCStructure.h:1353

References _ResetSave(), CHAR_UPD_GLOBAL_INSTANCE_RESETTIME, CharacterDatabase, CONFIG_INSTANCE_RESET_TIME_HOUR, DAY, Map::GetDifficulty(), GameTime::GetGameTime(), Map::GetInstanceId(), GetInstanceSave(), GetMapDifficultyData(), HOUR, INSTANCE_RESET_GLOBAL, MapEntry::Instanceable(), Map::IsDungeon(), LOG_ERROR, m_instanceSaveById, InstanceSave::m_playerList, MINUTE, RATE_INSTANCE_RESET_TIME, InstanceMap::Reset(), MapDifficulty::resetTime, ScheduleReset(), InstanceMap::SendResetWarnings(), PreparedStatementBase::SetData(), SetExtendedResetTimeFor(), SetResetTimeFor(), sMapMgr, sMapStore, sWorld, and Map::ToInstanceMap().

Referenced by Update().

◆ _ResetSave()

void InstanceSaveMgr::_ResetSave ( InstanceSaveHashMap::iterator &  itr)
private
665{
666 lock_instLists = true;
667
668 GuidList& pList = itr->second->m_playerList;
669 for (GuidList::iterator iter = pList.begin(), iter2; iter != pList.end(); )
670 {
671 iter2 = iter++;
672 PlayerUnbindInstanceNotExtended(*iter2, itr->second->GetMapId(), itr->second->GetDifficulty(), ObjectAccessor::FindConnectedPlayer(*iter2));
673 }
674
675 // delete stuff if no players left (noone extended id)
676 if (pList.empty())
677 {
678 // delete character_instance per id, delete instance per id
680 stmt->SetData(0, itr->second->GetInstanceId());
681 CharacterDatabase.Execute(stmt);
682 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INSTANCE_BY_INSTANCE);
683 stmt->SetData(0, itr->second->GetInstanceId());
684 CharacterDatabase.Execute(stmt);
685 DeleteInstanceSavedData(itr->second->GetInstanceId());
686
687 // clear respawn times if the map is already unloaded and won't do it by itself
688 if (!sMapMgr->FindMap(itr->second->GetMapId(), itr->second->GetInstanceId()))
689 Map::DeleteRespawnTimesInDB(itr->second->GetMapId(), itr->second->GetInstanceId());
690
691 sScriptMgr->OnInstanceIdRemoved(itr->second->GetInstanceId());
692
693 delete itr->second;
694 m_instanceSaveById.erase(itr);
695 }
696 else
697 {
698 // delete character_instance per id where extended = 0, transtaction with set extended = 0, transaction is used to avoid mysql thread races
699 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
701 stmt->SetData(0, itr->second->GetInstanceId());
702 trans->Append(stmt);
704 stmt->SetData(0, itr->second->GetInstanceId());
705 trans->Append(stmt);
706 CharacterDatabase.CommitTransaction(trans);
707
708 // update reset time and extended reset time for instance save
709 itr->second->SetResetTime(GetResetTimeFor(itr->second->GetMapId(), itr->second->GetDifficulty()));
710 itr->second->SetExtendedResetTime(GetExtendedResetTimeFor(itr->second->GetMapId(), itr->second->GetDifficulty()));
711 }
712
713 lock_instLists = false;
714}
@ CHAR_UPD_CHAR_INSTANCE_SET_NOT_EXTENDED
Definition CharacterDatabase.h:312
@ CHAR_DEL_INSTANCE_BY_INSTANCE
Definition CharacterDatabase.h:385
@ CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_NOT_EXTENDED
Definition CharacterDatabase.h:311
@ CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE
Definition CharacterDatabase.h:310
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
Definition DatabaseEnvFwd.h:69
std::list< ObjectGuid > GuidList
Definition ObjectGuid.h:258
#define sScriptMgr
Definition ScriptMgr.h:743
void DeleteInstanceSavedData(uint32 instanceId)
Definition InstanceSaveMgr.cpp:254
time_t GetResetTimeFor(uint32 mapid, Difficulty d) const
Definition InstanceSaveMgr.h:167
time_t GetExtendedResetTimeFor(uint32 mapid, Difficulty d) const
Definition InstanceSaveMgr.h:173
void PlayerUnbindInstanceNotExtended(ObjectGuid guid, uint32 mapid, Difficulty difficulty, Player *player=nullptr)
Definition InstanceSaveMgr.cpp:887
static void DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId)
Definition Map.cpp:2583
Player * FindConnectedPlayer(ObjectGuid const guid)
Definition ObjectAccessor.cpp:281

References CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE, CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_NOT_EXTENDED, CHAR_DEL_INSTANCE_BY_INSTANCE, CHAR_UPD_CHAR_INSTANCE_SET_NOT_EXTENDED, CharacterDatabase, DeleteInstanceSavedData(), Map::DeleteRespawnTimesInDB(), ObjectAccessor::FindConnectedPlayer(), GetExtendedResetTimeFor(), GetResetTimeFor(), lock_instLists, m_instanceSaveById, PlayerUnbindInstanceNotExtended(), PreparedStatementBase::SetData(), sMapMgr, and sScriptMgr.

Referenced by _ResetOrWarnAll().

◆ AddInstanceSave()

InstanceSave * InstanceSaveMgr::AddInstanceSave ( uint32  mapId,
uint32  instanceId,
Difficulty  difficulty,
bool  startup = false 
)
68{
69 ASSERT(!GetInstanceSave(instanceId));
70
71 MapEntry const* entry = sMapStore.LookupEntry(mapId);
72 if (!entry)
73 {
74 LOG_ERROR("instance.save", "InstanceSaveMgr::AddInstanceSave: wrong mapid = {}, instanceid = {}!", mapId, instanceId);
75 return nullptr;
76 }
77
78 if (instanceId == 0)
79 {
80 LOG_ERROR("instance.save", "InstanceSaveMgr::AddInstanceSave: mapid = {}, wrong instanceid = {}!", mapId, instanceId);
81 return nullptr;
82 }
83
84 if (difficulty >= (entry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY))
85 {
86 LOG_ERROR("instance.save", "InstanceSaveMgr::AddInstanceSave: mapid = {}, instanceid = {}, wrong difficulty {}!", mapId, instanceId, difficulty);
87 return nullptr;
88 }
89
90 time_t resetTime, extendedResetTime;
91 if (entry->map_type == MAP_RAID || difficulty > DUNGEON_DIFFICULTY_NORMAL)
92 {
93 resetTime = GetResetTimeFor(mapId, difficulty);
94 extendedResetTime = GetExtendedResetTimeFor(mapId, difficulty);
95 }
96 else
97 {
98 resetTime = GameTime::GetGameTime().count() + static_cast<long long>(3) * DAY; // normals expire after 3 days even if someone is still bound to them, cleared on startup
99 extendedResetTime = 0;
100 }
101 InstanceSave* save = new InstanceSave(mapId, instanceId, difficulty, resetTime, extendedResetTime);
102 if (!startup)
103 save->InsertToDB();
104
105 m_instanceSaveById[instanceId] = save;
106 return save;
107}
#define MAX_RAID_DIFFICULTY
Definition DBCEnums.h:282
@ MAP_RAID
Definition DBCEnums.h:348
@ DUNGEON_DIFFICULTY_NORMAL
Definition DBCEnums.h:269
#define MAX_DUNGEON_DIFFICULTY
Definition DBCEnums.h:281
#define ASSERT
Definition Errors.h:68
friend class InstanceSave
Definition InstanceSaveMgr.h:134
void InsertToDB()
Definition InstanceSaveMgr.cpp:166
bool IsRaid() const
Definition DBCStructure.h:1354
uint32 map_type
Definition DBCStructure.h:1328

References ASSERT, DAY, DUNGEON_DIFFICULTY_NORMAL, GetExtendedResetTimeFor(), GameTime::GetGameTime(), GetInstanceSave(), GetResetTimeFor(), InstanceSave::InsertToDB(), InstanceSave, MapEntry::IsRaid(), LOG_ERROR, m_instanceSaveById, MAP_RAID, MapEntry::map_type, MAX_DUNGEON_DIFFICULTY, MAX_RAID_DIFFICULTY, and sMapStore.

Referenced by LoadInstanceSaves().

◆ CopyBinds()

void InstanceSaveMgr::CopyBinds ( ObjectGuid  from,
ObjectGuid  to,
Player toPlr = nullptr 
)
975{
976 if (from == to)
977 return;
978
979 for (uint8 d = 0; d < MAX_DIFFICULTY; ++d)
980 {
982 for (BoundInstancesMap::const_iterator itr = bi.begin(); itr != bi.end(); ++itr)
983 if (!PlayerGetBoundInstance(to, itr->first, Difficulty(d)))
984 PlayerBindToInstance(to, itr->second.save, false, toPlr);
985 }
986}
Difficulty
Definition DBCEnums.h:266
#define MAX_DIFFICULTY
Definition DBCEnums.h:283
std::unordered_map< uint32, InstancePlayerBind > BoundInstancesMap
Definition InstanceSaveMgr.h:47
InstancePlayerBind * PlayerBindToInstance(ObjectGuid guid, InstanceSave *save, bool permanent, Player *player=nullptr)
Definition InstanceSaveMgr.cpp:792
BoundInstancesMap const & PlayerGetBoundInstances(ObjectGuid guid, Difficulty difficulty)
Definition InstanceSaveMgr.cpp:937
InstancePlayerBind * PlayerGetBoundInstance(ObjectGuid guid, uint32 mapid, Difficulty difficulty)
Definition InstanceSaveMgr.cpp:907

References MAX_DIFFICULTY, PlayerBindToInstance(), PlayerGetBoundInstance(), and PlayerGetBoundInstances().

◆ DeleteInstanceSavedData()

void InstanceSaveMgr::DeleteInstanceSavedData ( uint32  instanceId)
255{
256 if (instanceId)
257 {
259 stmt->SetData(0, instanceId);
260 CharacterDatabase.Execute(stmt);
261 }
262}
@ CHAR_DELETE_INSTANCE_SAVED_DATA
Definition CharacterDatabase.h:542

References CHAR_DELETE_INSTANCE_SAVED_DATA, CharacterDatabase, and PreparedStatementBase::SetData().

Referenced by _ResetSave(), and DeleteInstanceSaveIfNeeded().

◆ DeleteInstanceSaveIfNeeded() [1/2]

bool InstanceSaveMgr::DeleteInstanceSaveIfNeeded ( InstanceSave save,
bool  skipMapCheck,
bool  deleteSave = true 
)
121{
122 // pussywizard: save is removed only when there are no more players bound AND the map doesn't exist
123 // pussywizard: this function is called when unbinding a player and when unloading a map
124 if (!lock_instLists && save && save->m_playerList.empty() && (skipMapCheck || !sMapMgr->FindMap(save->GetMapId(), save->GetInstanceId())))
125 {
126 // delete save from storage:
127 InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(save->GetInstanceId());
128 ASSERT(itr != m_instanceSaveById.end() && itr->second == save);
129 m_instanceSaveById.erase(itr);
130
131 // delete save from db:
132 // character_instance is deleted when unbinding a certain player
134 stmt->SetData(0, save->GetInstanceId());
135 CharacterDatabase.Execute(stmt);
137
138 // clear respawn times (if map is loaded do it just to be sure, if already unloaded it won't do it by itself)
140
141 sScriptMgr->OnInstanceIdRemoved(save->GetInstanceId());
142
143 if (deleteSave)
144 {
145 delete save;
146 }
147
148 return true;
149 }
150 return false;
151}
uint32 GetInstanceId() const
Definition InstanceSaveMgr.h:62
uint32 GetMapId() const
Definition InstanceSaveMgr.h:63

References ASSERT, CHAR_DEL_INSTANCE_BY_INSTANCE, CharacterDatabase, DeleteInstanceSavedData(), Map::DeleteRespawnTimesInDB(), InstanceSave::GetInstanceId(), InstanceSave::GetMapId(), lock_instLists, m_instanceSaveById, InstanceSave::m_playerList, PreparedStatementBase::SetData(), sMapMgr, and sScriptMgr.

◆ DeleteInstanceSaveIfNeeded() [2/2]

bool InstanceSaveMgr::DeleteInstanceSaveIfNeeded ( uint32  InstanceId,
bool  skipMapCheck 
)
116{
117 return DeleteInstanceSaveIfNeeded(GetInstanceSave(InstanceId), skipMapCheck);
118}
bool DeleteInstanceSaveIfNeeded(uint32 InstanceId, bool skipMapCheck)
Definition InstanceSaveMgr.cpp:115

References DeleteInstanceSaveIfNeeded(), and GetInstanceSave().

Referenced by DeleteInstanceSaveIfNeeded(), and InstanceSave::RemovePlayer().

◆ GetExtendedResetTimeFor()

time_t InstanceSaveMgr::GetExtendedResetTimeFor ( uint32  mapid,
Difficulty  d 
) const
inline
174 {
175 ResetTimeByMapDifficultyMap::const_iterator itr = m_resetExtendedTimeByMapDifficulty.find(MAKE_PAIR32(mapid, d));
176 return itr != m_resetExtendedTimeByMapDifficulty.end() ? itr->second : 0;
177 }
uint32 MAKE_PAIR32(uint16 l, uint16 h)
Definition ObjectDefines.h:88
ResetTimeByMapDifficultyMap m_resetExtendedTimeByMapDifficulty
Definition InstanceSaveMgr.h:229

References m_resetExtendedTimeByMapDifficulty, and MAKE_PAIR32().

Referenced by _ResetSave(), AddInstanceSave(), and MergeWithNewInstanceSaves().

◆ GetInstanceSave()

InstanceSave * InstanceSaveMgr::GetInstanceSave ( uint32  InstanceId)
110{
111 InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(InstanceId);
112 return itr != m_instanceSaveById.end() ? itr->second : nullptr;
113}

References m_instanceSaveById.

Referenced by _ResetOrWarnAll(), AddInstanceSave(), DeleteInstanceSaveIfNeeded(), and LoadCharacterBinds().

◆ GetResetTimeFor()

time_t InstanceSaveMgr::GetResetTimeFor ( uint32  mapid,
Difficulty  d 
) const
inline
168 {
169 ResetTimeByMapDifficultyMap::const_iterator itr = m_resetTimeByMapDifficulty.find(MAKE_PAIR32(mapid, d));
170 return itr != m_resetTimeByMapDifficulty.end() ? itr->second : 0;
171 }
ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty
Definition InstanceSaveMgr.h:228

References m_resetTimeByMapDifficulty, and MAKE_PAIR32().

Referenced by _ResetSave(), AddInstanceSave(), LoadResetTimes(), and Update().

◆ GetResetTimeMap()

ResetTimeByMapDifficultyMap const & InstanceSaveMgr::GetResetTimeMap ( ) const
inline
190 {
192 }

References m_resetTimeByMapDifficulty.

◆ instance()

InstanceSaveMgr * InstanceSaveMgr::instance ( )
static
59{
61 return &instance;
62}
Definition InstanceSaveMgr.h:133
static InstanceSaveMgr * instance()
Definition InstanceSaveMgr.cpp:58

References instance().

Referenced by instance().

◆ LoadCharacterBinds()

void InstanceSaveMgr::LoadCharacterBinds ( )
410{
411 lock_instLists = true;
412
413 QueryResult result = CharacterDatabase.Query("SELECT guid, instance, permanent, extended FROM character_instance");
414 if (result)
415 {
416 do
417 {
418 Field* fields = result->Fetch();
419
420 ObjectGuid guid = ObjectGuid::Create<HighGuid::Player>(fields[0].Get<uint32>());
421 uint32 instanceId = fields[1].Get<uint32>();
422 bool perm = fields[2].Get<bool>();
423 bool extended = fields[3].Get<bool>();
424
425 if (InstanceSave* save = GetInstanceSave(instanceId))
426 {
428 InstancePlayerBind& bind = playerBindStorage[guid]->m[save->GetDifficulty()][save->GetMapId()];
429 if (bind.save) // pussywizard: another bind for the same map and difficulty! may happen because of mysql thread races
430 {
431 if (bind.perm) // already loaded perm -> delete currently checked one from db
432 {
434 stmt->SetData(0, guid.GetCounter());
435 stmt->SetData(1, instanceId);
436 CharacterDatabase.Execute(stmt);
437 continue;
438 }
439 else // override temp bind by newest one
440 {
442 stmt->SetData(0, guid.GetCounter());
443 stmt->SetData(1, bind.save->GetInstanceId());
444 CharacterDatabase.Execute(stmt);
445 bind.save->RemovePlayer(guid, this);
446 }
447 }
448 bind.save = save;
449 bind.perm = perm;
450 bind.extended = extended;
451 save->AddPlayer(guid);
452 if (perm)
453 save->SetCanReset(false);
454 }
455 } while (result->NextRow());
456 }
457
458 lock_instLists = false;
459}
@ CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID
Definition CharacterDatabase.h:313
std::shared_ptr< ResultSet > QueryResult
Definition DatabaseEnvFwd.h:27
Class used to access individual fields of database query result.
Definition Field.h:98
std::enable_if_t< std::is_arithmetic_v< T >, T > Get() const
Definition Field.h:112
void PlayerCreateBoundInstancesMaps(ObjectGuid guid)
Definition InstanceSaveMgr.cpp:945
static PlayerBindStorage playerBindStorage
Definition InstanceSaveMgr.h:220
bool RemovePlayer(ObjectGuid guid, InstanceSaveMgr *ism)
Definition InstanceSaveMgr.cpp:228
Definition ObjectGuid.h:121
LowType GetCounter() const
Definition ObjectGuid.h:149
Definition InstanceSaveMgr.h:40
InstanceSave * save
Definition InstanceSaveMgr.h:41
bool extended
Definition InstanceSaveMgr.h:43
bool perm
Definition InstanceSaveMgr.h:42

References CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID, CharacterDatabase, InstancePlayerBind::extended, Field::Get(), ObjectGuid::GetCounter(), InstanceSave::GetInstanceId(), GetInstanceSave(), lock_instLists, InstancePlayerBind::perm, playerBindStorage, PlayerCreateBoundInstancesMaps(), InstanceSave::RemovePlayer(), InstancePlayerBind::save, and PreparedStatementBase::SetData().

Referenced by LoadInstances().

◆ LoadInstances()

void InstanceSaveMgr::LoadInstances ( )
265{
266 uint32 oldMSTime = getMSTime();
267
268 // Delete character_instance for non-existent character
269 CharacterDatabase.DirectExecute("DELETE ci.* FROM character_instance AS ci LEFT JOIN characters AS c ON ci.guid = c.guid WHERE c.guid IS NULL");
270
271 // Delete expired normal instances (normals expire after 3 days even if someone is still bound to them, cleared on startup)
272 CharacterDatabase.DirectExecute("DELETE FROM instance WHERE resettime > 0 AND resettime < UNIX_TIMESTAMP()");
273
274 // Delete instance with no binds
275 CharacterDatabase.DirectExecute("DELETE i.* FROM instance AS i LEFT JOIN character_instance AS ci ON i.id = ci.instance WHERE ci.guid IS NULL");
276
277 // Delete creature_respawn, gameobject_respawn and creature_instance for non-existent instance
278 CharacterDatabase.DirectExecute("DELETE FROM creature_respawn WHERE instanceId > 0 AND instanceId NOT IN (SELECT id FROM instance)");
279 CharacterDatabase.DirectExecute("DELETE FROM gameobject_respawn WHERE instanceId > 0 AND instanceId NOT IN (SELECT id FROM instance)");
280 CharacterDatabase.DirectExecute("DELETE tmp.* FROM character_instance AS tmp LEFT JOIN instance ON tmp.instance = instance.id WHERE tmp.instance > 0 AND instance.id IS NULL");
281
282 // Clean invalid references to instance
283 CharacterDatabase.DirectExecute("UPDATE corpse SET instanceId = 0 WHERE instanceId > 0 AND instanceId NOT IN (SELECT id FROM instance)");
284 CharacterDatabase.DirectExecute("UPDATE characters AS tmp LEFT JOIN instance ON tmp.instance_id = instance.id SET tmp.instance_id = 0 WHERE tmp.instance_id > 0 AND instance.id IS NULL");
285
286 // Initialize instance id storage (Needs to be done after the trash has been clean out)
287 sMapMgr->InitInstanceIds();
288
289 // Load reset times and clean expired instances
291
292 // pussywizard
295
296 // Sanitize pending rows on Instance_saved_data for data that wasn't deleted properly
298
299 LOG_INFO("server.loading", ">> Loaded Instances And Binds in {} ms", GetMSTimeDiffToNow(oldMSTime));
300 LOG_INFO("server.loading", " ");
301}
#define LOG_INFO(filterType__,...)
Definition Log.h:153
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:131
uint32 getMSTime()
Definition Timer.h:103
void LoadCharacterBinds()
Definition InstanceSaveMgr.cpp:409
void LoadInstanceSaves()
Definition InstanceSaveMgr.cpp:378
void LoadResetTimes()
Definition InstanceSaveMgr.cpp:303
void SanitizeInstanceSavedData()
Definition InstanceSaveMgr.cpp:248

References CharacterDatabase, getMSTime(), GetMSTimeDiffToNow(), LoadCharacterBinds(), LoadInstanceSaves(), LoadResetTimes(), LOG_INFO, SanitizeInstanceSavedData(), and sMapMgr.

◆ LoadInstanceSaves()

void InstanceSaveMgr::LoadInstanceSaves ( )
379{
380 QueryResult result = CharacterDatabase.Query("SELECT id, map, resettime, difficulty, completedEncounters, data FROM instance ORDER BY id ASC");
381 if (result)
382 {
383 do
384 {
385 Field* fields = result->Fetch();
386
387 uint32 instanceId = fields[0].Get<uint32>();
388 uint32 mapId = fields[1].Get<uint16>();
389 time_t resettime = time_t(fields[2].Get<uint32>());
390 uint8 difficulty = fields[3].Get<uint8>();
391 uint32 completedEncounters = fields[4].Get<uint32>();
392 std::string instanceData = fields[5].Get<std::string>();
393
394 // Mark instance id as being used
395 sMapMgr->RegisterInstanceId(instanceId);
396
397 InstanceSave* save = AddInstanceSave(mapId, instanceId, Difficulty(difficulty), true);
398 if (save)
399 {
400 save->SetCompletedEncounterMask(completedEncounters);
401 save->SetInstanceData(instanceData);
402 if (resettime > 0)
403 save->SetResetTime(resettime);
404 }
405 } while (result->NextRow());
406 }
407}
InstanceSave * AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, bool startup=false)
Definition InstanceSaveMgr.cpp:67
void SetResetTime(time_t resetTime)
Definition InstanceSaveMgr.h:79
void SetInstanceData(std::string str)
Definition InstanceSaveMgr.h:71
void SetCompletedEncounterMask(uint32 mask)
Definition InstanceSaveMgr.h:73

References AddInstanceSave(), CharacterDatabase, Field::Get(), InstanceSave::SetCompletedEncounterMask(), InstanceSave::SetInstanceData(), InstanceSave::SetResetTime(), and sMapMgr.

Referenced by LoadInstances().

◆ LoadInstanceSavesAndBindsForMapIDs()

InstanceMapLoadRows InstanceSaveMgr::LoadInstanceSavesAndBindsForMapIDs ( std::vector< uint32 > const &  mapIDs)
465{
467
468 std::stringstream mapIDsStr;
469 for (size_t i = 0; i < mapIDs.size(); ++i)
470 {
471 mapIDsStr << mapIDs[i];
472 if (i < mapIDs.size() - 1)
473 mapIDsStr << ",";
474 }
475
476 QueryResult result = CharacterDatabase.Query("SELECT id, map, resettime, difficulty, completedEncounters, data FROM instance WHERE map IN ({}) ORDER BY id ASC", mapIDsStr.str());
477 if (result)
478 {
479 do
480 {
481 Field* fields = result->Fetch();
482
484 row.instanceId = fields[0].Get<uint32>();
485 row.mapId = fields[1].Get<uint16>();
486 row.resetTime = time_t(fields[2].Get<uint32>());
487 row.difficulty = fields[3].Get<uint8>();
488 row.completedEncounters = fields[4].Get<uint32>();
489 row.data = fields[5].Get<std::string>();
490 rows.instances.push_back(std::move(row));
491 } while (result->NextRow());
492 }
493
494 result = CharacterDatabase.Query("SELECT guid, instance, permanent, extended FROM character_instance WHERE instance IN (SELECT id FROM instance WHERE map IN ({}))", mapIDsStr.str());
495 if (result)
496 {
497 do
498 {
499 Field* fields = result->Fetch();
500
502 row.guidLow = fields[0].Get<uint32>();
503 row.instanceId = fields[1].Get<uint32>();
504 row.perm = fields[2].Get<bool>();
505 row.extended = fields[3].Get<bool>();
506 rows.binds.push_back(row);
507 } while (result->NextRow());
508 }
509
510 return rows;
511}
Definition InstanceSaveMgr.h:122
uint32 instanceId
Definition InstanceSaveMgr.h:124
bool extended
Definition InstanceSaveMgr.h:126
uint32 guidLow
Definition InstanceSaveMgr.h:123
bool perm
Definition InstanceSaveMgr.h:125
Definition InstanceSaveMgr.h:113
uint16 mapId
Definition InstanceSaveMgr.h:115
uint8 difficulty
Definition InstanceSaveMgr.h:117
std::string data
Definition InstanceSaveMgr.h:119
uint32 completedEncounters
Definition InstanceSaveMgr.h:118
uint32 instanceId
Definition InstanceSaveMgr.h:114
time_t resetTime
Definition InstanceSaveMgr.h:116
Definition InstanceSaveMgr.h:111
std::vector< InstanceRow > instances
Definition InstanceSaveMgr.h:128
std::vector< BindRow > binds
Definition InstanceSaveMgr.h:129

References InstanceMapLoadRows::binds, CharacterDatabase, InstanceMapLoadRows::InstanceRow::completedEncounters, InstanceMapLoadRows::InstanceRow::data, InstanceMapLoadRows::InstanceRow::difficulty, InstanceMapLoadRows::BindRow::extended, Field::Get(), InstanceMapLoadRows::BindRow::guidLow, InstanceMapLoadRows::InstanceRow::instanceId, InstanceMapLoadRows::BindRow::instanceId, InstanceMapLoadRows::instances, InstanceMapLoadRows::InstanceRow::mapId, InstanceMapLoadRows::BindRow::perm, and InstanceMapLoadRows::InstanceRow::resetTime.

◆ LoadResetTimes()

void InstanceSaveMgr::LoadResetTimes ( )
304{
305 time_t now = GameTime::GetGameTime().count();
306 time_t today = (now / DAY) * DAY;
307
308 // load the global respawn times for raid/heroic instances
309 uint32 diff = sWorld->getIntConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
310 QueryResult result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset");
311 if (result)
312 {
313 do
314 {
315 Field* fields = result->Fetch();
316 uint32 mapid = fields[0].Get<uint16>();
317 Difficulty difficulty = Difficulty(fields[1].Get<uint8>());
318 uint64 resettime = fields[2].Get<uint32>();
319
320 MapDifficulty const* mapDiff = GetMapDifficultyData(mapid, difficulty);
321 if (!mapDiff)
322 {
323 LOG_ERROR("instance.save", "InstanceSaveMgr::LoadResetTimes: invalid mapid({})/difficulty({}) pair in instance_reset!", mapid, difficulty);
324 CharacterDatabase.DirectExecute("DELETE FROM instance_reset WHERE mapid = '{}' AND difficulty = '{}'", mapid, difficulty);
325 continue;
326 }
327
328 SetResetTimeFor(mapid, difficulty, resettime);
329 } while (result->NextRow());
330 }
331
332 // calculate new global reset times for expired instances and those that have never been reset yet
333 // add the global reset times to the priority queue
334 for (MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr)
335 {
336 uint32 map_diff_pair = itr->first;
337 uint32 mapid = PAIR32_LOPART(map_diff_pair);
338 Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair));
339 MapDifficulty const* mapDiff = &itr->second;
340 if (!mapDiff->resetTime)
341 continue;
342
343 // the reset_delay must be at least one day
344 uint32 period = uint32(((mapDiff->resetTime * sWorld->getRate(RATE_INSTANCE_RESET_TIME)) / DAY) * DAY);
345 if (period < DAY)
346 period = DAY;
347
348 time_t t = GetResetTimeFor(mapid, difficulty);
349 if (!t)
350 {
351 // initialize the reset time
352 t = today + period + diff;
353 SetResetTimeFor(mapid, difficulty, t);
354 CharacterDatabase.DirectExecute("INSERT INTO instance_reset VALUES ('{}', '{}', '{}')", mapid, difficulty, (uint32)t);
355 }
356
357 if (t < now)
358 {
359 // assume that expired instances have already been cleaned
360 // calculate the next reset time
361 t = (t / DAY) * DAY;
362 t += ((today - t) / period + 1) * period + diff;
363 CharacterDatabase.DirectExecute("UPDATE instance_reset SET resettime = '{}' WHERE mapid = '{}' AND difficulty = '{}'", (uint32)t, mapid, difficulty);
364 }
365
366 SetExtendedResetTimeFor(mapid, difficulty, t);
367
368 // schedule the global reset/warning
369 uint8 type;
370 for (type = 1; type < 5; ++type)
371 if (now + ResetTimeDelay[type - 1] < t)
372 break;
373
374 ScheduleReset(t - ResetTimeDelay[type - 1], InstResetEvent(type, mapid, difficulty));
375 }
376}
MapDifficultyMap sMapDifficultyMap
Definition DBCStores.cpp:121
std::uint64_t uint64
Definition Define.h:106
uint16 PAIR32_HIPART(uint32 x)
Definition ObjectDefines.h:93
uint16 PAIR32_LOPART(uint32 x)
Definition ObjectDefines.h:98
static uint16 ResetTimeDelay[]
Definition InstanceSaveMgr.h:38

References CharacterDatabase, CONFIG_INSTANCE_RESET_TIME_HOUR, DAY, Field::Get(), GameTime::GetGameTime(), GetMapDifficultyData(), GetResetTimeFor(), HOUR, LOG_ERROR, PAIR32_HIPART(), PAIR32_LOPART(), RATE_INSTANCE_RESET_TIME, MapDifficulty::resetTime, ResetTimeDelay, ScheduleReset(), SetExtendedResetTimeFor(), SetResetTimeFor(), sMapDifficultyMap, and sWorld.

Referenced by LoadInstances().

◆ MergeWithNewInstanceSaves()

void InstanceSaveMgr::MergeWithNewInstanceSaves ( InstanceMapLoadRows const &  loadResult)
516{
517 // Same guard as LoadCharacterBinds: without it, an unbind cascading into
518 // DeleteInstanceSaveIfNeeded would delete the very DB rows being merged.
519 lock_instLists = true;
520
521 for (InstanceMapLoadRows::InstanceRow const& row : loadResult.instances)
522 {
523 MapEntry const* entry = sMapStore.LookupEntry(row.mapId);
524 if (!entry)
525 {
526 LOG_ERROR("instance.save", "InstanceSaveMgr::MergeWithNewInstanceSaves: wrong mapid = {}, instanceid = {}!", row.mapId, row.instanceId);
527 continue;
528 }
529
530 // Same row validation as AddInstanceSave for rows loaded on reassignment.
531 if (row.instanceId == 0)
532 {
533 LOG_ERROR("instance.save", "InstanceSaveMgr::MergeWithNewInstanceSaves: mapid = {}, wrong instanceid = {}!", row.mapId, row.instanceId);
534 continue;
535 }
536
537 if (row.difficulty >= (entry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY))
538 {
539 LOG_ERROR("instance.save", "InstanceSaveMgr::MergeWithNewInstanceSaves: mapid = {}, instanceid = {}, wrong difficulty {}!", row.mapId, row.instanceId, row.difficulty);
540 continue;
541 }
542
543 time_t extendedResetTime = 0;
544 if (entry->IsRaid() || row.difficulty > DUNGEON_DIFFICULTY_NORMAL)
545 extendedResetTime = GetExtendedResetTimeFor(row.mapId, Difficulty(row.difficulty));
546
547 InstanceSave* save = new InstanceSave(row.mapId, row.instanceId, Difficulty(row.difficulty), row.resetTime, extendedResetTime);
548 save->SetCompletedEncounterMask(row.completedEncounters);
549 save->SetInstanceData(row.data);
550 if (row.resetTime > 0)
551 save->SetResetTime(row.resetTime);
552
553 InstanceSaveHashMap::iterator currentSave = m_instanceSaveById.find(row.instanceId);
554 if (currentSave != m_instanceSaveById.end())
555 {
556 InstanceSave* oldSave = currentSave->second;
557
558 // Unbind every player still pointing at the stale save before it is
559 // freed, in-memory only: the DB rows were just refetched and are
560 // rebound below. Iterate a copy, PlayerUnbindInstance mutates the list.
561 GuidList players = oldSave->m_playerList;
562 for (ObjectGuid const& playerGuid : players)
563 PlayerUnbindInstance(playerGuid, oldSave->GetMapId(), oldSave->GetDifficulty(), false);
564
565 m_instanceSaveById.erase(currentSave);
566 delete oldSave;
567 }
568 m_instanceSaveById[row.instanceId] = save;
569 }
570
571 for (InstanceMapLoadRows::BindRow const& row : loadResult.binds)
572 {
573 InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(row.instanceId);
574 InstanceSave* save = itr != m_instanceSaveById.end() ? itr->second : nullptr;
575 if (!save)
576 continue;
577
578 ObjectGuid guid = ObjectGuid::Create<HighGuid::Player>(row.guidLow);
579
581 InstancePlayerBind& bind = playerBindStorage[guid]->m[save->GetDifficulty()][save->GetMapId()];
582 if (bind.save) // pussywizard: another bind for the same map and difficulty! may happen because of mysql thread races
583 {
584 if (bind.perm) // already loaded perm -> delete currently checked one from db
585 {
587 stmt->SetData(0, guid.GetCounter());
588 stmt->SetData(1, row.instanceId);
589 CharacterDatabase.Execute(stmt);
590 continue;
591 }
592 else // override temp bind by newest one
593 {
595 stmt->SetData(0, guid.GetCounter());
596 stmt->SetData(1, bind.save->GetInstanceId());
597 CharacterDatabase.Execute(stmt);
598 bind.save->RemovePlayer(guid, this);
599 }
600 }
601 bind.save = save;
602 bind.perm = row.perm;
603 bind.extended = row.extended;
604 save->AddPlayer(guid);
605 if (row.perm)
606 save->SetCanReset(false);
607 }
608
609 lock_instLists = false;
610}
void PlayerUnbindInstance(ObjectGuid guid, uint32 mapid, Difficulty difficulty, bool deleteFromDB, Player *player=nullptr)
Definition InstanceSaveMgr.cpp:864
void AddPlayer(ObjectGuid guid)
Definition InstanceSaveMgr.cpp:222
void SetCanReset(bool canReset)
Definition InstanceSaveMgr.h:83
Difficulty GetDifficulty() const
Definition InstanceSaveMgr.h:64

References InstanceSave::AddPlayer(), InstanceMapLoadRows::binds, CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID, CharacterDatabase, DUNGEON_DIFFICULTY_NORMAL, InstancePlayerBind::extended, ObjectGuid::GetCounter(), InstanceSave::GetDifficulty(), GetExtendedResetTimeFor(), InstanceSave::GetInstanceId(), InstanceSave::GetMapId(), InstanceMapLoadRows::instances, InstanceSave, MapEntry::IsRaid(), lock_instLists, LOG_ERROR, m_instanceSaveById, InstanceSave::m_playerList, MAX_DUNGEON_DIFFICULTY, MAX_RAID_DIFFICULTY, InstancePlayerBind::perm, playerBindStorage, PlayerCreateBoundInstancesMaps(), PlayerUnbindInstance(), InstanceSave::RemovePlayer(), InstancePlayerBind::save, InstanceSave::SetCanReset(), InstanceSave::SetCompletedEncounterMask(), PreparedStatementBase::SetData(), InstanceSave::SetInstanceData(), InstanceSave::SetResetTime(), and sMapStore.

◆ PlayerBindToInstance()

InstancePlayerBind * InstanceSaveMgr::PlayerBindToInstance ( ObjectGuid  guid,
InstanceSave save,
bool  permanent,
Player player = nullptr 
)
793{
794 InstancePlayerBind& bind = playerBindStorage[guid]->m[save->GetDifficulty()][save->GetMapId()];
795 ASSERT(!bind.perm || permanent); // ensure there's no changing permanent to temporary, this can be done only by unbinding
796
797 if (bind.save)
798 {
799 if (save != bind.save || permanent != bind.perm)
800 {
801 bind.extended = false;
802
804 stmt->SetData(0, save->GetInstanceId());
805 stmt->SetData(1, permanent);
806 stmt->SetData(2, guid.GetCounter());
807 stmt->SetData(3, bind.save->GetInstanceId());
808 CharacterDatabase.Execute(stmt);
809 }
810 }
811 else
812 {
813 // pussywizard: protect against mysql thread races!
814 // pussywizard: CHANGED MY MIND! DON'T SLOW DOWN THIS QUERY! HANDLE ONLY DURING LOADING FROM DB!
815 // example: enter instance -> bind -> update old id to new id -> exit -> delete new id
816 // if delete by new id is executed before update, then we end up with in db
817 /*CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
818 // ensure any for that map+difficulty is deleted!
819 CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INSTANCE_BY_GUID_MAP_DIFF); // DELETE ci FROM character_instance ci JOIN instance i ON ci.instance = i.id WHERE ci.guid = ? AND i.map = ? AND i.difficulty = ?
820 stmt->SetData(0, guidLow);
821 stmt->SetData(1, uint16(save->GetMapId()));
822 stmt->SetData(2, uint8(save->GetDifficulty()));
823 trans->Append(stmt);
824 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_INSTANCE);
825 stmt->SetData(0, guidLow);
826 stmt->SetData(1, save->GetInstanceId());
827 stmt->SetData(2, permanent);
828 trans->Append(stmt);
829 CharacterDatabase.CommitTransaction(trans);*/
830
832 stmt->SetData(0, guid.GetCounter());
833 stmt->SetData(1, save->GetInstanceId());
834 stmt->SetData(2, permanent);
835 CharacterDatabase.Execute(stmt);
836
837 if (player)
839 }
840
841 if (bind.save != save)
842 {
843 if (bind.save)
844 bind.save->RemovePlayer(guid, this);
845 save->AddPlayer(guid);
846 }
847
848 if (permanent)
849 {
850 save->SetCanReset(false);
851 if (!bind.perm && player) // temporary changing to permanent
852 player->GetSession()->SendCalendarRaidLockout(save, true);
853 }
854
855 bind.save = save;
856 bind.perm = permanent;
857
858 if (player)
859 sScriptMgr->OnPlayerBindToInstance(player, save->GetDifficulty(), save->GetMapId(), permanent);
860
861 return &bind;
862}
@ CHAR_INS_CHAR_INSTANCE
Definition CharacterDatabase.h:316
@ CHAR_UPD_CHAR_INSTANCE
Definition CharacterDatabase.h:314
@ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID
Definition DBCEnums.h:136
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1=0, uint32 miscValue2=0, Unit *unit=nullptr)
Definition PlayerUpdates.cpp:2181
WorldSession * GetSession() const
Definition Player.h:2030
void SendCalendarRaidLockout(InstanceSave const *save, bool add)
Definition CalendarHandler.cpp:814

References ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID, InstanceSave::AddPlayer(), ASSERT, CHAR_INS_CHAR_INSTANCE, CHAR_UPD_CHAR_INSTANCE, CharacterDatabase, InstancePlayerBind::extended, ObjectGuid::GetCounter(), InstanceSave::GetDifficulty(), InstanceSave::GetInstanceId(), InstanceSave::GetMapId(), Player::GetSession(), InstancePlayerBind::perm, playerBindStorage, InstanceSave::RemovePlayer(), InstancePlayerBind::save, WorldSession::SendCalendarRaidLockout(), InstanceSave::SetCanReset(), PreparedStatementBase::SetData(), sScriptMgr, and Player::UpdateAchievementCriteria().

Referenced by CopyBinds().

◆ PlayerCreateBoundInstancesMaps()

void InstanceSaveMgr::PlayerCreateBoundInstancesMaps ( ObjectGuid  guid)
946{
947 if (playerBindStorage.find(guid) == playerBindStorage.end())
949}
Definition InstanceSaveMgr.h:50

References playerBindStorage.

Referenced by LoadCharacterBinds(), and MergeWithNewInstanceSaves().

◆ PlayerGetBoundInstance()

InstancePlayerBind * InstanceSaveMgr::PlayerGetBoundInstance ( ObjectGuid  guid,
uint32  mapid,
Difficulty  difficulty 
)
908{
909 Difficulty difficulty_fixed = ( IsSharedDifficultyMap(mapid) ? Difficulty(difficulty % 2) : difficulty);
910
911 MapDifficulty const* mapDiff = GetDownscaledMapDifficultyData(mapid, difficulty_fixed);
912 if (!mapDiff)
913 return nullptr;
914
915 BoundInstancesMapWrapper* w = nullptr;
916 PlayerBindStorage::const_iterator itr = playerBindStorage.find(guid);
917 if (itr != playerBindStorage.end())
918 w = itr->second;
919 else
920 return nullptr;
921
922 BoundInstancesMap::iterator itr2 = w->m[difficulty_fixed].find(mapid);
923 if (itr2 != w->m[difficulty_fixed].end())
924 return &itr2->second;
925 else
926 return nullptr;
927}
MapDifficulty const * GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty)
Definition DBCStores.cpp:767
bool IsSharedDifficultyMap(uint32 mapid)
Definition DBCStores.cpp:829
BoundInstancesMap m[MAX_DIFFICULTY]
Definition InstanceSaveMgr.h:51

References GetDownscaledMapDifficultyData(), IsSharedDifficultyMap(), BoundInstancesMapWrapper::m, and playerBindStorage.

Referenced by CopyBinds(), PlayerGetDestinationInstanceId(), PlayerGetInstanceSave(), and PlayerIsPermBoundToInstance().

◆ PlayerGetBoundInstances()

BoundInstancesMap const & InstanceSaveMgr::PlayerGetBoundInstances ( ObjectGuid  guid,
Difficulty  difficulty 
)
938{
939 PlayerBindStorage::iterator itr = playerBindStorage.find(guid);
940 if (itr != playerBindStorage.end())
941 return itr->second->m[difficulty];
943}
static BoundInstancesMap emptyBoundInstancesMap
Definition InstanceSaveMgr.h:221

References emptyBoundInstancesMap, and playerBindStorage.

Referenced by CopyBinds().

◆ PlayerGetDestinationInstanceId()

uint32 InstanceSaveMgr::PlayerGetDestinationInstanceId ( Player player,
uint32  mapid,
Difficulty  difficulty 
)
958{
959 // returning 0 means a new instance will be created
960 // non-zero implicates that InstanceSave exists
961
962 InstancePlayerBind* ipb = PlayerGetBoundInstance(player->GetGUID(), mapid, difficulty);
963 if (ipb && ipb->perm) // 1. self perm
964 return ipb->save->GetInstanceId();
965 if (Group* g = player->GetGroup())
966 {
967 if (InstancePlayerBind* ilb = PlayerGetBoundInstance(g->GetLeaderGUID(), mapid, difficulty)) // 2. leader temp/perm
968 return ilb->save->GetInstanceId();
969 return 0; // 3. in group, no leader bind
970 }
971 return ipb ? ipb->save->GetInstanceId() : 0; // 4. self temp
972}
Definition Group.h:177
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:114
Group * GetGroup()
Definition Player.h:2516

References Player::GetGroup(), Object::GetGUID(), InstanceSave::GetInstanceId(), InstancePlayerBind::perm, PlayerGetBoundInstance(), and InstancePlayerBind::save.

◆ PlayerGetInstanceSave()

InstanceSave * InstanceSaveMgr::PlayerGetInstanceSave ( ObjectGuid  guid,
uint32  mapid,
Difficulty  difficulty 
)
952{
953 InstancePlayerBind* pBind = PlayerGetBoundInstance(guid, mapid, difficulty);
954 return (pBind ? pBind->save : nullptr);
955}

References PlayerGetBoundInstance(), and InstancePlayerBind::save.

◆ PlayerIsPermBoundToInstance()

bool InstanceSaveMgr::PlayerIsPermBoundToInstance ( ObjectGuid  guid,
uint32  mapid,
Difficulty  difficulty 
)
930{
931 if (InstancePlayerBind* bind = PlayerGetBoundInstance(guid, mapid, difficulty))
932 if (bind->perm)
933 return true;
934 return false;
935}

References PlayerGetBoundInstance().

◆ PlayerUnbindInstance()

void InstanceSaveMgr::PlayerUnbindInstance ( ObjectGuid  guid,
uint32  mapid,
Difficulty  difficulty,
bool  deleteFromDB,
Player player = nullptr 
)
865{
867 BoundInstancesMap::iterator itr = w->m[difficulty].find(mapid);
868 if (itr != w->m[difficulty].end())
869 {
870 if (deleteFromDB)
871 {
873 stmt->SetData(0, guid.GetCounter());
874 stmt->SetData(1, itr->second.save->GetInstanceId());
875 CharacterDatabase.Execute(stmt);
876 }
877
878 if (itr->second.perm && player)
879 player->GetSession()->SendCalendarRaidLockout(itr->second.save, false);
880
881 InstanceSave* tmp = itr->second.save;
882 w->m[difficulty].erase(itr);
883 tmp->RemovePlayer(guid, this);
884 }
885}

References CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID, CharacterDatabase, ObjectGuid::GetCounter(), Player::GetSession(), BoundInstancesMapWrapper::m, playerBindStorage, InstanceSave::RemovePlayer(), WorldSession::SendCalendarRaidLockout(), and PreparedStatementBase::SetData().

Referenced by MergeWithNewInstanceSaves(), and UnbindAllFor().

◆ PlayerUnbindInstanceNotExtended()

void InstanceSaveMgr::PlayerUnbindInstanceNotExtended ( ObjectGuid  guid,
uint32  mapid,
Difficulty  difficulty,
Player player = nullptr 
)
888{
890 BoundInstancesMap::iterator itr = w->m[difficulty].find(mapid);
891 if (itr != w->m[difficulty].end())
892 {
893 if (itr->second.extended)
894 itr->second.extended = false;
895 else
896 {
897 if (itr->second.perm && player)
898 player->GetSession()->SendCalendarRaidLockout(itr->second.save, false);
899
900 InstanceSave* tmp = itr->second.save;
901 w->m[difficulty].erase(itr);
902 tmp->RemovePlayer(guid, this);
903 }
904 }
905}

References Player::GetSession(), BoundInstancesMapWrapper::m, playerBindStorage, InstanceSave::RemovePlayer(), and WorldSession::SendCalendarRaidLockout().

Referenced by _ResetSave().

◆ SanitizeInstanceSavedData()

void InstanceSaveMgr::SanitizeInstanceSavedData ( )
249{
251 CharacterDatabase.Execute(stmt);
252}
@ CHAR_SANITIZE_INSTANCE_SAVED_DATA
Definition CharacterDatabase.h:543

References CHAR_SANITIZE_INSTANCE_SAVED_DATA, and CharacterDatabase.

Referenced by LoadInstances().

◆ ScheduleReset()

void InstanceSaveMgr::ScheduleReset ( time_t  time,
InstResetEvent  event 
)
613{
614 m_resetTimeQueue.insert(std::pair<time_t, InstResetEvent>(time, event));
615}
ResetTimeQueue m_resetTimeQueue
Definition InstanceSaveMgr.h:230

References m_resetTimeQueue.

Referenced by _ResetOrWarnAll(), LoadResetTimes(), and Update().

◆ SetExtendedResetTimeFor()

void InstanceSaveMgr::SetExtendedResetTimeFor ( uint32  mapid,
Difficulty  d,
time_t  t 
)
inline

◆ SetResetTimeFor()

void InstanceSaveMgr::SetResetTimeFor ( uint32  mapid,
Difficulty  d,
time_t  t 
)
inline
180 {
182 }

References m_resetTimeByMapDifficulty, and MAKE_PAIR32().

Referenced by _ResetOrWarnAll(), and LoadResetTimes().

◆ UnbindAllFor()

void InstanceSaveMgr::UnbindAllFor ( InstanceSave save)
989{
990 uint32 mapId = save->GetMapId();
991 Difficulty difficulty = save->GetDifficulty();
992 GuidList players = save->m_playerList;
993
994 for (ObjectGuid const& guid : players)
995 {
996 PlayerUnbindInstance(guid, mapId, difficulty, true, ObjectAccessor::FindConnectedPlayer(guid));
997 }
998}

References ObjectAccessor::FindConnectedPlayer(), InstanceSave::GetDifficulty(), InstanceSave::GetMapId(), InstanceSave::m_playerList, and PlayerUnbindInstance().

◆ Update()

void InstanceSaveMgr::Update ( )
618{
619 time_t now = GameTime::GetGameTime().count();
620 time_t t;
621 bool resetOccurred = false;
622
623 while (!m_resetTimeQueue.empty())
624 {
625 t = m_resetTimeQueue.begin()->first;
626 if (t >= now)
627 break;
628
629 InstResetEvent& event = m_resetTimeQueue.begin()->second;
630 if (event.type)
631 {
632 // global reset/warning for a certain map
633 time_t resetTime = GetResetTimeFor(event.mapid, event.difficulty);
634 bool warn = event.type < 5;
635 _ResetOrWarnAll(event.mapid, event.difficulty, warn, resetTime);
636 if (warn)
637 {
638 // schedule the next warning/reset
639 ++event.type;
640 ScheduleReset(resetTime - ResetTimeDelay[event.type - 1], event);
641 }
642 else
643 resetOccurred = true;
644 }
645 m_resetTimeQueue.erase(m_resetTimeQueue.begin());
646 }
647
648 // pussywizard: send updated calendar and raid info
649 if (resetOccurred)
650 {
651 LOG_INFO("instance.save", "Instance ID reset occurred, sending updated calendar and raid info to all players!");
652 WorldPacket dummy;
653
654 WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions();
655 for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr)
656 if (Player* plr = itr->second->GetPlayer())
657 {
658 itr->second->HandleCalendarGetCalendar(dummy);
659 plr->SendRaidInfo();
660 }
661 }
662}
#define sWorldSessionMgr
Definition WorldSessionMgr.h:118
void _ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, time_t resetTime)
Definition InstanceSaveMgr.cpp:716
Definition Player.h:1086
Definition WorldPacket.h:26
std::unordered_map< uint32, WorldSession * > SessionMap
Definition WorldSessionMgr.h:64

References _ResetOrWarnAll(), GameTime::GetGameTime(), GetResetTimeFor(), LOG_INFO, m_resetTimeQueue, ResetTimeDelay, ScheduleReset(), and sWorldSessionMgr.

Friends And Related Symbol Documentation

◆ InstanceSave

friend class InstanceSave
friend

Member Data Documentation

◆ emptyBoundInstancesMap

BoundInstancesMap InstanceSaveMgr::emptyBoundInstancesMap
staticprotected

Referenced by PlayerGetBoundInstances().

◆ lock_instLists

bool InstanceSaveMgr::lock_instLists {false}
private

◆ m_instanceSaveById

◆ m_resetExtendedTimeByMapDifficulty

ResetTimeByMapDifficultyMap InstanceSaveMgr::m_resetExtendedTimeByMapDifficulty
private

◆ m_resetTimeByMapDifficulty

ResetTimeByMapDifficultyMap InstanceSaveMgr::m_resetTimeByMapDifficulty
private

◆ m_resetTimeQueue

ResetTimeQueue InstanceSaveMgr::m_resetTimeQueue
private

Referenced by ScheduleReset(), and Update().

◆ playerBindStorage

◆ ResetTimeDelay

uint16 InstanceSaveMgr::ResetTimeDelay = {3600, 900, 300, 60, 0}
staticprotected

Referenced by LoadResetTimes(), and Update().


The documentation for this class was generated from the following files: