diff options
author | n0n4m3 <none@none> | 2009-12-17 11:18:07 +0100 |
---|---|---|
committer | n0n4m3 <none@none> | 2009-12-17 11:18:07 +0100 |
commit | 360edd11df3911567000d5e150f3ede22af112f5 (patch) | |
tree | b06a0244a2f24b2a5322e8f61437cae8f9fb6706 /src/game/InstanceSaveMgr.cpp | |
parent | 085bc555d73ebc1e28304c4dbfdb9542bb78f21e (diff) |
Update InstanceSaveMgr for new instance system
--HG--
branch : trunk
Diffstat (limited to 'src/game/InstanceSaveMgr.cpp')
-rw-r--r-- | src/game/InstanceSaveMgr.cpp | 147 |
1 files changed, 86 insertions, 61 deletions
diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp index 8c1aab1b60b..128674d978a 100644 --- a/src/game/InstanceSaveMgr.cpp +++ b/src/game/InstanceSaveMgr.cpp @@ -77,15 +77,27 @@ InstanceSaveManager::~InstanceSaveManager() - adding instance into manager - called from InstanceMap::Add, _LoadBoundInstances, LoadGroups */ -InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, uint8 difficulty, time_t resetTime, bool canReset, bool load) +InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load) { - InstanceSave *save = GetInstanceSave(instanceId); - if(save) return save; + if(InstanceSave *old_save = GetInstanceSave(instanceId)) + return old_save; const MapEntry* entry = sMapStore.LookupEntry(mapId); - if(!entry || instanceId == 0) + if (!entry) { - sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d!", mapId, instanceId); + sLog.outError("InstanceSaveManager::AddInstanceSave: wrong mapid = %d!", mapId, instanceId); + return NULL; + } + + if (instanceId == 0) + { + sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, wrong instanceid = %d!", mapId, instanceId); + return NULL; + } + + if (difficulty >= (entry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY)) + { + sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong dificalty %u!", mapId, instanceId, difficulty); return NULL; } @@ -93,19 +105,19 @@ 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 == DIFFICULTY_HEROIC) - resetTime = GetResetTimeFor(mapId); + if(entry->map_type == MAP_RAID || difficulty > DUNGEON_DIFFICULTY_NORMAL) + resetTime = 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, instanceId)); + ScheduleReset(true, resetTime, InstResetEvent(0, mapId, difficulty, instanceId)); } } sLog.outDebug("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d", mapId, instanceId); - save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset); + InstanceSave *save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset); if(!load) save->SaveToDB(); m_instanceSaveById[instanceId] = save; @@ -141,7 +153,7 @@ void InstanceSaveManager::RemoveInstanceSave(uint32 InstanceId) } } -InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, uint8 difficulty, time_t resetTime, bool canReset) +InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset) : m_resetTime(resetTime), m_instanceid(InstanceId), m_mapid(MapId), m_difficulty(difficulty), m_canReset(canReset) { @@ -180,7 +192,7 @@ time_t InstanceSave::GetResetTimeForDB() { // only save the reset time for normal instances const MapEntry *entry = sMapStore.LookupEntry(GetMapId()); - if(!entry || entry->map_type == MAP_RAID || GetDifficulty() == DIFFICULTY_HEROIC) + if(!entry || entry->map_type == MAP_RAID || GetDifficulty() == DUNGEON_DIFFICULTY_HEROIC) return 0; else return GetResetTime(); @@ -402,18 +414,26 @@ void InstanceSaveManager::LoadResetTimes() // 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::map<uint32, std::pair<uint32, time_t> > ResetTimeMapType; - ResetTimeMapType InstResetTime; - QueryResult *result = CharacterDatabase.Query("SELECT id, map, resettime FROM instance WHERE resettime > 0"); + typedef std::pair<uint32 /*PAIR32(map,difficulty)*/, time_t> ResetTimeMapDiffType; + typedef std::map<uint32, ResetTimeMapDiffType> InstResetTimeMapDiffType; + InstResetTimeMapDiffType instResetTime; + + // index instance ids by map/difficulty pairs for fast reset warning send + typedef std::multimap<uint32 /*PAIR32(map,difficulty)*/, uint32 /*instanceid*/ > 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)[2].GetUInt64())) + if(time_t resettime = time_t((*result)[3].GetUInt64())) { uint32 id = (*result)[0].GetUInt32(); uint32 mapid = (*result)[1].GetUInt32(); - InstResetTime[id] = std::pair<uint32, uint64>(mapid, resettime); + 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()); @@ -428,8 +448,8 @@ void InstanceSaveManager::LoadResetTimes() Field *fields = result->Fetch(); uint32 instance = fields[1].GetUInt32(); time_t resettime = time_t(fields[0].GetUInt64() + 2 * HOUR); - ResetTimeMapType::iterator itr = InstResetTime.find(instance); - if(itr != InstResetTime.end() && itr->second.second != resettime) + 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; @@ -440,62 +460,65 @@ void InstanceSaveManager::LoadResetTimes() } // schedule the reset times - for (ResetTimeMapType::iterator itr = InstResetTime.begin(); itr != InstResetTime.end(); ++itr) + for(InstResetTimeMapDiffType::iterator itr = instResetTime.begin(); itr != instResetTime.end(); ++itr) if(itr->second.second > now) - ScheduleReset(true, itr->second.second, InstResetEvent(0, itr->second.first, itr->first)); + 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_INSTANCE_RESET_TIME_HOUR) * HOUR; - m_resetTimeByMapId.resize(sMapStore.GetNumRows()+1); - result = CharacterDatabase.Query("SELECT mapid, resettime FROM instance_reset"); + result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset"); if(result) { do { Field *fields = result->Fetch(); uint32 mapid = fields[0].GetUInt32(); - if(!objmgr.GetInstanceTemplate(mapid)) + 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 in instance_reset!", mapid); - CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u'", mapid); + 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 oldresettime = fields[1].GetUInt64(); uint64 newresettime = (oldresettime / DAY) * DAY + diff; if(oldresettime != newresettime) - CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u'", newresettime, mapid); + CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty = '%u'", newresettime, mapid, difficulty); - m_resetTimeByMapId[mapid] = newresettime; + 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, difficulty", "instance", "LEFT JOIN instance_reset ON mapid = map WHERE (instance.resettime < '"UI64FMTD"' AND instance.resettime > '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime < '"UI64FMTD"')", (uint64)now, (uint64)now); + _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 (uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++) + for(MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr) { - InstanceTemplate const* temp = objmgr.GetInstanceTemplate(i); - if(!temp) continue; - // only raid/heroic maps have a global reset time - const MapEntry* entry = sMapStore.LookupEntry(temp->map); - if(!entry || !entry->HasResetTime()) + 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; - uint32 period = temp->reset_delay * DAY; - assert(period != 0); - time_t t = m_resetTimeByMapId[temp->map]; + // the reset_delay must be at least one day + uint32 period = (mapDiff->resetTime / DAY * sWorld.getRate(RATE_INSTANCE_RESET_TIME)) * 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','"UI64FMTD"')", i, (uint64)t); + CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','%u','"UI64FMTD"')", mapid, difficulty, (uint64)t); } if(t < now) @@ -504,17 +527,23 @@ void InstanceSaveManager::LoadResetTimes() // 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'", (uint64)t, i); + CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty); } - m_resetTimeByMapId[temp->map] = t; + 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; - ScheduleReset(true, t - tim[type-1], InstResetEvent(type, i)); + 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)); + } } } @@ -555,8 +584,8 @@ void InstanceSaveManager::Update() else { // global reset/warning for a certain map - time_t resetTime = GetResetTimeFor(event.mapid); - _ResetOrWarnAll(event.mapid, event.type != 4, resetTime - now); + time_t resetTime = GetResetTimeFor(event.mapid,event.difficulty); + _ResetOrWarnAll(event.mapid, event.difficulty, event.type != 4, resetTime - now); if(event.type != 4) { // schedule the next warning/reset @@ -607,29 +636,28 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId) else objmgr.DeleteRespawnTimeForInstance(instanceId); // even if map is not loaded } -void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLeft) +void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeLeft) { // global reset for all instances of the given map - // note: this isn't fast but it's meant to be executed very rarely - Map const *map = MapManager::Instance().CreateBaseMap(mapid); - if(!map->Instanceable()) + MapEntry const *mapEntry = sMapStore.LookupEntry(mapid); + if (!mapEntry->Instanceable()) return; + uint64 now = (uint64)time(NULL); if(!warn) { - // this is called one minute before the reset time - InstanceTemplate const* temp = objmgr.GetInstanceTemplate(mapid); - if(!temp || !temp->reset_delay) + MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty); + if (!mapDiff || !mapDiff->resetTime) { - sLog.outError("InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d", mapid); + sLog.outError("InstanceSaveManager::ResetOrWarnAll: not valid difficulty or no reset delay for map %d", mapid); 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) + if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty) _ResetSave(itr); else ++itr; @@ -644,16 +672,14 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe // calculate the next reset time uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR; - uint32 period = temp->reset_delay * DAY; + uint32 period = mapDiff->resetTime * DAY; uint64 next_reset = ((now + timeLeft + MINUTE) / DAY * DAY) + period + diff; // update it in the DB - CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%d'", next_reset, mapid); - - // schedule next reset. - m_resetTimeByMapId[mapid] = (time_t) next_reset; - ScheduleReset(true, (time_t) (next_reset-3600), InstResetEvent(1, mapid)); + CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%d' AND difficulty = '%d'", next_reset, mapid, difficulty); } + // note: this isn't fast but it's meant to be executed very rarely + Map const *map = MapManager::Instance().CreateBaseMap(mapid); // _not_ include difficulty MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps(); MapInstanced::InstancedMaps::iterator mitr; for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr) @@ -682,4 +708,3 @@ uint32 InstanceSaveManager::GetNumBoundGroupsTotal() ret += itr->second->GetGroupCount(); return ret; } - |