void DungeonResetScheduler::LoadResetTimes() { time_t now = time(nullptr); time_t today = (now / DAY) * DAY; time_t nextWeek = today + (7 * 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.GetMaxEntry(); 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 // generate time by config on first server launch tm localTm = *localtime(&now); localTm.tm_hour = sWorld.getConfig(CONFIG_UINT32_QUEST_DAILY_RESET_HOUR); localTm.tm_min = 0; localTm.tm_sec = 0; if (period > DAY) // resets bigger than 1 day start on config day localTm.tm_mday += ((7 - localTm.tm_wday + sWorld.getConfig(CONFIG_UINT32_ARENA_FIRST_RESET_DAY)) % 7); else // resets day and less start on next day localTm.tm_mday += 1; localTm.tm_isdst = -1; t = mktime(&localTm); CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','" UI64FMTD "')", temp->map, (uint64)t); } if (t < now || t > nextWeek) { // 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 > time_t(now + resetEventTypeDelay[type])) break; ScheduleReset(true, t - resetEventTypeDelay[type], DungeonResetEvent(type, temp->map, 0)); } }
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 > 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 (!objmgr.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*)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()) continue; uint32 period = temp->reset_delay * DAY; ASSERT(period != 0); 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 = 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)); } }
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 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(); 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 = 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); 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, InstanceResetEvent(RESET_EVENT_DUNGEON, itr->second.first, itr->first)); } // load the global respawn times for raid 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(); if(!ObjectMgr::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()); 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++) { // only raid maps have a global reset time InstanceTemplate const* temp = ObjectMgr::GetInstanceTemplate(i); if(!temp || !temp->reset_delay) 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); } m_resetTimeByMapId[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], InstanceResetEvent(type, temp->map, 0)); } }