aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/World
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2019-08-04 12:22:57 +0200
committerGitHub <noreply@github.com>2019-08-04 12:22:57 +0200
commita5e73e41c0e813e674bb0a644e0052052435494e (patch)
treecabbeadc1e07635f1a8fc53599895613cbe61723 /src/server/game/World
parent15e85f882fdb7b5d1d48302907e76c993ee4e923 (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.cpp259
-rw-r--r--src/server/game/World/World.h11
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: