TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
InstanceSaveManager Class Reference

#include <InstanceSaveMgr.h>

Classes

struct  InstResetEvent
 

Public Types

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

Public Member Functions

void Unload ()
 
void LoadInstances ()
 
void LoadResetTimes ()
 
time_t GetResetTimeFor (uint32 mapid, Difficulty d) const
 
time_t GetSubsequentResetTime (uint32 mapid, Difficulty difficulty, time_t resetTime) const
 
void InitializeResetTimeFor (uint32 mapid, Difficulty d, time_t t)
 
void SetResetTimeFor (uint32 mapid, Difficulty d, time_t t)
 
ResetTimeByMapDifficultyMap const & GetResetTimeMap () const
 
void ScheduleReset (bool add, time_t time, InstResetEvent event)
 
void ForceGlobalReset (uint32 mapId, Difficulty difficulty)
 
void Update ()
 
InstanceSave * AddInstanceSave (uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load=false)
 
void RemoveInstanceSave (uint32 InstanceId)
 
void UnloadInstanceSave (uint32 InstanceId)
 
InstanceSave * GetInstanceSave (uint32 InstanceId)
 
uint32 GetNumInstanceSaves () const
 
uint32 GetNumBoundPlayersTotal () const
 
uint32 GetNumBoundGroupsTotal () const
 

Static Public Member Functions

static InstanceSaveManager * instance ()
 
static void DeleteInstanceFromDB (uint32 instanceid)
 

Static Protected Attributes

static uint16 ResetTimeDelay [] = {3600, 900, 300, 60}
 

Private Member Functions

 InstanceSaveManager ()
 
 ~InstanceSaveManager ()
 
void _ResetOrWarnAll (uint32 mapid, Difficulty difficulty, bool warn, time_t resetTime)
 
void _ResetInstance (uint32 mapid, uint32 instanceId)
 
void _ResetSave (InstanceSaveHashMap::iterator &itr)
 

Private Attributes

bool lock_instLists
 
InstanceSaveHashMap m_instanceSaveById
 
ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty
 
ResetTimeQueue m_resetTimeQueue
 

Friends

class InstanceSave
 

Member Typedef Documentation

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

Constructor & Destructor Documentation

InstanceSaveManager::InstanceSaveManager ( )
inlineprivate
155 : lock_instLists(false) { };
bool lock_instLists
Definition: InstanceSaveMgr.h:235
InstanceSaveManager::~InstanceSaveManager ( )
private
38 {
39 }

Member Function Documentation

void InstanceSaveManager::_ResetInstance ( uint32  mapid,
uint32  instanceId 
)
private
595 {
596  TC_LOG_DEBUG("maps", "InstanceSaveMgr::_ResetInstance %u, %u", mapid, instanceId);
597  Map const* map = sMapMgr->CreateBaseMap(mapid);
598  if (!map->Instanceable())
599  return;
600 
601  InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(instanceId);
602  if (itr != m_instanceSaveById.end())
603  _ResetSave(itr);
604 
605  DeleteInstanceFromDB(instanceId); // even if save not loaded
606 
607  Map* iMap = ((MapInstanced*)map)->FindInstanceMap(instanceId);
608 
609  if (iMap && iMap->IsDungeon())
610  ((InstanceMap*)iMap)->Reset(INSTANCE_RESET_RESPAWN_DELAY);
611 
612  if (iMap)
613  {
614  iMap->DeleteRespawnTimes();
615  iMap->DeleteCorpseData();
616  }
617  else
618  Map::DeleteRespawnTimesInDB(mapid, instanceId);
619 
620  // Free up the instance id and allow it to be reused
621  sMapMgr->FreeInstanceId(instanceId);
622 }
Definition: MapInstanced.h:28
bool IsDungeon() const
Definition: Map.h:395
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:198
void _ResetSave(InstanceSaveHashMap::iterator &itr)
Definition: InstanceSaveMgr.cpp:547
Definition: Map.h:758
InstanceSaveHashMap m_instanceSaveById
Definition: InstanceSaveMgr.h:237
static void DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId)
Definition: Map.cpp:3671
void DeleteRespawnTimes()
Definition: Map.cpp:3663
Definition: Map.h:259
#define sMapMgr
Definition: MapManager.h:194
bool Instanceable() const
Definition: Map.h:394
Definition: Map.h:755
void DeleteCorpseData()
Definition: Map.cpp:3760
static void DeleteInstanceFromDB(uint32 instanceid)
Definition: InstanceSaveMgr.cpp:129

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void InstanceSaveManager::_ResetOrWarnAll ( uint32  mapid,
Difficulty  difficulty,
bool  warn,
time_t  resetTime 
)
private
Todo:
delete creature/gameobject respawn times even if the maps are not loaded
625 {
626  // global reset for all instances of the given map
627  MapEntry const* mapEntry = sMapStore.LookupEntry(mapid);
628  if (!mapEntry->Instanceable())
629  return;
630  TC_LOG_DEBUG("misc", "InstanceSaveManager::ResetOrWarnAll: Processing map %s (%u) on difficulty %u (warn? %u)", mapEntry->MapName_lang, mapid, uint8(difficulty), warn);
631 
632  time_t now = time(NULL);
633 
634  if (!warn)
635  {
636  // calculate the next reset time
637  time_t next_reset = GetSubsequentResetTime(mapid, difficulty, resetTime);
638  if (!next_reset)
639  return;
640 
641  // delete/promote instance binds from the DB, even if not loaded
643 
645  stmt->setUInt16(0, uint16(mapid));
646  stmt->setUInt8(1, uint8(difficulty));
647  trans->Append(stmt);
648 
650  stmt->setUInt16(0, uint16(mapid));
651  stmt->setUInt8(1, uint8(difficulty));
652  trans->Append(stmt);
653 
655  stmt->setUInt16(0, uint16(mapid));
656  stmt->setUInt8(1, uint8(difficulty));
657  trans->Append(stmt);
658 
660  stmt->setUInt16(0, uint16(mapid));
661  stmt->setUInt8(1, uint8(difficulty));
662  trans->Append(stmt);
663 
665 
666  // promote loaded binds to instances of the given map
667  for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();)
668  {
669  if (itr->second->GetMapId() == mapid && itr->second->GetDifficultyID() == difficulty)
670  _ResetSave(itr);
671  else
672  ++itr;
673  }
674 
675  SetResetTimeFor(mapid, difficulty, next_reset);
676  ScheduleReset(true, time_t(next_reset-3600), InstResetEvent(1, mapid, difficulty, 0));
677 
678  // Update it in the DB
680 
681  stmt->setUInt32(0, next_reset);
682  stmt->setUInt16(1, uint16(mapid));
683  stmt->setUInt8(2, uint8(difficulty));
684 
686  }
687 
688  // note: this isn't fast but it's meant to be executed very rarely
689  Map const* map = sMapMgr->CreateBaseMap(mapid); // _not_ include difficulty
690  MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps();
691  MapInstanced::InstancedMaps::iterator mitr;
692  uint32 timeLeft;
693 
694  for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr)
695  {
696  Map* map2 = mitr->second;
697  if (!map2->IsDungeon())
698  continue;
699 
700  if (warn)
701  {
702  if (now >= resetTime)
703  timeLeft = 0;
704  else
705  timeLeft = uint32(resetTime - now);
706 
707  ((InstanceMap*)map2)->SendResetWarnings(timeLeft);
708  }
709  else
710  ((InstanceMap*)map2)->Reset(INSTANCE_RESET_GLOBAL);
711  }
712 
714 }
Definition: MapInstanced.h:28
void Execute(const char *sql)
Definition: DatabaseWorkerPool.h:87
void ScheduleReset(bool add, time_t time, InstResetEvent event)
Definition: InstanceSaveMgr.cpp:465
Definition: Map.h:752
Definition: CharacterDatabase.h:355
bool Instanceable() const
Definition: DBCStructure.h:859
void setUInt8(const uint8 index, const uint8 value)
Definition: PreparedStatement.cpp:97
SQLTransaction BeginTransaction()
Begins an automanaged transaction pointer that will automatically rollback if not commited...
Definition: DatabaseWorkerPool.h:221
Definition: DBCStructure.h:830
arena_t NULL
Definition: jemalloc_internal.h:624
bool IsDungeon() const
Definition: Map.h:395
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:198
void _ResetSave(InstanceSaveHashMap::iterator &itr)
Definition: InstanceSaveMgr.cpp:547
time_t GetSubsequentResetTime(uint32 mapid, Difficulty difficulty, time_t resetTime) const
Definition: InstanceSaveMgr.cpp:448
uint16_t uint16
Definition: g3dmath.h:166
Definition: PreparedStatement.h:74
std::unordered_map< uint32, Map * > InstancedMaps
Definition: MapInstanced.h:32
void CommitTransaction(SQLTransaction transaction)
Definition: DatabaseWorkerPool.cpp:179
void SetResetTimeFor(uint32 mapid, Difficulty d, time_t t)
Definition: InstanceSaveMgr.h:198
Definition: Map.h:758
InstanceSaveHashMap m_instanceSaveById
Definition: InstanceSaveMgr.h:237
void setUInt16(const uint8 index, const uint16 value)
Definition: PreparedStatement.cpp:106
uint32_t uint32
Definition: Define.h:150
Definition: CharacterDatabase.h:421
PreparedStatement * GetPreparedStatement(PreparedStatementIndex index)
Definition: DatabaseWorkerPool.h:263
Definition: Map.h:259
void setUInt32(const uint8 index, const uint32 value)
Definition: PreparedStatement.cpp:115
uint8_t uint8
Definition: g3dmath.h:164
Definition: CharacterDatabase.h:424
DBCStorage< MapEntry > sMapStore(Mapfmt)
#define sMapMgr
Definition: MapManager.h:194
uint8_t uint8
Definition: Define.h:152
Definition: CharacterDatabase.h:423
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
char * MapName_lang
Definition: DBCStructure.h:838
uint32_t uint32
Definition: g3dmath.h:168
Definition: CharacterDatabase.h:422
std::shared_ptr< Transaction > SQLTransaction
Definition: Transaction.h:58

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void InstanceSaveManager::_ResetSave ( InstanceSaveHashMap::iterator &  itr)
private
548 {
549  // unbind all players bound to the instance
550  // do not allow UnbindInstance to automatically unload the InstanceSaves
551  lock_instLists = true;
552 
553  bool shouldDelete = true;
554  InstanceSave::PlayerListType &pList = itr->second->m_playerList;
555  std::vector<Player*> temp; // list of expired binds that should be unbound
556  for (Player* player : pList)
557  {
558  if (InstancePlayerBind* bind = player->GetBoundInstance(itr->second->GetMapId(), itr->second->GetDifficultyID()))
559  {
560  ASSERT(bind->save == itr->second);
561  if (bind->perm && bind->extendState) // permanent and not already expired
562  {
563  // actual promotion in DB already happened in caller
564  bind->extendState = bind->extendState == EXTEND_STATE_EXTENDED ? EXTEND_STATE_NORMAL : EXTEND_STATE_EXPIRED;
565  shouldDelete = false;
566  continue;
567  }
568  }
569  temp.push_back(player);
570  }
571  for (Player* player : temp)
572  {
573  player->UnbindInstance(itr->second->GetMapId(), itr->second->GetDifficultyID(), true);
574  }
575 
576  InstanceSave::GroupListType &gList = itr->second->m_groupList;
577  while (!gList.empty())
578  {
579  Group* group = *(gList.begin());
580  group->UnbindInstance(itr->second->GetMapId(), itr->second->GetDifficultyID(), true);
581  }
582 
583  if (shouldDelete)
584  {
585  delete itr->second;
586  itr = m_instanceSaveById.erase(itr);
587  }
588  else
589  ++itr;
590 
591  lock_instLists = false;
592 }
InstanceSaveHashMap m_instanceSaveById
Definition: InstanceSaveMgr.h:237
std::list< Group * > GroupListType
Definition: InstanceSaveMgr.h:130
std::list< Player * > PlayerListType
Definition: InstanceSaveMgr.h:129
void UnbindInstance(uint32 mapid, uint8 difficulty, bool unload=false)
Definition: Group.cpp:2257
bool lock_instLists
Definition: InstanceSaveMgr.h:235
#define ASSERT
Definition: Errors.h:55
Definition: Group.h:191

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

InstanceSave * InstanceSaveManager::AddInstanceSave ( uint32  mapId,
uint32  instanceId,
Difficulty  difficulty,
time_t  resetTime,
bool  canReset,
bool  load = false 
)
75 {
76  if (InstanceSave* old_save = GetInstanceSave(instanceId))
77  return old_save;
78 
79  const MapEntry* entry = sMapStore.LookupEntry(mapId);
80  if (!entry)
81  {
82  TC_LOG_ERROR("misc", "InstanceSaveManager::AddInstanceSave: wrong mapid = %d, instanceid = %d!", mapId, instanceId);
83  return NULL;
84  }
85 
86  if (instanceId == 0)
87  {
88  TC_LOG_ERROR("misc", "InstanceSaveManager::AddInstanceSave: mapid = %d, wrong instanceid = %d!", mapId, instanceId);
89  return NULL;
90  }
91 
92  DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty);
93  if (!difficultyEntry || difficultyEntry->InstanceType != entry->InstanceType)
94  {
95  TC_LOG_ERROR("misc", "InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong dificalty %u!", mapId, instanceId, difficulty);
96  return NULL;
97  }
98 
99  if (!resetTime)
100  {
101  // initialize reset time
102  // for normal instances if no creatures are killed the instance will reset in two hours
103  if (entry->IsRaid() || difficulty > DIFFICULTY_NORMAL)
104  resetTime = GetResetTimeFor(mapId, difficulty);
105  else
106  {
107  resetTime = time(NULL) + 2 * HOUR;
108  // normally this will be removed soon after in InstanceMap::Add, prevent error
109  ScheduleReset(true, resetTime, InstResetEvent(0, mapId, difficulty, instanceId));
110  }
111  }
112 
113  TC_LOG_DEBUG("maps", "InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d", mapId, instanceId);
114 
115  InstanceSave* save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset);
116  if (!load)
117  save->SaveToDB();
118 
119  m_instanceSaveById[instanceId] = save;
120  return save;
121 }
void ScheduleReset(bool add, time_t time, InstResetEvent event)
Definition: InstanceSaveMgr.cpp:465
Definition: Common.h:98
time_t GetResetTimeFor(uint32 mapid, Difficulty d) const
Definition: InstanceSaveMgr.h:184
Definition: DBCStructure.h:830
arena_t NULL
Definition: jemalloc_internal.h:624
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:198
friend class InstanceSave
Definition: InstanceSaveMgr.h:152
void SaveToDB()
Definition: InstanceSaveMgr.cpp:189
uint32 InstanceType
Definition: DBCStructure.h:834
InstanceSaveHashMap m_instanceSaveById
Definition: InstanceSaveMgr.h:237
uint32 InstanceType
Definition: DBCStructure.h:342
Definition: InstanceSaveMgr.h:44
bool IsRaid() const
Definition: DBCStructure.h:860
DBCStorage< MapEntry > sMapStore(Mapfmt)
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:207
InstanceSave * GetInstanceSave(uint32 InstanceId)
Definition: InstanceSaveMgr.cpp:123
DBCStorage< DifficultyEntry > sDifficultyStore(DifficultyFmt)
Definition: DBCEnums.h:405
Definition: DBCStructure.h:338

+ Here is the call graph for this function:

void InstanceSaveManager::DeleteInstanceFromDB ( uint32  instanceid)
static
130 {
132 
134  stmt->setUInt32(0, instanceid);
135  trans->Append(stmt);
136 
138  stmt->setUInt32(0, instanceid);
139  trans->Append(stmt);
140 
142  stmt->setUInt32(0, instanceid);
143  trans->Append(stmt);
144 
146  // Respawn times should be deleted only when the map gets unloaded
147 }
Definition: CharacterDatabase.h:419
Definition: CharacterDatabase.h:420
SQLTransaction BeginTransaction()
Begins an automanaged transaction pointer that will automatically rollback if not commited...
Definition: DatabaseWorkerPool.h:221
Definition: PreparedStatement.h:74
void CommitTransaction(SQLTransaction transaction)
Definition: DatabaseWorkerPool.cpp:179
Definition: CharacterDatabase.h:351
PreparedStatement * GetPreparedStatement(PreparedStatementIndex index)
Definition: DatabaseWorkerPool.h:263
void setUInt32(const uint8 index, const uint32 value)
Definition: PreparedStatement.cpp:115
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
std::shared_ptr< Transaction > SQLTransaction
Definition: Transaction.h:58

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void InstanceSaveManager::ForceGlobalReset ( uint32  mapId,
Difficulty  difficulty 
)
503 {
504  if (!GetDownscaledMapDifficultyData(mapId, difficulty))
505  return;
506  // remove currently scheduled reset times
507  ScheduleReset(false, 0, InstResetEvent(1, mapId, difficulty, 0));
508  ScheduleReset(false, 0, InstResetEvent(4, mapId, difficulty, 0));
509  // force global reset on the instance
510  _ResetOrWarnAll(mapId, difficulty, false, time(nullptr));
511 }
void ScheduleReset(bool add, time_t time, InstResetEvent event)
Definition: InstanceSaveMgr.cpp:465
MapDifficultyEntry const * GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty)
Definition: DBCStores.cpp:737
void _ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, time_t resetTime)
Definition: InstanceSaveMgr.cpp:624

+ Here is the call graph for this function:

InstanceSave * InstanceSaveManager::GetInstanceSave ( uint32  InstanceId)
124 {
125  InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(InstanceId);
126  return itr != m_instanceSaveById.end() ? itr->second : NULL;
127 }
arena_t NULL
Definition: jemalloc_internal.h:624
InstanceSaveHashMap m_instanceSaveById
Definition: InstanceSaveMgr.h:237

+ Here is the caller graph for this function:

uint32 InstanceSaveManager::GetNumBoundGroupsTotal ( ) const
726 {
727  uint32 ret = 0;
728  for (InstanceSaveHashMap::const_iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr)
729  ret += itr->second->GetGroupCount();
730 
731  return ret;
732 }
InstanceSaveHashMap m_instanceSaveById
Definition: InstanceSaveMgr.h:237
uint32_t uint32
Definition: Define.h:150
uint32 InstanceSaveManager::GetNumBoundPlayersTotal ( ) const
717 {
718  uint32 ret = 0;
719  for (InstanceSaveHashMap::const_iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr)
720  ret += itr->second->GetPlayerCount();
721 
722  return ret;
723 }
InstanceSaveHashMap m_instanceSaveById
Definition: InstanceSaveMgr.h:237
uint32_t uint32
Definition: Define.h:150
uint32 InstanceSaveManager::GetNumInstanceSaves ( ) const
inline
223 { return uint32(m_instanceSaveById.size()); }
InstanceSaveHashMap m_instanceSaveById
Definition: InstanceSaveMgr.h:237
uint32_t uint32
Definition: g3dmath.h:168
time_t InstanceSaveManager::GetResetTimeFor ( uint32  mapid,
Difficulty  d 
) const
inline
185  {
186  ResetTimeByMapDifficultyMap::const_iterator itr = m_resetTimeByMapDifficulty.find(MAKE_PAIR64(mapid, d));
187  return itr != m_resetTimeByMapDifficulty.end() ? itr->second : 0;
188  }
ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty
Definition: InstanceSaveMgr.h:239
uint64 MAKE_PAIR64(uint32 l, uint32 h)
Definition: ObjectDefines.h:34

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ResetTimeByMapDifficultyMap const& InstanceSaveManager::GetResetTimeMap ( ) const
inline
206  {
208  }
ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty
Definition: InstanceSaveMgr.h:239
time_t InstanceSaveManager::GetSubsequentResetTime ( uint32  mapid,
Difficulty  difficulty,
time_t  resetTime 
) const
449 {
450  MapDifficultyEntry const* mapDiff = GetMapDifficultyData(mapid, difficulty);
451  if (!mapDiff || !mapDiff->RaidDuration)
452  {
453  TC_LOG_ERROR("misc", "InstanceSaveManager::GetSubsequentResetTime: not valid difficulty or no reset delay for map %u", mapid);
454  return 0;
455  }
456 
457  time_t diff = sWorld->getIntConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
458  time_t period = uint32(((mapDiff->RaidDuration * sWorld->getRate(RATE_INSTANCE_RESET_TIME)) / DAY) * DAY);
459  if (period < DAY)
460  period = DAY;
461 
462  return ((resetTime + MINUTE) / DAY * DAY) + period + diff;
463 }
MapDifficultyEntry const * GetMapDifficultyData(uint32 mapId, Difficulty difficulty)
Definition: DBCStores.cpp:724
Definition: World.h:254
Definition: Common.h:98
uint32 RaidDuration
Definition: DBCStructure.h:891
#define sWorld
Definition: World.h:887
Definition: Common.h:97
Definition: Common.h:99
Definition: DBCStructure.h:885
Definition: World.h:438
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:207
uint32_t uint32
Definition: g3dmath.h:168

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void InstanceSaveManager::InitializeResetTimeFor ( uint32  mapid,
Difficulty  d,
time_t  t 
)
inline
193  {
195  }
ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty
Definition: InstanceSaveMgr.h:239
uint64 MAKE_PAIR64(uint32 l, uint32 h)
Definition: ObjectDefines.h:34

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

InstanceSaveManager * InstanceSaveManager::instance ( )
static
42 {
44  return &instance;
45 }
static InstanceSaveManager * instance()
Definition: InstanceSaveMgr.cpp:41
Definition: InstanceSaveMgr.h:150

+ Here is the caller graph for this function:

void InstanceSaveManager::LoadInstances ( )
262 {
263  uint32 oldMSTime = getMSTime();
264 
265  // Delete expired instances (Instance related spawns are removed in the following cleanup queries)
266  CharacterDatabase.DirectExecute("DELETE i FROM instance i LEFT JOIN instance_reset ir ON mapid = map AND i.difficulty = ir.difficulty "
267  "WHERE (i.resettime > 0 AND i.resettime < UNIX_TIMESTAMP()) OR (ir.resettime IS NOT NULL AND ir.resettime < UNIX_TIMESTAMP())");
268 
269  // Delete invalid character_instance and group_instance references
270  CharacterDatabase.DirectExecute("DELETE ci.* FROM character_instance AS ci LEFT JOIN characters AS c ON ci.guid = c.guid WHERE c.guid IS NULL");
271  CharacterDatabase.DirectExecute("DELETE gi.* FROM group_instance AS gi LEFT JOIN groups AS g ON gi.guid = g.guid WHERE g.guid IS NULL");
272 
273  // Delete invalid instance references
274  CharacterDatabase.DirectExecute("DELETE i.* FROM instance AS i LEFT JOIN character_instance AS ci ON i.id = ci.instance LEFT JOIN group_instance AS gi ON i.id = gi.instance WHERE ci.guid IS NULL AND gi.guid IS NULL");
275 
276  // Delete invalid references to instance
277  CharacterDatabase.DirectExecute("DELETE FROM creature_respawn WHERE instanceId > 0 AND instanceId NOT IN (SELECT id FROM instance)");
278  CharacterDatabase.DirectExecute("DELETE FROM gameobject_respawn WHERE instanceId > 0 AND instanceId NOT IN (SELECT id FROM instance)");
279  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");
280  CharacterDatabase.DirectExecute("DELETE tmp.* FROM group_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
290  sInstanceSaveMgr->LoadResetTimes();
291 
292  TC_LOG_INFO("server.loading", ">> Loaded instances in %u ms", GetMSTimeDiffToNow(oldMSTime));
293 
294 }
uint32 getMSTime()
Definition: Timer.h:24
uint32_t uint32
Definition: Define.h:150
#define sInstanceSaveMgr
Definition: InstanceSaveMgr.h:243
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition: Timer.h:42
#define sMapMgr
Definition: MapManager.h:194
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:201
void DirectExecute(const char *sql)
Definition: DatabaseWorkerPool.h:121

+ Here is the call graph for this function:

void InstanceSaveManager::LoadResetTimes ( )
297 {
298  time_t now = time(NULL);
299  time_t today = (now / DAY) * DAY;
300 
301  // NOTE: Use DirectPExecute for tables that will be queried later
302 
303  // get the current reset times for normal instances (these may need to be updated)
304  // these are only kept in memory for InstanceSaves that are loaded later
305  // resettime = 0 in the DB for raid/heroic instances so those are skipped
306  typedef std::pair<uint32 /*PAIR32(map, difficulty)*/, time_t> ResetTimeMapDiffType;
307  typedef std::map<uint32, ResetTimeMapDiffType> InstResetTimeMapDiffType;
308  InstResetTimeMapDiffType instResetTime;
309 
310  // index instance ids by map/difficulty pairs for fast reset warning send
311  typedef std::multimap<uint32 /*PAIR32(map, difficulty)*/, uint32 /*instanceid*/ > ResetTimeMapDiffInstances;
312  typedef std::pair<ResetTimeMapDiffInstances::const_iterator, ResetTimeMapDiffInstances::const_iterator> ResetTimeMapDiffInstancesBounds;
313  ResetTimeMapDiffInstances mapDiffResetInstances;
314 
315  QueryResult result = CharacterDatabase.Query("SELECT id, map, difficulty, resettime FROM instance ORDER BY id ASC");
316  if (result)
317  {
318  do
319  {
320  Field* fields = result->Fetch();
321 
322  uint32 instanceId = fields[0].GetUInt32();
323 
324  // Instances are pulled in ascending order from db and nextInstanceId is initialized with 1,
325  // so if the instance id is used, increment until we find the first unused one for a potential new instance
326  if (sMapMgr->GetNextInstanceId() == instanceId)
327  sMapMgr->SetNextInstanceId(instanceId + 1);
328 
329  // Mark instance id as being used
330  sMapMgr->RegisterInstanceId(instanceId);
331 
332  if (time_t resettime = time_t(fields[3].GetUInt32()))
333  {
334  uint32 mapid = fields[1].GetUInt16();
335  uint32 difficulty = fields[2].GetUInt8();
336 
337  instResetTime[instanceId] = ResetTimeMapDiffType(MAKE_PAIR32(mapid, difficulty), resettime);
338  mapDiffResetInstances.insert(ResetTimeMapDiffInstances::value_type(MAKE_PAIR32(mapid, difficulty), instanceId));
339  }
340  }
341  while (result->NextRow());
342 
343  // update reset time for normal instances with the max creature respawn time + X hours
345  {
346  do
347  {
348  Field* fields = result2->Fetch();
349  uint32 instance = fields[1].GetUInt32();
350  time_t resettime = time_t(fields[0].GetUInt32() + 2 * HOUR);
351  InstResetTimeMapDiffType::iterator itr = instResetTime.find(instance);
352  if (itr != instResetTime.end() && itr->second.second != resettime)
353  {
354  CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '" UI64FMTD "' WHERE id = '%u'", uint64(resettime), instance);
355  itr->second.second = resettime;
356  }
357  }
358  while (result->NextRow());
359  }
360 
361  // schedule the reset times
362  for (InstResetTimeMapDiffType::iterator itr = instResetTime.begin(); itr != instResetTime.end(); ++itr)
363  if (itr->second.second > now)
364  ScheduleReset(true, itr->second.second, InstResetEvent(0, PAIR32_LOPART(itr->second.first), Difficulty(PAIR32_HIPART(itr->second.first)), itr->first));
365  }
366 
367  // load the global respawn times for raid/heroic instances
368  uint32 diff = sWorld->getIntConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
369  result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset");
370  if (result)
371  {
372  do
373  {
374  Field* fields = result->Fetch();
375  uint32 mapid = fields[0].GetUInt16();
376  Difficulty difficulty = Difficulty(fields[1].GetUInt8());
377  uint64 oldresettime = fields[2].GetUInt32();
378 
379  MapDifficultyEntry const* mapDiff = GetMapDifficultyData(mapid, difficulty);
380  if (!mapDiff)
381  {
382  TC_LOG_ERROR("misc", "InstanceSaveManager::LoadResetTimes: invalid mapid(%u)/difficulty(%u) pair in instance_reset!", mapid, difficulty);
383  CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u' AND difficulty = '%u'", mapid, difficulty);
384  continue;
385  }
386 
387  // update the reset time if the hour in the configs changes
388  uint64 newresettime = (oldresettime / DAY) * DAY + diff;
389  if (oldresettime != newresettime)
390  CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '%u' WHERE mapid = '%u' AND difficulty = '%u'", uint32(newresettime), mapid, difficulty);
391 
392  InitializeResetTimeFor(mapid, difficulty, newresettime);
393  } while (result->NextRow());
394  }
395 
396  // calculate new global reset times for expired instances and those that have never been reset yet
397  // add the global reset times to the priority queue
398  for (auto& mapDifficultyPair : sMapDifficultyMap)
399  {
400  uint32 mapid = mapDifficultyPair.first;
401 
402  for (auto& difficultyPair : mapDifficultyPair.second)
403  {
404  Difficulty difficulty = Difficulty(difficultyPair.first);
405  MapDifficultyEntry const* mapDiff = difficultyPair.second;
406  if (!mapDiff->RaidDuration)
407  continue;
408 
409  // the reset_delay must be at least one day
410  uint32 period = uint32(((mapDiff->RaidDuration * sWorld->getRate(RATE_INSTANCE_RESET_TIME)) / DAY) * DAY);
411  if (period < DAY)
412  period = DAY;
413 
414  time_t t = GetResetTimeFor(mapid, difficulty);
415  if (!t)
416  {
417  // initialize the reset time
418  t = today + period + diff;
419  CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u', '%u', '%u')", mapid, difficulty, (uint32)t);
420  }
421 
422  if (t < now)
423  {
424  // assume that expired instances have already been cleaned
425  // calculate the next reset time
426  t = (t / DAY) * DAY;
427  t += ((today - t) / period + 1) * period + diff;
428  CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '" UI64FMTD "' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty);
429  }
430 
431  InitializeResetTimeFor(mapid, difficulty, t);
432 
433  // schedule the global reset/warning
434  uint8 type;
435  for (type = 1; type < 4; ++type)
436  if (t - ResetTimeDelay[type - 1] > now)
437  break;
438 
439  ScheduleReset(true, t - ResetTimeDelay[type - 1], InstResetEvent(type, mapid, difficulty, 0));
440 
441  ResetTimeMapDiffInstancesBounds range = mapDiffResetInstances.equal_range(MAKE_PAIR32(mapid, difficulty));
442  for (; range.first != range.second; ++range.first)
443  ScheduleReset(true, t - ResetTimeDelay[type - 1], InstResetEvent(type, mapid, difficulty, range.first->second));
444  }
445  }
446 }
Difficulty
Definition: DBCEnums.h:402
MapDifficultyEntry const * GetMapDifficultyData(uint32 mapId, Difficulty difficulty)
Definition: DBCStores.cpp:724
std::shared_ptr< PreparedResultSet > PreparedQueryResult
Definition: QueryResult.h:107
void ScheduleReset(bool add, time_t time, InstResetEvent event)
Definition: InstanceSaveMgr.cpp:465
Definition: World.h:254
Definition: Common.h:98
MapDifficultyMap sMapDifficultyMap
Definition: DBCStores.cpp:115
Class used to access individual fields of database query result.
Definition: Field.h:56
time_t GetResetTimeFor(uint32 mapid, Difficulty d) const
Definition: InstanceSaveMgr.h:184
static InstanceSaveManager * instance()
Definition: InstanceSaveMgr.cpp:41
arena_t NULL
Definition: jemalloc_internal.h:624
uint32 RaidDuration
Definition: DBCStructure.h:891
uint64_t uint64
Definition: g3dmath.h:170
#define sWorld
Definition: World.h:887
uint8 GetUInt8() const
Definition: Field.h:70
void DirectPExecute(Format &&sql, Args &&...args)
Definition: DatabaseWorkerPool.h:134
uint16 PAIR32_LOPART(uint32 x)
Definition: ObjectDefines.h:64
Definition: Common.h:99
#define UI64FMTD
Definition: Define.h:137
Definition: CharacterDatabase.h:293
uint32_t uint32
Definition: Define.h:150
uint64_t uint64
Definition: Define.h:149
std::shared_ptr< ResultSet > QueryResult
Definition: QueryResult.h:61
uint16 GetUInt16() const
Definition: Field.h:108
PreparedStatement * GetPreparedStatement(PreparedStatementIndex index)
Definition: DatabaseWorkerPool.h:263
QueryResult Query(const char *sql, T *connection=nullptr)
Definition: DatabaseWorkerPool.cpp:113
Definition: DBCStructure.h:885
void InitializeResetTimeFor(uint32 mapid, Difficulty d, time_t t)
Definition: InstanceSaveMgr.h:192
Definition: World.h:438
#define sMapMgr
Definition: MapManager.h:194
uint32 GetUInt32() const
Definition: Field.h:146
uint8_t uint8
Definition: Define.h:152
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:207
uint32_t uint32
Definition: g3dmath.h:168
uint16 PAIR32_HIPART(uint32 x)
Definition: ObjectDefines.h:59
uint32 MAKE_PAIR32(uint16 l, uint16 h)
Definition: ObjectDefines.h:54
static uint16 ResetTimeDelay[]
Definition: InstanceSaveMgr.h:228

+ Here is the call graph for this function:

void InstanceSaveManager::RemoveInstanceSave ( uint32  InstanceId)
150 {
151  InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(InstanceId);
152  if (itr != m_instanceSaveById.end())
153  {
154  // save the resettime for normal instances only when they get unloaded
155  if (time_t resettime = itr->second->GetResetTimeForDB())
156  {
158 
159  stmt->setUInt32(0, uint32(resettime));
160  stmt->setUInt32(1, InstanceId);
161 
163  }
164 
165  itr->second->SetToDelete(true);
166  m_instanceSaveById.erase(itr);
167  }
168 }
void Execute(const char *sql)
Definition: DatabaseWorkerPool.h:87
Definition: PreparedStatement.h:74
Definition: CharacterDatabase.h:354
InstanceSaveHashMap m_instanceSaveById
Definition: InstanceSaveMgr.h:237
PreparedStatement * GetPreparedStatement(PreparedStatementIndex index)
Definition: DatabaseWorkerPool.h:263
void setUInt32(const uint8 index, const uint32 value)
Definition: PreparedStatement.cpp:115
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint32_t uint32
Definition: g3dmath.h:168

+ Here is the call graph for this function:

void InstanceSaveManager::ScheduleReset ( bool  add,
time_t  time,
InstResetEvent  event 
)
466 {
467  if (!add)
468  {
469  // find the event in the queue and remove it
470  ResetTimeQueue::iterator itr;
471  std::pair<ResetTimeQueue::iterator, ResetTimeQueue::iterator> range;
472  range = m_resetTimeQueue.equal_range(time);
473  for (itr = range.first; itr != range.second; ++itr)
474  {
475  if (itr->second == event)
476  {
477  m_resetTimeQueue.erase(itr);
478  return;
479  }
480  }
481 
482  // in case the reset time changed (should happen very rarely), we search the whole queue
483  if (itr == range.second)
484  {
485  for (itr = m_resetTimeQueue.begin(); itr != m_resetTimeQueue.end(); ++itr)
486  {
487  if (itr->second == event)
488  {
489  m_resetTimeQueue.erase(itr);
490  return;
491  }
492  }
493 
494  if (itr == m_resetTimeQueue.end())
495  TC_LOG_ERROR("misc", "InstanceSaveManager::ScheduleReset: cannot cancel the reset, the event(%d, %d, %d) was not found!", event.type, event.mapid, event.instanceId);
496  }
497  }
498  else
499  m_resetTimeQueue.insert(std::pair<time_t, InstResetEvent>(time, event));
500 }
ResetTimeQueue m_resetTimeQueue
Definition: InstanceSaveMgr.h:240
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:207

+ Here is the caller graph for this function:

void InstanceSaveManager::SetResetTimeFor ( uint32  mapid,
Difficulty  d,
time_t  t 
)
inline
199  {
200  ResetTimeByMapDifficultyMap::iterator itr = m_resetTimeByMapDifficulty.find(MAKE_PAIR64(mapid, d));
201  ASSERT(itr != m_resetTimeByMapDifficulty.end());
202  itr->second = t;
203  }
ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty
Definition: InstanceSaveMgr.h:239
uint64 MAKE_PAIR64(uint32 l, uint32 h)
Definition: ObjectDefines.h:34
#define ASSERT
Definition: Errors.h:55

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void InstanceSaveManager::Unload ( )
48 {
49  lock_instLists = true;
50  for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr)
51  {
52  InstanceSave* save = itr->second;
53 
54  for (InstanceSave::PlayerListType::iterator itr2 = save->m_playerList.begin(), next = itr2; itr2 != save->m_playerList.end(); itr2 = next)
55  {
56  ++next;
57  (*itr2)->UnbindInstance(save->GetMapId(), save->GetDifficultyID(), true);
58  }
59 
60  for (InstanceSave::GroupListType::iterator itr2 = save->m_groupList.begin(), next = itr2; itr2 != save->m_groupList.end(); itr2 = next)
61  {
62  ++next;
63  (*itr2)->UnbindInstance(save->GetMapId(), save->GetDifficultyID(), true);
64  }
65 
66  delete save;
67  }
68 }
PlayerListType m_playerList
Definition: InstanceSaveMgr.h:136
int next(int i, int n)
Definition: RecastContour.cpp:469
InstanceSaveHashMap m_instanceSaveById
Definition: InstanceSaveMgr.h:237
Definition: InstanceSaveMgr.h:44
uint32 GetMapId() const
Definition: InstanceSaveMgr.h:65
Difficulty GetDifficultyID() const
Definition: InstanceSaveMgr.h:121
bool lock_instLists
Definition: InstanceSaveMgr.h:235
GroupListType m_groupList
Definition: InstanceSaveMgr.h:137

+ Here is the call graph for this function:

void InstanceSaveManager::UnloadInstanceSave ( uint32  InstanceId)
171 {
172  if (InstanceSave* save = GetInstanceSave(InstanceId))
173  save->UnloadIfEmpty();
174 }
Definition: InstanceSaveMgr.h:44
InstanceSave * GetInstanceSave(uint32 InstanceId)
Definition: InstanceSaveMgr.cpp:123

+ Here is the call graph for this function:

void InstanceSaveManager::Update ( )
514 {
515  time_t now = time(NULL);
516  time_t t;
517 
518  while (!m_resetTimeQueue.empty())
519  {
520  t = m_resetTimeQueue.begin()->first;
521  if (t >= now)
522  break;
523 
524  InstResetEvent &event = m_resetTimeQueue.begin()->second;
525  if (event.type == 0)
526  {
527  // for individual normal instances, max creature respawn + X hours
528  _ResetInstance(event.mapid, event.instanceId);
529  m_resetTimeQueue.erase(m_resetTimeQueue.begin());
530  }
531  else
532  {
533  // global reset/warning for a certain map
534  time_t resetTime = GetResetTimeFor(event.mapid, event.difficulty);
535  _ResetOrWarnAll(event.mapid, event.difficulty, event.type != 4, resetTime);
536  if (event.type != 4)
537  {
538  // schedule the next warning/reset
539  ++event.type;
540  ScheduleReset(true, resetTime - ResetTimeDelay[event.type-1], event);
541  }
542  m_resetTimeQueue.erase(m_resetTimeQueue.begin());
543  }
544  }
545 }
void ScheduleReset(bool add, time_t time, InstResetEvent event)
Definition: InstanceSaveMgr.cpp:465
time_t GetResetTimeFor(uint32 mapid, Difficulty d) const
Definition: InstanceSaveMgr.h:184
arena_t NULL
Definition: jemalloc_internal.h:624
ResetTimeQueue m_resetTimeQueue
Definition: InstanceSaveMgr.h:240
void _ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, time_t resetTime)
Definition: InstanceSaveMgr.cpp:624
void _ResetInstance(uint32 mapid, uint32 instanceId)
Definition: InstanceSaveMgr.cpp:594
static uint16 ResetTimeDelay[]
Definition: InstanceSaveMgr.h:228

+ Here is the call graph for this function:

Friends And Related Function Documentation

friend class InstanceSave
friend

Member Data Documentation

bool InstanceSaveManager::lock_instLists
private
InstanceSaveHashMap InstanceSaveManager::m_instanceSaveById
private
ResetTimeByMapDifficultyMap InstanceSaveManager::m_resetTimeByMapDifficulty
private
ResetTimeQueue InstanceSaveManager::m_resetTimeQueue
private
uint16 InstanceSaveManager::ResetTimeDelay = {3600, 900, 300, 60}
staticprotected

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