diff options
| author | Treeston <treeston.mmoc@gmail.com> | 2019-08-04 12:22:57 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-04 12:22:57 +0200 |
| commit | a5e73e41c0e813e674bb0a644e0052052435494e (patch) | |
| tree | cabbeadc1e07635f1a8fc53599895613cbe61723 /src/server/game/World | |
| parent | 15e85f882fdb7b5d1d48302907e76c993ee4e923 (diff) | |
Core/Pooling: Quest pooling rewrite: (PR#23627)
- Split quest pooling from PoolMgr (into QuestPoolMgr)
- Proper saving/restoring on server restart
- No more hacking into sObjectMgr to insert/remove available quests
Diffstat (limited to 'src/server/game/World')
| -rw-r--r-- | src/server/game/World/World.cpp | 259 | ||||
| -rw-r--r-- | src/server/game/World/World.h | 11 |
2 files changed, 130 insertions, 140 deletions
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 50db5f7d34d..2a80f607a63 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -67,6 +67,7 @@ #include "PlayerDump.h" #include "PoolMgr.h" #include "QueryCallback.h" +#include "QuestPools.h" #include "Realm.h" #include "ScriptMgr.h" #include "ScriptReloadMgr.h" @@ -971,7 +972,20 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_CAST_UNSTUCK] = sConfigMgr->GetBoolDefault("CastUnstuck", true); m_int_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfigMgr->GetIntDefault("Instance.ResetTimeHour", 4); m_int_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfigMgr->GetIntDefault("Instance.UnloadDelay", 30 * MINUTE * IN_MILLISECONDS); + m_int_configs[CONFIG_DAILY_QUEST_RESET_TIME_HOUR] = sConfigMgr->GetIntDefault("Quests.DailyResetTime", 3); + if (m_int_configs[CONFIG_DAILY_QUEST_RESET_TIME_HOUR] < 0 || m_int_configs[CONFIG_DAILY_QUEST_RESET_TIME_HOUR] > 23) + { + TC_LOG_ERROR("server.loading", "Quests.DailyResetTime (%i) must be in range 0..23. Set to 3.", m_int_configs[CONFIG_DAILY_QUEST_RESET_TIME_HOUR]); + m_int_configs[CONFIG_DAILY_QUEST_RESET_TIME_HOUR] = 3; + } + + m_int_configs[CONFIG_WEEKLY_QUEST_RESET_TIME_WDAY] = sConfigMgr->GetIntDefault("Quests.WeeklyResetWDay", 3); + if (m_int_configs[CONFIG_WEEKLY_QUEST_RESET_TIME_WDAY] < 0 || m_int_configs[CONFIG_WEEKLY_QUEST_RESET_TIME_WDAY] > 6) + { + TC_LOG_ERROR("server.loading", "Quests.WeeklyResetDay (%i) must be in range 0..6. Set to 3 (Wednesday).", m_int_configs[CONFIG_WEEKLY_QUEST_RESET_TIME_WDAY]); + m_int_configs[CONFIG_WEEKLY_QUEST_RESET_TIME_WDAY] = 3; + } m_int_configs[CONFIG_MAX_PRIMARY_TRADE_SKILL] = sConfigMgr->GetIntDefault("MaxPrimaryTradeSkill", 2); m_int_configs[CONFIG_MIN_PETITION_SIGNS] = sConfigMgr->GetIntDefault("MinPetitionSigns", 9); @@ -1815,6 +1829,8 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading Objects Pooling Data..."); sPoolMgr->LoadFromDB(); + TC_LOG_INFO("server.loading", "Loading Quest Pooling Data..."); + sQuestPoolMgr->LoadFromDB(); // must be after quest templates TC_LOG_INFO("server.loading", "Loading Game Event Data..."); // must be after loading pools fully sGameEventMgr->LoadHolidayDates(); // Must be after loading DBC @@ -2143,14 +2159,9 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Deleting expired bans..."); LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); // One-time query - TC_LOG_INFO("server.loading", "Calculate next daily quest reset time..."); - InitDailyQuestResetTime(); - - TC_LOG_INFO("server.loading", "Calculate next weekly quest reset time..."); - InitWeeklyQuestResetTime(); - - TC_LOG_INFO("server.loading", "Calculate next monthly quest reset time..."); - InitMonthlyQuestResetTime(); + TC_LOG_INFO("server.loading", "Initializing quest reset times..."); + InitQuestResetTimes(); + CheckQuestResetTimes(); TC_LOG_INFO("server.loading", "Calculate random battleground reset time..."); InitRandomBGResetTime(); @@ -2297,20 +2308,7 @@ void World::Update(uint32 diff) } } - /// Handle daily quests reset time - if (currentGameTime > m_NextDailyQuestReset) - { - ResetDailyQuests(); - InitDailyQuestResetTime(false); - } - - /// Handle weekly quests reset time - if (currentGameTime > m_NextWeeklyQuestReset) - ResetWeeklyQuests(); - - /// Handle monthly quests reset time - if (currentGameTime > m_NextMonthlyQuestReset) - ResetMonthlyQuests(); + CheckQuestResetTimes(); if (currentGameTime > m_NextRandomBGReset) ResetRandomBG(); @@ -3132,55 +3130,123 @@ void World::_UpdateRealmCharCount(PreparedQueryResult resultCharCount) } } -void World::InitWeeklyQuestResetTime() +void World::InitQuestResetTimes() { - time_t wstime = uint64(sWorld->getWorldState(WS_WEEKLY_QUEST_RESET_TIME)); - time_t curtime = GameTime::GetGameTime(); - m_NextWeeklyQuestReset = wstime < curtime ? curtime : time_t(wstime); + m_NextDailyQuestReset = sWorld->getWorldState(WS_DAILY_QUEST_RESET_TIME); + m_NextWeeklyQuestReset = sWorld->getWorldState(WS_WEEKLY_QUEST_RESET_TIME); + m_NextMonthlyQuestReset = sWorld->getWorldState(WS_MONTHLY_QUEST_RESET_TIME); } -void World::InitDailyQuestResetTime(bool loading) +static time_t GetNextDailyResetTime(time_t t) { - time_t mostRecentQuestTime = 0; + return GetLocalHourTimestamp(t, sWorld->getIntConfig(CONFIG_DAILY_QUEST_RESET_TIME_HOUR), true); +} - if (loading) - { - QueryResult result = CharacterDatabase.Query("SELECT MAX(time) FROM character_queststatus_daily"); - if (result) - { - Field* fields = result->Fetch(); - mostRecentQuestTime = time_t(fields[0].GetUInt32()); - } - } +void World::ResetDailyQuests() +{ + // reset all saved quest status + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_DAILY); + CharacterDatabase.Execute(stmt); + // reset all quest status in memory + for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + if (Player* player = itr->second->GetPlayer()) + player->ResetDailyQuestStatus(); - // FIX ME: client not show day start time - time_t curTime = GameTime::GetGameTime(); - tm localTm; - localtime_r(&curTime, &localTm); - localTm.tm_hour = getIntConfig(CONFIG_DAILY_QUEST_RESET_TIME_HOUR); - localTm.tm_min = 0; - localTm.tm_sec = 0; + // reselect pools + sQuestPoolMgr->ChangeDailyQuests(); - // current day reset time - time_t curDayResetTime = mktime(&localTm); + // store next reset time + time_t now = GameTime::GetGameTime(); + time_t next = GetNextDailyResetTime(now); + ASSERT(now < next); + + m_NextDailyQuestReset = next; + sWorld->setWorldState(WS_DAILY_QUEST_RESET_TIME, uint64(next)); + + TC_LOG_INFO("misc", "Daily quests for all characters have been reset."); +} + +static time_t GetNextWeeklyResetTime(time_t t) +{ + t = GetNextDailyResetTime(t); + tm time = TimeBreakdown(t); + int wday = time.tm_wday; + int target = sWorld->getIntConfig(CONFIG_WEEKLY_QUEST_RESET_TIME_WDAY); + if (target < wday) + wday -= 7; + t += (DAY * (target - wday)); + return t; +} + +void World::ResetWeeklyQuests() +{ + // reset all saved quest status + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_WEEKLY); + CharacterDatabase.Execute(stmt); + // reset all quest status in memory + for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + if (Player* player = itr->second->GetPlayer()) + player->ResetWeeklyQuestStatus(); + + // reselect pools + sQuestPoolMgr->ChangeWeeklyQuests(); + + // store next reset time + time_t now = GameTime::GetGameTime(); + time_t next = GetNextWeeklyResetTime(now); + ASSERT(now < next); + + m_NextWeeklyQuestReset = next; + sWorld->setWorldState(WS_WEEKLY_QUEST_RESET_TIME, uint64(next)); + + TC_LOG_INFO("misc", "Weekly quests for all characters have been reset."); +} + +static time_t GetNextMonthlyResetTime(time_t t) +{ + t = GetNextDailyResetTime(t); + tm time = TimeBreakdown(t); + if (time.tm_mday == 1) + return t; + + time.tm_mday = 1; + time.tm_mon += 1; + return mktime(&time); +} + +void World::ResetMonthlyQuests() +{ + // reset all saved quest status + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_MONTHLY); + CharacterDatabase.Execute(stmt); + // reset all quest status in memory + for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + if (Player* player = itr->second->GetPlayer()) + player->ResetMonthlyQuestStatus(); - // last reset time before current moment - time_t resetTime = (curTime < curDayResetTime) ? curDayResetTime - DAY : curDayResetTime; + // reselect pools + sQuestPoolMgr->ChangeMonthlyQuests(); - // need reset (if we have quest time before last reset time (not processed by some reason) - if (mostRecentQuestTime && mostRecentQuestTime <= resetTime) - m_NextDailyQuestReset = mostRecentQuestTime; - else // plan next reset time - m_NextDailyQuestReset = (curTime >= curDayResetTime) ? curDayResetTime + DAY : curDayResetTime; + // store next reset time + time_t now = GameTime::GetGameTime(); + time_t next = GetNextMonthlyResetTime(now); + ASSERT(now < next); - sWorld->setWorldState(WS_DAILY_QUEST_RESET_TIME, uint64(m_NextDailyQuestReset)); + m_NextMonthlyQuestReset = next; + sWorld->setWorldState(WS_MONTHLY_QUEST_RESET_TIME, uint64(next)); + + TC_LOG_INFO("misc", "Monthly quests for all characters have been reset."); } -void World::InitMonthlyQuestResetTime() +void World::CheckQuestResetTimes() { - time_t wstime = uint64(sWorld->getWorldState(WS_MONTHLY_QUEST_RESET_TIME)); - time_t curtime = GameTime::GetGameTime(); - m_NextMonthlyQuestReset = wstime < curtime ? curtime : time_t(wstime); + time_t const now = GameTime::GetGameTime(); + if (m_NextDailyQuestReset <= now) + ResetDailyQuests(); + if (m_NextWeeklyQuestReset <= now) + ResetWeeklyQuests(); + if (m_NextMonthlyQuestReset <= now) + ResetMonthlyQuests(); } void World::InitRandomBGResetTime() @@ -3239,83 +3305,6 @@ void World::InitGuildResetTime() sWorld->setWorldState(WS_GUILD_DAILY_RESET_TIME, uint64(m_NextGuildReset)); } -void World::ResetDailyQuests() -{ - TC_LOG_INFO("misc", "Daily quests reset for all characters."); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_DAILY); - CharacterDatabase.Execute(stmt); - - for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) - if (itr->second->GetPlayer()) - itr->second->GetPlayer()->ResetDailyQuestStatus(); - - // change available dailies - sPoolMgr->ChangeDailyQuests(); -} - -void World::ResetWeeklyQuests() -{ - TC_LOG_INFO("misc", "Weekly quests reset for all characters."); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_WEEKLY); - CharacterDatabase.Execute(stmt); - - for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) - if (itr->second->GetPlayer()) - itr->second->GetPlayer()->ResetWeeklyQuestStatus(); - - m_NextWeeklyQuestReset = time_t(m_NextWeeklyQuestReset + WEEK); - sWorld->setWorldState(WS_WEEKLY_QUEST_RESET_TIME, uint64(m_NextWeeklyQuestReset)); - - // change available weeklies - sPoolMgr->ChangeWeeklyQuests(); -} - -void World::ResetMonthlyQuests() -{ - TC_LOG_INFO("misc", "Monthly quests reset for all characters."); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_MONTHLY); - CharacterDatabase.Execute(stmt); - - for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) - if (itr->second->GetPlayer()) - itr->second->GetPlayer()->ResetMonthlyQuestStatus(); - - // generate time - time_t curTime = GameTime::GetGameTime(); - tm localTm; - localtime_r(&curTime, &localTm); - - int month = localTm.tm_mon; - int year = localTm.tm_year; - - ++month; - - // month 11 is december, next is january (0) - if (month > 11) - { - month = 0; - year += 1; - } - - // reset time for next month - localTm.tm_year = year; - localTm.tm_mon = month; - localTm.tm_mday = 1; // don't know if we really need config option for day / hour - localTm.tm_hour = 0; - localTm.tm_min = 0; - localTm.tm_sec = 0; - - time_t nextMonthResetTime = mktime(&localTm); - - // plan next reset time - m_NextMonthlyQuestReset = (curTime >= nextMonthResetTime) ? nextMonthResetTime + MONTH : nextMonthResetTime; - - sWorld->setWorldState(WS_MONTHLY_QUEST_RESET_TIME, uint64(m_NextMonthlyQuestReset)); -} - void World::ResetEventSeasonalQuests(uint16 event_id) { TC_LOG_INFO("misc", "Seasonal quests reset for all characters."); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index edf310c408b..9e144de6da2 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -247,6 +247,7 @@ enum WorldIntConfigs CONFIG_INSTANCE_RESET_TIME_HOUR, CONFIG_INSTANCE_UNLOAD_DELAY, CONFIG_DAILY_QUEST_RESET_TIME_HOUR, + CONFIG_WEEKLY_QUEST_RESET_TIME_WDAY, CONFIG_MAX_PRIMARY_TRADE_SKILL, CONFIG_MIN_PETITION_SIGNS, CONFIG_MIN_QUEST_SCALED_XP_RATIO, @@ -780,14 +781,14 @@ class TC_GAME_API World // callback for UpdateRealmCharacters void _UpdateRealmCharCount(PreparedQueryResult resultCharCount); - void InitDailyQuestResetTime(bool loading = true); - void InitWeeklyQuestResetTime(); - void InitMonthlyQuestResetTime(); - void InitRandomBGResetTime(); - void InitGuildResetTime(); + void InitQuestResetTimes(); + void CheckQuestResetTimes(); void ResetDailyQuests(); void ResetWeeklyQuests(); void ResetMonthlyQuests(); + + void InitRandomBGResetTime(); + void InitGuildResetTime(); void ResetRandomBG(); void ResetGuildCap(); private: |
