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::map<uint32, std::pair<uint32, uint64> > ResetTimeMapType; ResetTimeMapType InstResetTime; QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT id, map, resettime FROM instance WHERE resettime > 0"); if (result) { do { if (uint64 resettime = (*result)[2].GetUInt64()) { uint32 id = (*result)[0].GetUInt32(); uint32 mapid = (*result)[1].GetUInt32(); InstResetTime[id] = std::pair<uint32, uint64>(mapid, resettime); } } while (result->NextRow()); // 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(); uint64 resettime = fields[0].GetUInt64() + 2 * HOUR; ResetTimeMapType::iterator itr = InstResetTime.find(instance); if (itr != InstResetTime.end() && itr->second.second != resettime) { CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '" UI64FMTD "' WHERE id = '%u'", resettime, instance); itr->second.second = resettime; } } while (result->NextRow()); } // schedule the reset times for (ResetTimeMapType::iterator itr = InstResetTime.begin(); itr != InstResetTime.end(); ++itr) if (itr->second.second > uint32(now)) ScheduleReset(true, itr->second.second, InstResetEvent(0, 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"); if (result) { do { Field* fields = result->Fetch(); uint32 mapid = fields[0].GetUInt32(); if (!sObjectMgr.GetInstanceTemplate(mapid)) { sLog.outError("InstanceSaveManager::LoadResetTimes: invalid mapid %u in instance_reset!", mapid); CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u'", mapid); 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); m_resetTimeByMapId[mapid] = newresettime; } while (result->NextRow()); } // 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); // 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++) { InstanceTemplate* temp = (InstanceTemplate*)sObjectMgr.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()) continue; // the reset_delay must be at least one day uint32 period = uint32(((temp->reset_delay * sWorld.getRate(RATE_INSTANCE_RESET_TIME))/DAY) * DAY); if (period < DAY) period = DAY; time_t t = m_resetTimeByMapId[temp->map]; if (!t) { // initialize the reset time t = today + period + diff; CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','" UI64FMTD "')", i, (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'", (uint64)t, i); } m_resetTimeByMapId[temp->map] = t; // schedule the global reset/warning uint8 type; for (type = 1; type < 4; ++type) if (t - ResetTimeDelay[type-1] > now) break; ScheduleReset(true, t - ResetTimeDelay[type-1], InstResetEvent(type, i)); } }
void DungeonResetScheduler::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::map<uint32, std::pair<uint32, time_t> > ResetTimeMapType; ResetTimeMapType InstResetTime; QueryResult *result = CharacterDatabase.Query("SELECT id, map, resettime FROM instance WHERE resettime > 0"); if( result ) { do { if (time_t resettime = time_t((*result)[2].GetUInt64())) { uint32 id = (*result)[0].GetUInt32(); uint32 mapid = (*result)[1].GetUInt32(); MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); if (!mapEntry || !mapEntry->IsDungeon()) { sMapPersistentStateMgr.DeleteInstanceFromDB(id); continue; } InstResetTime[id] = std::pair<uint32, uint64>(mapid, resettime); } } while (result->NextRow()); delete result; // update reset time for normal instances with the max creature respawn time + X hours result = CharacterDatabase.Query("SELECT MAX(respawntime), instance FROM creature_respawn WHERE instance > 0 GROUP BY instance"); if( result ) { do { Field* fields = result->Fetch(); time_t resettime = time_t(fields[0].GetUInt64() + 2 * HOUR); uint32 instance = fields[1].GetUInt32(); ResetTimeMapType::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(ResetTimeMapType::iterator itr = InstResetTime.begin(); itr != InstResetTime.end(); ++itr) if(itr->second.second > now) ScheduleReset(true, itr->second.second, DungeonResetEvent(RESET_EVENT_NORMAL_DUNGEON, 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; m_resetTimeByMapId.resize(sMapStore.GetNumRows()+1); result = CharacterDatabase.Query("SELECT mapid, resettime FROM instance_reset"); if(result) { do { Field* fields = result->Fetch(); uint32 mapid = fields[0].GetUInt32(); MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); if (!mapEntry || !mapEntry->IsDungeon() || !ObjectMgr::GetInstanceTemplate(mapid)) { sLog.outError("MapPersistentStateManager::LoadResetTimes: invalid mapid %u in instance_reset!", mapid); CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u'", mapid); 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); SetResetTimeFor(mapid, 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._CleanupExpiredInstancesAtTime(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++) { InstanceTemplate const* temp = ObjectMgr::GetInstanceTemplate(i); if (!temp) continue; // only raid/heroic maps have a global reset time MapEntry const* mapEntry = sMapStore.LookupEntry(temp->map); if (!mapEntry || !mapEntry->IsDungeon() || !mapEntry->HasResetTime()) continue; uint32 period = GetMaxResetTimeFor(temp); time_t t = GetResetTimeFor(temp->map); if(!t) { // initialize the reset time t = today + period + diff; CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','"UI64FMTD"')", temp->map, (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'", (uint64)t, temp->map); } SetResetTimeFor(temp->map, t); // schedule the global reset/warning ResetEventType type = RESET_EVENT_INFORM_1; for(; type < RESET_EVENT_INFORM_LAST; type = ResetEventType(type+1)) if(t - resetEventTypeDelay[type] > now) break; ScheduleReset(true, t - resetEventTypeDelay[type], DungeonResetEvent(type, temp->map, 0)); } }