aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Instances/InstanceSaveMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Instances/InstanceSaveMgr.cpp')
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.cpp102
1 files changed, 73 insertions, 29 deletions
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp
index 9a64335e6f0..3538262ed35 100644
--- a/src/server/game/Instances/InstanceSaveMgr.cpp
+++ b/src/server/game/Instances/InstanceSaveMgr.cpp
@@ -439,6 +439,23 @@ void InstanceSaveManager::LoadResetTimes()
}
}
+time_t InstanceSaveManager::GetSubsequentResetTime(uint32 mapid, Difficulty difficulty, time_t resetTime) const
+{
+ MapDifficulty const* mapDiff = GetMapDifficultyData(mapid, difficulty);
+ if (!mapDiff || !mapDiff->resetTime)
+ {
+ TC_LOG_ERROR("misc", "InstanceSaveManager::GetSubsequentResetTime: not valid difficulty or no reset delay for map %u", mapid);
+ return 0;
+ }
+
+ time_t diff = sWorld->getIntConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
+ time_t period = uint32(((mapDiff->resetTime * sWorld->getRate(RATE_INSTANCE_RESET_TIME)) / DAY) * DAY);
+ if (period < DAY)
+ period = DAY;
+
+ return ((resetTime + MINUTE) / DAY * DAY) + period + diff;
+}
+
void InstanceSaveManager::ScheduleReset(bool add, time_t time, InstResetEvent event)
{
if (!add)
@@ -476,6 +493,17 @@ void InstanceSaveManager::ScheduleReset(bool add, time_t time, InstResetEvent ev
m_resetTimeQueue.insert(std::pair<time_t, InstResetEvent>(time, event));
}
+void InstanceSaveManager::ForceGlobalReset(uint32 mapId, Difficulty difficulty)
+{
+ if (!GetDownscaledMapDifficultyData(mapId, difficulty))
+ return;
+ // remove currently scheduled reset times
+ ScheduleReset(false, 0, InstResetEvent(1, mapId, difficulty, 0));
+ ScheduleReset(false, 0, InstResetEvent(4, mapId, difficulty, 0));
+ // force global reset on the instance
+ _ResetOrWarnAll(mapId, difficulty, false, time(nullptr));
+}
+
void InstanceSaveManager::Update()
{
time_t now = time(NULL);
@@ -516,10 +544,26 @@ void InstanceSaveManager::_ResetSave(InstanceSaveHashMap::iterator &itr)
// do not allow UnbindInstance to automatically unload the InstanceSaves
lock_instLists = true;
+ bool shouldDelete = true;
InstanceSave::PlayerListType &pList = itr->second->m_playerList;
- while (!pList.empty())
+ std::vector<Player*> temp; // list of expired binds that should be unbound
+ for (Player* player : pList)
+ {
+ if (InstancePlayerBind* bind = player->GetBoundInstance(itr->second->GetMapId(), itr->second->GetDifficulty()))
+ {
+ ASSERT(bind->save == itr->second);
+ if (bind->perm && bind->extendState) // permanent and not already expired
+ {
+ // actual promotion in DB already happened in caller
+ bind->extendState = bind->extendState == EXTEND_STATE_EXTENDED ? EXTEND_STATE_NORMAL : EXTEND_STATE_EXPIRED;
+ shouldDelete = false;
+ continue;
+ }
+ }
+ temp.push_back(player);
+ }
+ for (Player* player : temp)
{
- Player* player = *(pList.begin());
player->UnbindInstance(itr->second->GetMapId(), itr->second->GetDifficulty(), true);
}
@@ -530,8 +574,13 @@ void InstanceSaveManager::_ResetSave(InstanceSaveHashMap::iterator &itr)
group->UnbindInstance(itr->second->GetMapId(), itr->second->GetDifficulty(), true);
}
- delete itr->second;
- m_instanceSaveById.erase(itr++);
+ if (shouldDelete)
+ {
+ delete itr->second;
+ itr = m_instanceSaveById.erase(itr);
+ }
+ else
+ ++itr;
lock_instLists = false;
}
@@ -572,31 +621,21 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b
MapEntry const* mapEntry = sMapStore.LookupEntry(mapid);
if (!mapEntry->Instanceable())
return;
+ TC_LOG_DEBUG("misc", "InstanceSaveManager::ResetOrWarnAll: Processing map %s (%u) on difficulty %u (warn? %u)", mapEntry->name[0], mapid, uint8(difficulty), warn);
time_t now = time(NULL);
if (!warn)
{
- MapDifficulty const* mapDiff = GetMapDifficultyData(mapid, difficulty);
- if (!mapDiff || !mapDiff->resetTime)
- {
- TC_LOG_ERROR("misc", "InstanceSaveManager::ResetOrWarnAll: not valid difficulty or no reset delay for map %d", mapid);
+ // calculate the next reset time
+ time_t next_reset = GetSubsequentResetTime(mapid, difficulty, resetTime);
+ if (!next_reset)
return;
- }
- // remove all binds to instances of the given map
- for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();)
- {
- if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty)
- _ResetSave(itr);
- else
- ++itr;
- }
-
- // delete them from the DB, even if not loaded
+ // delete/promote instance binds from the DB, even if not loaded
SQLTransaction trans = CharacterDatabase.BeginTransaction();
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INSTANCE_BY_MAP_DIFF);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EXPIRED_CHAR_INSTANCE_BY_MAP_DIFF);
stmt->setUInt16(0, uint16(mapid));
stmt->setUInt8(1, uint8(difficulty));
trans->Append(stmt);
@@ -606,21 +645,26 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b
stmt->setUInt8(1, uint8(difficulty));
trans->Append(stmt);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INSTANCE_BY_MAP_DIFF);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EXPIRED_INSTANCE_BY_MAP_DIFF);
stmt->setUInt16(0, uint16(mapid));
stmt->setUInt8(1, uint8(difficulty));
trans->Append(stmt);
- CharacterDatabase.CommitTransaction(trans);
-
- // calculate the next reset time
- uint32 diff = sWorld->getIntConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_EXPIRE_CHAR_INSTANCE_BY_MAP_DIFF);
+ stmt->setUInt16(0, uint16(mapid));
+ stmt->setUInt8(1, uint8(difficulty));
+ trans->Append(stmt);
- uint32 period = uint32(((mapDiff->resetTime * sWorld->getRate(RATE_INSTANCE_RESET_TIME))/DAY) * DAY);
- if (period < DAY)
- period = DAY;
+ CharacterDatabase.CommitTransaction(trans);
- uint32 next_reset = uint32(((resetTime + MINUTE) / DAY * DAY) + period + diff);
+ // promote loaded binds to instances of the given map
+ for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();)
+ {
+ if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty)
+ _ResetSave(itr);
+ else
+ ++itr;
+ }
SetResetTimeFor(mapid, difficulty, next_reset);
ScheduleReset(true, time_t(next_reset-3600), InstResetEvent(1, mapid, difficulty, 0));