From e88a718c5d907917615d134efe088546b2cac76d Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 22 Jun 2010 04:35:07 +0400 Subject: [PATCH] [10094] Extract instance reset scheduler from InstanceSaveMgr Reset scheduler code not need explicit access to instance saves, and no reson mix it with instance save managment code in single class --- src/game/InstanceSaveMgr.cpp | 433 ++++++++++++++++++----------------- src/game/InstanceSaveMgr.h | 94 +++++--- src/game/Map.cpp | 6 +- src/game/MovementHandler.cpp | 2 +- src/shared/revision_nr.h | 2 +- 5 files changed, 296 insertions(+), 241 deletions(-) diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp index fb89b8132..c4790e6ed 100644 --- a/src/game/InstanceSaveMgr.cpp +++ b/src/game/InstanceSaveMgr.cpp @@ -123,9 +123,221 @@ bool InstanceSave::UnloadIfEmpty() return true; } +//== InstanceResetScheduler functions ====================== + +void InstanceResetScheduler::LoadResetTimes() +{ + time_t now = time(NULL); + time_t today = (now / DAY) * DAY; + + // NOTE: Use DirectPExecute for tables that will be queried later + + // get the current reset times for normal instances (these may need to be updated) + // these are only kept in memory for InstanceSaves that are loaded later + // resettime = 0 in the DB for raid/heroic instances so those are skipped + typedef std::pair ResetTimeMapDiffType; + typedef std::map InstResetTimeMapDiffType; + InstResetTimeMapDiffType instResetTime; + + // index instance ids by map/difficulty pairs for fast reset warning send + typedef std::multimap ResetTimeMapDiffInstances; + ResetTimeMapDiffInstances mapDiffResetInstances; + + QueryResult *result = CharacterDatabase.Query("SELECT id, map, difficulty, resettime FROM instance WHERE resettime > 0"); + if( result ) + { + do + { + if(time_t resettime = time_t((*result)[3].GetUInt64())) + { + uint32 id = (*result)[0].GetUInt32(); + uint32 mapid = (*result)[1].GetUInt32(); + uint32 difficulty = (*result)[2].GetUInt32(); + instResetTime[id] = ResetTimeMapDiffType(MAKE_PAIR32(mapid,difficulty), resettime); + mapDiffResetInstances.insert(ResetTimeMapDiffInstances::value_type(MAKE_PAIR32(mapid,difficulty),id)); + } + } + while (result->NextRow()); + delete result; + + // update reset time for normal instances with the max creature respawn time + X hours + result = WorldDatabase.Query("SELECT MAX(respawntime), instance FROM creature_respawn WHERE instance > 0 GROUP BY instance"); + if( result ) + { + do + { + Field *fields = result->Fetch(); + uint32 instance = fields[1].GetUInt32(); + time_t resettime = time_t(fields[0].GetUInt64() + 2 * HOUR); + InstResetTimeMapDiffType::iterator itr = instResetTime.find(instance); + if(itr != instResetTime.end() && itr->second.second != resettime) + { + CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", uint64(resettime), instance); + itr->second.second = resettime; + } + } + while (result->NextRow()); + delete result; + } + + // schedule the reset times + for(InstResetTimeMapDiffType::iterator itr = instResetTime.begin(); itr != instResetTime.end(); ++itr) + if(itr->second.second > now) + ScheduleReset(true, itr->second.second, InstanceResetEvent(0, PAIR32_LOPART(itr->second.first),Difficulty(PAIR32_HIPART(itr->second.first)),itr->first)); + } + + // load the global respawn times for raid/heroic instances + uint32 diff = sWorld.getConfig(CONFIG_UINT32_INSTANCE_RESET_TIME_HOUR) * HOUR; + result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset"); + if(result) + { + do + { + Field *fields = result->Fetch(); + uint32 mapid = fields[0].GetUInt32(); + Difficulty difficulty = Difficulty(fields[1].GetUInt32()); + uint64 oldresettime = fields[2].GetUInt64(); + + MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty); + if(!mapDiff) + { + sLog.outError("InstanceSaveManager::LoadResetTimes: invalid mapid(%u)/difficulty(%u) pair in instance_reset!", mapid, difficulty); + CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u' AND difficulty = '%u'", mapid,difficulty); + continue; + } + + // update the reset time if the hour in the configs changes + uint64 newresettime = (oldresettime / DAY) * DAY + diff; + if(oldresettime != newresettime) + CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty = '%u'", newresettime, mapid, difficulty); + + SetResetTimeFor(mapid,difficulty,newresettime); + } while(result->NextRow()); + delete result; + } + + // clean expired instances, references to them will be deleted in CleanupInstances + // must be done before calculating new reset times + m_InstanceSaves._CleanupExiredInstancesAtTime(now); + + // calculate new global reset times for expired instances and those that have never been reset yet + // add the global reset times to the priority queue + for(MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr) + { + uint32 map_diff_pair = itr->first; + uint32 mapid = PAIR32_LOPART(map_diff_pair); + Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair)); + MapDifficulty const* mapDiff = &itr->second; + if (!mapDiff->resetTime) + continue; + + // the reset_delay must be at least one day + uint32 period = uint32(mapDiff->resetTime / DAY * sWorld.getConfig(CONFIG_FLOAT_RATE_INSTANCE_RESET_TIME)) * DAY; + if (period < DAY) + period = DAY; + + time_t t = GetResetTimeFor(mapid,difficulty); + if(!t) + { + // initialize the reset time + t = today + period + diff; + CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','%u','"UI64FMTD"')", mapid, difficulty, (uint64)t); + } + + if(t < now) + { + // assume that expired instances have already been cleaned + // calculate the next reset time + t = (t / DAY) * DAY; + t += ((today - t) / period + 1) * period + diff; + CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty); + } + + SetResetTimeFor(mapid,difficulty,t); + + // schedule the global reset/warning + uint8 type = 1; + static int tim[4] = {3600, 900, 300, 60}; + for(; type < 4; type++) + if(t - tim[type-1] > now) + break; + + for(ResetTimeMapDiffInstances::const_iterator in_itr = mapDiffResetInstances.lower_bound(map_diff_pair); + in_itr != mapDiffResetInstances.upper_bound(map_diff_pair); ++in_itr) + { + ScheduleReset(true, t - tim[type-1], InstanceResetEvent(type, mapid, difficulty, in_itr->second)); + } + } +} + +void InstanceResetScheduler::ScheduleReset(bool add, time_t time, InstanceResetEvent event) +{ + if (add) + m_resetTimeQueue.insert(std::pair(time, event)); + else + { + // find the event in the queue and remove it + ResetTimeQueue::iterator itr; + std::pair range; + range = m_resetTimeQueue.equal_range(time); + for(itr = range.first; itr != range.second; ++itr) + { + if (itr->second == event) + { + m_resetTimeQueue.erase(itr); + return; + } + } + // in case the reset time changed (should happen very rarely), we search the whole queue + if(itr == range.second) + { + for(itr = m_resetTimeQueue.begin(); itr != m_resetTimeQueue.end(); ++itr) + { + if(itr->second == event) + { + m_resetTimeQueue.erase(itr); + return; + } + } + + if(itr == m_resetTimeQueue.end()) + sLog.outError("InstanceResetScheduler::ScheduleReset: cannot cancel the reset, the event(%d,%d,%d) was not found!", event.type, event.mapid, event.instanceId); + } + } +} + +void InstanceResetScheduler::Update() +{ + time_t now = time(NULL), t; + while(!m_resetTimeQueue.empty() && (t = m_resetTimeQueue.begin()->first) < now) + { + InstanceResetEvent &event = m_resetTimeQueue.begin()->second; + if(event.type == 0) + { + // for individual normal instances, max creature respawn + X hours + m_InstanceSaves._ResetInstance(event.mapid, event.instanceId); + m_resetTimeQueue.erase(m_resetTimeQueue.begin()); + } + else + { + // global reset/warning for a certain map + time_t resetTime = GetResetTimeFor(event.mapid,event.difficulty); + m_InstanceSaves._ResetOrWarnAll(event.mapid, event.difficulty, event.type != 4, uint32(resetTime - now)); + if(event.type != 4) + { + // schedule the next warning/reset + event.type++; + static int tim[4] = {3600, 900, 300, 60}; + ScheduleReset(true, resetTime - tim[event.type-1], event); + } + m_resetTimeQueue.erase(m_resetTimeQueue.begin()); + } + } +} + //== InstanceSaveManager functions ========================= -InstanceSaveManager::InstanceSaveManager() : lock_instLists(false) +InstanceSaveManager::InstanceSaveManager() : lock_instLists(false), m_Scheduler(*this) { } @@ -171,12 +383,12 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance // initialize reset time // for normal instances if no creatures are killed the instance will reset in two hours if(entry->map_type == MAP_RAID || difficulty > DUNGEON_DIFFICULTY_NORMAL) - resetTime = GetResetTimeFor(mapId,difficulty); + resetTime = m_Scheduler.GetResetTimeFor(mapId,difficulty); else { resetTime = time(NULL) + 2 * HOUR; // normally this will be removed soon after in InstanceMap::Add, prevent error - ScheduleReset(true, resetTime, InstResetEvent(0, mapId, difficulty, instanceId)); + m_Scheduler.ScheduleReset(true, resetTime, InstanceResetEvent(0, mapId, difficulty, instanceId)); } } @@ -254,7 +466,7 @@ void InstanceSaveManager::CleanupInstances() bar.step(); // load reset times and clean expired instances - LoadResetTimes(); + m_Scheduler.LoadResetTimes(); // clean character/group - instance binds with invalid group/characters _DelHelper(CharacterDatabase, "character_instance.guid, instance", "character_instance", "LEFT JOIN characters ON character_instance.guid = characters.guid WHERE characters.guid IS NULL"); @@ -364,202 +576,6 @@ void InstanceSaveManager::PackInstances() sLog.outString(); } -void InstanceSaveManager::LoadResetTimes() -{ - time_t now = time(NULL); - time_t today = (now / DAY) * DAY; - - // NOTE: Use DirectPExecute for tables that will be queried later - - // get the current reset times for normal instances (these may need to be updated) - // these are only kept in memory for InstanceSaves that are loaded later - // resettime = 0 in the DB for raid/heroic instances so those are skipped - typedef std::pair ResetTimeMapDiffType; - typedef std::map InstResetTimeMapDiffType; - InstResetTimeMapDiffType instResetTime; - - // index instance ids by map/difficulty pairs for fast reset warning send - typedef std::multimap ResetTimeMapDiffInstances; - ResetTimeMapDiffInstances mapDiffResetInstances; - - QueryResult *result = CharacterDatabase.Query("SELECT id, map, difficulty, resettime FROM instance WHERE resettime > 0"); - if( result ) - { - do - { - if(time_t resettime = time_t((*result)[3].GetUInt64())) - { - uint32 id = (*result)[0].GetUInt32(); - uint32 mapid = (*result)[1].GetUInt32(); - uint32 difficulty = (*result)[2].GetUInt32(); - instResetTime[id] = ResetTimeMapDiffType(MAKE_PAIR32(mapid,difficulty), resettime); - mapDiffResetInstances.insert(ResetTimeMapDiffInstances::value_type(MAKE_PAIR32(mapid,difficulty),id)); - } - } - while (result->NextRow()); - delete result; - - // update reset time for normal instances with the max creature respawn time + X hours - result = WorldDatabase.Query("SELECT MAX(respawntime), instance FROM creature_respawn WHERE instance > 0 GROUP BY instance"); - if( result ) - { - do - { - Field *fields = result->Fetch(); - uint32 instance = fields[1].GetUInt32(); - time_t resettime = time_t(fields[0].GetUInt64() + 2 * HOUR); - InstResetTimeMapDiffType::iterator itr = instResetTime.find(instance); - if(itr != instResetTime.end() && itr->second.second != resettime) - { - CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", uint64(resettime), instance); - itr->second.second = resettime; - } - } - while (result->NextRow()); - delete result; - } - - // schedule the reset times - for(InstResetTimeMapDiffType::iterator itr = instResetTime.begin(); itr != instResetTime.end(); ++itr) - if(itr->second.second > now) - ScheduleReset(true, itr->second.second, InstResetEvent(0, PAIR32_LOPART(itr->second.first),Difficulty(PAIR32_HIPART(itr->second.first)),itr->first)); - } - - // load the global respawn times for raid/heroic instances - uint32 diff = sWorld.getConfig(CONFIG_UINT32_INSTANCE_RESET_TIME_HOUR) * HOUR; - result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset"); - if(result) - { - do - { - Field *fields = result->Fetch(); - uint32 mapid = fields[0].GetUInt32(); - Difficulty difficulty = Difficulty(fields[1].GetUInt32()); - uint64 oldresettime = fields[2].GetUInt64(); - - MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty); - if(!mapDiff) - { - sLog.outError("InstanceSaveManager::LoadResetTimes: invalid mapid(%u)/difficulty(%u) pair in instance_reset!", mapid, difficulty); - CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u' AND difficulty = '%u'", mapid,difficulty); - continue; - } - - // update the reset time if the hour in the configs changes - uint64 newresettime = (oldresettime / DAY) * DAY + diff; - if(oldresettime != newresettime) - CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty = '%u'", newresettime, mapid, difficulty); - - SetResetTimeFor(mapid,difficulty,newresettime); - } while(result->NextRow()); - delete result; - } - - // clean expired instances, references to them will be deleted in CleanupInstances - // must be done before calculating new reset times - _DelHelper(CharacterDatabase, "id, map, instance.difficulty", "instance", "LEFT JOIN instance_reset ON mapid = map AND instance.difficulty = instance_reset.difficulty WHERE (instance.resettime < '"UI64FMTD"' AND instance.resettime > '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime < '"UI64FMTD"')", (uint64)now, (uint64)now); - - // calculate new global reset times for expired instances and those that have never been reset yet - // add the global reset times to the priority queue - for(MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr) - { - uint32 map_diff_pair = itr->first; - uint32 mapid = PAIR32_LOPART(map_diff_pair); - Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair)); - MapDifficulty const* mapDiff = &itr->second; - if (!mapDiff->resetTime) - continue; - - // the reset_delay must be at least one day - uint32 period = uint32(mapDiff->resetTime / DAY * sWorld.getConfig(CONFIG_FLOAT_RATE_INSTANCE_RESET_TIME)) * DAY; - if (period < DAY) - period = DAY; - - time_t t = GetResetTimeFor(mapid,difficulty); - if(!t) - { - // initialize the reset time - t = today + period + diff; - CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','%u','"UI64FMTD"')", mapid, difficulty, (uint64)t); - } - - if(t < now) - { - // assume that expired instances have already been cleaned - // calculate the next reset time - t = (t / DAY) * DAY; - t += ((today - t) / period + 1) * period + diff; - CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty); - } - - SetResetTimeFor(mapid,difficulty,t); - - // schedule the global reset/warning - uint8 type = 1; - static int tim[4] = {3600, 900, 300, 60}; - for(; type < 4; type++) - if(t - tim[type-1] > now) - break; - - for(ResetTimeMapDiffInstances::const_iterator in_itr = mapDiffResetInstances.lower_bound(map_diff_pair); - in_itr != mapDiffResetInstances.upper_bound(map_diff_pair); ++in_itr) - { - ScheduleReset(true, t - tim[type-1], InstResetEvent(type, mapid, difficulty, in_itr->second)); - } - } -} - -void InstanceSaveManager::ScheduleReset(bool add, time_t time, InstResetEvent event) -{ - if(add) m_resetTimeQueue.insert(std::pair(time, event)); - else - { - // find the event in the queue and remove it - ResetTimeQueue::iterator itr; - std::pair range; - range = m_resetTimeQueue.equal_range(time); - for(itr = range.first; itr != range.second; ++itr) - if(itr->second == event) { m_resetTimeQueue.erase(itr); return; } - // in case the reset time changed (should happen very rarely), we search the whole queue - if(itr == range.second) - { - for(itr = m_resetTimeQueue.begin(); itr != m_resetTimeQueue.end(); ++itr) - if(itr->second == event) { m_resetTimeQueue.erase(itr); return; } - if(itr == m_resetTimeQueue.end()) - sLog.outError("InstanceSaveManager::ScheduleReset: cannot cancel the reset, the event(%d,%d,%d) was not found!", event.type, event.mapid, event.instanceId); - } - } -} - -void InstanceSaveManager::Update() -{ - time_t now = time(NULL), t; - while(!m_resetTimeQueue.empty() && (t = m_resetTimeQueue.begin()->first) < now) - { - InstResetEvent &event = m_resetTimeQueue.begin()->second; - if(event.type == 0) - { - // for individual normal instances, max creature respawn + X hours - _ResetInstance(event.mapid, event.instanceId); - m_resetTimeQueue.erase(m_resetTimeQueue.begin()); - } - else - { - // global reset/warning for a certain map - time_t resetTime = GetResetTimeFor(event.mapid,event.difficulty); - _ResetOrWarnAll(event.mapid, event.difficulty, event.type != 4, uint32(resetTime - now)); - if(event.type != 4) - { - // schedule the next warning/reset - event.type++; - static int tim[4] = {3600, 900, 300, 60}; - ScheduleReset(true, resetTime - tim[event.type-1], event); - } - m_resetTimeQueue.erase(m_resetTimeQueue.begin()); - } - } -} - void InstanceSaveManager::_ResetSave(InstanceSaveHashMap::iterator &itr) { // unbind all players bound to the instance @@ -574,16 +590,20 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId) { DEBUG_LOG("InstanceSaveMgr::_ResetInstance %u, %u", mapid, instanceId); Map *map = (MapInstanced*)sMapMgr.CreateBaseMap(mapid); - if(!map->Instanceable()) + if (!map->Instanceable()) return; InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(instanceId); - if(itr != m_instanceSaveById.end()) _ResetSave(itr); + if (itr != m_instanceSaveById.end()) + _ResetSave(itr); + DeleteInstanceFromDB(instanceId); // even if save not loaded Map* iMap = ((MapInstanced*)map)->FindMap(instanceId); - if(iMap && iMap->IsDungeon()) ((InstanceMap*)iMap)->Reset(INSTANCE_RESET_RESPAWN_DELAY); - else sObjectMgr.DeleteRespawnTimeForInstance(instanceId); // even if map is not loaded + if (iMap && iMap->IsDungeon()) + ((InstanceMap*)iMap)->Reset(INSTANCE_RESET_RESPAWN_DELAY); + else + sObjectMgr.DeleteRespawnTimeForInstance(instanceId);// even if map is not loaded } void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeLeft) @@ -662,3 +682,8 @@ uint32 InstanceSaveManager::GetNumBoundGroupsTotal() ret += itr->second->GetGroupCount(); return ret; } + +void InstanceSaveManager::_CleanupExiredInstancesAtTime( time_t t ) +{ + _DelHelper(CharacterDatabase, "id, map, instance.difficulty", "instance", "LEFT JOIN instance_reset ON mapid = map AND instance.difficulty = instance_reset.difficulty WHERE (instance.resettime < '"UI64FMTD"' AND instance.resettime > '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime < '"UI64FMTD"')", (uint64)t, (uint64)t); +} \ No newline at end of file diff --git a/src/game/InstanceSaveMgr.h b/src/game/InstanceSaveMgr.h index ee9a5f7a1..57917c203 100644 --- a/src/game/InstanceSaveMgr.h +++ b/src/game/InstanceSaveMgr.h @@ -112,9 +112,62 @@ class InstanceSave bool m_canReset; }; +/* resetTime is a global propery of each (raid/heroic) map + all instances of that map reset at the same time */ +struct InstanceResetEvent +{ + uint8 type; + Difficulty difficulty:8; + uint16 mapid; + uint16 instanceId; + + InstanceResetEvent() : type(0), difficulty(DUNGEON_DIFFICULTY_NORMAL), mapid(0), instanceId(0) {} + InstanceResetEvent(uint8 t, uint32 _mapid, Difficulty d, uint16 _instanceid) + : type(t), difficulty(d), mapid(_mapid), instanceId(_instanceid) {} + bool operator == (const InstanceResetEvent& e) { return e.instanceId == instanceId; } +}; + +class InstanceSaveManager; + +class InstanceResetScheduler +{ + public: // constructors + explicit InstanceResetScheduler(InstanceSaveManager& mgr) : m_InstanceSaves(mgr) {} + void LoadResetTimes(); + + public: // accessors + time_t GetResetTimeFor(uint32 mapid, Difficulty d) const + { + ResetTimeByMapDifficultyMap::const_iterator itr = m_resetTimeByMapDifficulty.find(MAKE_PAIR32(mapid,d)); + return itr != m_resetTimeByMapDifficulty.end() ? itr->second : 0; + } + + public: // modifiers + void SetResetTimeFor(uint32 mapid, Difficulty d, time_t t) + { + m_resetTimeByMapDifficulty[MAKE_PAIR32(mapid,d)] = t; + } + + void ScheduleReset(bool add, time_t time, InstanceResetEvent event); + + void Update(); + + private: // fields + InstanceSaveManager& m_InstanceSaves; + + + // fast lookup for reset times (always use existed functions for access/set) + typedef UNORDERED_MAP ResetTimeByMapDifficultyMap; + ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty; + + typedef std::multimap ResetTimeQueue; + ResetTimeQueue m_resetTimeQueue; +}; + class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton > { friend class InstanceSave; + friend class InstanceResetScheduler; public: InstanceSaveManager(); ~InstanceSaveManager(); @@ -122,39 +175,10 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton InstanceSaveHashMap; typedef UNORDERED_MAP InstanceSaveMapMap; - /* resetTime is a global propery of each (raid/heroic) map - all instances of that map reset at the same time */ - struct InstResetEvent - { - uint8 type; - Difficulty difficulty:8; - uint16 mapid; - uint16 instanceId; - - InstResetEvent() : type(0), difficulty(DUNGEON_DIFFICULTY_NORMAL), mapid(0), instanceId(0) {} - InstResetEvent(uint8 t, uint32 _mapid, Difficulty d, uint16 _instanceid) - : type(t), difficulty(d), mapid(_mapid), instanceId(_instanceid) {} - bool operator == (const InstResetEvent& e) { return e.instanceId == instanceId; } - }; - typedef std::multimap ResetTimeQueue; - typedef UNORDERED_MAP ResetTimeByMapDifficultyMap; - void CleanupInstances(); void PackInstances(); - void LoadResetTimes(); - time_t GetResetTimeFor(uint32 mapid, Difficulty d) const - { - ResetTimeByMapDifficultyMap::const_iterator itr = m_resetTimeByMapDifficulty.find(MAKE_PAIR32(mapid,d)); - return itr != m_resetTimeByMapDifficulty.end() ? itr->second : 0; - } - void SetResetTimeFor(uint32 mapid, Difficulty d, time_t t) - { - m_resetTimeByMapDifficulty[MAKE_PAIR32(mapid,d)] = t; - } - void ScheduleReset(bool add, time_t time, InstResetEvent event); - - void Update(); + InstanceResetScheduler& GetScheduler() { return m_Scheduler; } InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load = false); void RemoveInstanceSave(uint32 InstanceId); @@ -167,18 +191,22 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton::Instance() diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 57f09ce13..af4a58e4a 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -2054,8 +2054,10 @@ void InstanceMap::SetResetSchedule(bool on) if(IsDungeon() && !HavePlayers() && !IsRaidOrHeroicDungeon()) { InstanceSave *save = sInstanceSaveMgr.GetInstanceSave(GetInstanceId()); - if(!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId()); - else sInstanceSaveMgr.ScheduleReset(on, save->GetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), Difficulty(GetSpawnMode()), GetInstanceId())); + if (!save) + sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId()); + else + sInstanceSaveMgr.GetScheduler().ScheduleReset(on, save->GetResetTime(), InstanceResetEvent(0, GetId(), Difficulty(GetSpawnMode()), GetInstanceId())); } } diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 9c9377673..c6376646a 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -144,7 +144,7 @@ void WorldSession::HandleMoveWorldportAckOpcode() { if (mapDiff->resetTime) { - if (time_t timeReset = sInstanceSaveMgr.GetResetTimeFor(mEntry->MapID,diff)) + if (time_t timeReset = sInstanceSaveMgr.GetScheduler().GetResetTimeFor(mEntry->MapID,diff)) { uint32 timeleft = uint32(timeReset - time(NULL)); GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index bfb891d40..de9628373 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10093" + #define REVISION_NR "10094" #endif // __REVISION_NR_H__