Skip to content

Commit 1760ed3

Browse files
authored
Merge bfe5f68 into 0933ac2
2 parents 0933ac2 + bfe5f68 commit 1760ed3

8 files changed

Lines changed: 816 additions & 57 deletions

File tree

src/game/WorldHandlers/World.cpp

Lines changed: 228 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,11 @@
8888
#include "LFGMgr.h"
8989
#include "DisableMgr.h"
9090
#include "Language.h"
91-
#include "CommandMgr.h"
92-
#include "GitRevision.h"
93-
#include "UpdateTime.h"
94-
#include "GameTime.h"
91+
#include "CommandMgr.h"
92+
#include "GitRevision.h"
93+
#include "UpdateTime.h"
94+
#include "GameTime.h"
95+
#include "ScheduledExit.h"
9596

9697
#ifdef ENABLE_ELUNA
9798
#include "LuaEngine.h"
@@ -108,8 +109,8 @@
108109
// WARDEN
109110
#include "WardenCheckMgr.h"
110111

111-
#include <iostream>
112-
#include <sstream>
112+
#include <iostream>
113+
#include <sstream>
113114

114115
INSTANTIATE_SINGLETON_1(World);
115116

@@ -157,8 +158,10 @@ World::World()
157158
m_startTime = m_gameTime;
158159
m_maxActiveSessionCount = 0;
159160
m_maxQueuedSessionCount = 0;
160-
m_MaintenanceTimeChecker = 0;
161-
m_broadcastEnable = false;
161+
m_MaintenanceTimeChecker = 0;
162+
m_scheduledExitDelay = 0;
163+
m_scheduledExitCountdownActive = false;
164+
m_broadcastEnable = false;
162165
m_broadcastList.clear();
163166
m_broadcastWeight = 0;
164167

@@ -578,7 +581,7 @@ void World::LoadConfigSettings(bool reload)
578581
setConfig(CONFIG_UINT32_MAX_WHOLIST_RETURNS, "MaxWhoListReturns", 49);
579582
setConfig(CONFIG_UINT32_AUTOBROADCAST_INTERVAL, "AutoBroadcast", 600);
580583

581-
if (getConfig(CONFIG_UINT32_AUTOBROADCAST_INTERVAL) > 0)
584+
if (getConfig(CONFIG_UINT32_AUTOBROADCAST_INTERVAL) > 0)
582585
{
583586
m_broadcastEnable = true;
584587
}
@@ -590,9 +593,11 @@ void World::LoadConfigSettings(bool reload)
590593
if (reload && m_broadcastEnable)
591594
{
592595
m_broadcastTimer.SetInterval(getConfig(CONFIG_UINT32_AUTOBROADCAST_INTERVAL) * IN_MILLISECONDS);
593-
}
594-
595-
std::string forceLoadGridOnMaps = sConfig.GetStringDefault("LoadAllGridsOnMaps", "");
596+
}
597+
598+
LoadScheduledExitConfig();
599+
600+
std::string forceLoadGridOnMaps = sConfig.GetStringDefault("LoadAllGridsOnMaps", "");
596601
if (!forceLoadGridOnMaps.empty())
597602
{
598603
unsigned int pos = 0;
@@ -2182,7 +2187,7 @@ void World::_UpdateGameTime()
21822187
m_gameTime = thisTime;
21832188

21842189
///- if there is a shutdown timer
2185-
if (!m_stopEvent && m_ShutdownTimer > 0 && elapsed > 0)
2190+
if (!m_stopEvent && m_ShutdownTimer > 0 && elapsed > 0)
21862191
{
21872192
///- ... and it is overdue, stop the world (set m_stopEvent)
21882193
if (m_ShutdownTimer <= elapsed)
@@ -2197,17 +2202,28 @@ void World::_UpdateGameTime()
21972202
} // minimum timer value to wait idle state
21982203
}
21992204
///- ... else decrease it and if necessary display a shutdown countdown to the users
2200-
else
2201-
{
2202-
m_ShutdownTimer -= elapsed;
2203-
2204-
ShutdownMsg();
2205-
}
2206-
}
2207-
}
2205+
else
2206+
{
2207+
m_ShutdownTimer -= elapsed;
2208+
2209+
MaNGOS::ScheduledExitCountdownActions actions = MaNGOS::GetScheduledExitCountdownActions(m_scheduledExitCountdownActive);
2210+
if (actions.sendShutdownTimer)
2211+
{
2212+
ShutdownMsg();
2213+
}
2214+
2215+
if (actions.sendConfiguredWarnings)
2216+
{
2217+
SendScheduledExitWarnings();
2218+
}
2219+
}
2220+
}
2221+
2222+
CheckScheduledExit();
2223+
}
22082224

22092225
/// Shutdown the server
2210-
void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode)
2226+
void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode)
22112227
{
22122228
// ignore if server shutdown at next tick
22132229
if (m_stopEvent)
@@ -2235,8 +2251,8 @@ void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode)
22352251
else
22362252
{
22372253
m_ShutdownTimer = time;
2238-
ShutdownMsg(true);
2239-
}
2254+
ShutdownMsg(true);
2255+
}
22402256

22412257
#ifdef ENABLE_PLAYERBOTS
22422258
sRandomPlayerbotMgr.LogoutAllBots();
@@ -2249,14 +2265,189 @@ void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode)
22492265
e->OnShutdownInitiate(ShutdownExitCode(exitcode), ShutdownMask(options));
22502266
}
22512267
#endif /* ENABLE_ELUNA */
2252-
}
2253-
2254-
/// Display a shutdown message to the user(s)
2255-
void World::ShutdownMsg(bool show /*= false*/, Player* player /*= NULL*/)
2256-
{
2257-
// not show messages for idle shutdown mode
2258-
if (m_ShutdownMask & SHUTDOWN_MASK_IDLE)
2259-
{
2268+
}
2269+
2270+
void World::LoadScheduledExitConfig()
2271+
{
2272+
m_scheduledExit = MaNGOS::ScheduledExitSchedule();
2273+
m_scheduledExitDelay = 0;
2274+
m_scheduledExitWarnings.clear();
2275+
m_scheduledExitCountdownActive = false;
2276+
2277+
if (!sConfig.GetBoolDefault("ScheduledExit.Enable", false))
2278+
{
2279+
sLog.outString("ScheduledExit: disabled");
2280+
return;
2281+
}
2282+
2283+
std::string dayText = sConfig.GetStringDefault("ScheduledExit.DayOfWeek", "3");
2284+
uint32 dayOfWeek = 0;
2285+
if (!MaNGOS::ParseScheduledExitUInt32(dayText, dayOfWeek) || dayOfWeek > 6)
2286+
{
2287+
sLog.outError("ScheduledExit: invalid ScheduledExit.DayOfWeek '%s'; disabling scheduled exit", dayText.c_str());
2288+
return;
2289+
}
2290+
2291+
std::string timeText = sConfig.GetStringDefault("ScheduledExit.Time", "05:00");
2292+
uint32 hour = 0;
2293+
uint32 minute = 0;
2294+
if (!MaNGOS::ParseScheduledExitTime(timeText, hour, minute))
2295+
{
2296+
sLog.outError("ScheduledExit: invalid ScheduledExit.Time '%s'; disabling scheduled exit", timeText.c_str());
2297+
return;
2298+
}
2299+
2300+
std::string modeText = sConfig.GetStringDefault("ScheduledExit.Mode", "restart");
2301+
MaNGOS::ScheduledExitMode mode = MaNGOS::SCHEDULED_EXIT_MODE_RESTART;
2302+
if (!MaNGOS::ParseScheduledExitMode(modeText, mode))
2303+
{
2304+
sLog.outError("ScheduledExit: invalid ScheduledExit.Mode '%s'; disabling scheduled exit", modeText.c_str());
2305+
return;
2306+
}
2307+
2308+
std::string delayText = sConfig.GetStringDefault("ScheduledExit.Delay", "900");
2309+
uint32 delay = 0;
2310+
if (!MaNGOS::ParseScheduledExitUInt32(delayText, delay))
2311+
{
2312+
sLog.outError("ScheduledExit: invalid ScheduledExit.Delay '%s'; disabling scheduled exit", delayText.c_str());
2313+
return;
2314+
}
2315+
2316+
std::vector<std::string> warningErrors;
2317+
std::vector<uint32> warningTimes = MaNGOS::ParseScheduledExitWarningTimes(
2318+
sConfig.GetStringDefault("ScheduledExit.WarningTimes", "900,600,300,60"), delay, warningErrors);
2319+
2320+
for (std::vector<std::string>::const_iterator itr = warningErrors.begin(); itr != warningErrors.end(); ++itr)
2321+
{
2322+
sLog.outError("ScheduledExit: ignoring %s", itr->c_str());
2323+
}
2324+
2325+
for (std::vector<uint32>::const_iterator itr = warningTimes.begin(); itr != warningTimes.end(); ++itr)
2326+
{
2327+
if (*itr == 0)
2328+
{
2329+
sLog.outError("ScheduledExit: ignoring warning milestone 0");
2330+
continue;
2331+
}
2332+
2333+
std::ostringstream configKey;
2334+
configKey << "ScheduledExit.WarningText." << *itr;
2335+
2336+
ScheduledExitWarning warning;
2337+
warning.remainingSeconds = *itr;
2338+
warning.text = sConfig.GetStringDefault(configKey.str().c_str(), "");
2339+
if (warning.text.empty())
2340+
{
2341+
warning.text = MaNGOS::BuildScheduledExitWarningText(mode, *itr);
2342+
}
2343+
warning.sent = false;
2344+
m_scheduledExitWarnings.push_back(warning);
2345+
}
2346+
2347+
m_scheduledExit.enabled = true;
2348+
m_scheduledExit.dayOfWeek = dayOfWeek;
2349+
m_scheduledExit.hour = hour;
2350+
m_scheduledExit.minute = minute;
2351+
m_scheduledExit.mode = mode;
2352+
m_scheduledExitDelay = delay;
2353+
2354+
if (MaNGOS::MarkScheduledExitHandledIfMatching(m_scheduledExit, safe_localtime(time(NULL)), m_scheduledExitState))
2355+
{
2356+
sLog.outString("ScheduledExit: startup minute matches configured schedule; suppressing this minute to avoid restart loop");
2357+
}
2358+
2359+
std::ostringstream milestones;
2360+
for (std::vector<ScheduledExitWarning>::const_iterator itr = m_scheduledExitWarnings.begin(); itr != m_scheduledExitWarnings.end(); ++itr)
2361+
{
2362+
if (itr != m_scheduledExitWarnings.begin())
2363+
{
2364+
milestones << ",";
2365+
}
2366+
milestones << itr->remainingSeconds;
2367+
}
2368+
2369+
sLog.outString("ScheduledExit: enabled day=%u time=%02u:%02u mode=%s delay=%u warningTimes=%s",
2370+
m_scheduledExit.dayOfWeek, m_scheduledExit.hour, m_scheduledExit.minute,
2371+
MaNGOS::ScheduledExitModeToString(m_scheduledExit.mode), m_scheduledExitDelay,
2372+
milestones.str().c_str());
2373+
}
2374+
2375+
void World::CheckScheduledExit()
2376+
{
2377+
if (!m_scheduledExit.enabled || m_stopEvent)
2378+
{
2379+
return;
2380+
}
2381+
2382+
if (!MaNGOS::CheckAndMarkScheduledExit(m_scheduledExit, safe_localtime(m_gameTime), m_scheduledExitState))
2383+
{
2384+
return;
2385+
}
2386+
2387+
if (m_ShutdownTimer > 0)
2388+
{
2389+
sLog.outString("ScheduledExit: %s scheduled for day=%u time=%02u:%02u skipped because shutdown/restart is already in progress",
2390+
MaNGOS::ScheduledExitModeToString(m_scheduledExit.mode), m_scheduledExit.dayOfWeek, m_scheduledExit.hour, m_scheduledExit.minute);
2391+
return;
2392+
}
2393+
2394+
StartScheduledExit();
2395+
}
2396+
2397+
void World::StartScheduledExit()
2398+
{
2399+
uint32 mask = m_scheduledExit.mode == MaNGOS::SCHEDULED_EXIT_MODE_RESTART ? SHUTDOWN_MASK_RESTART : SHUTDOWN_MASK_STOP;
2400+
uint8 exitCode = m_scheduledExit.mode == MaNGOS::SCHEDULED_EXIT_MODE_RESTART ? RESTART_EXIT_CODE : SHUTDOWN_EXIT_CODE;
2401+
2402+
sLog.outString("ScheduledExit: firing scheduled %s with delay %u seconds",
2403+
MaNGOS::ScheduledExitModeToString(m_scheduledExit.mode), m_scheduledExitDelay);
2404+
2405+
ResetScheduledExitWarnings();
2406+
m_scheduledExitCountdownActive = m_scheduledExitDelay > 0;
2407+
ShutdownServ(m_scheduledExitDelay, mask, exitCode);
2408+
2409+
if (m_scheduledExitCountdownActive)
2410+
{
2411+
SendScheduledExitWarnings();
2412+
}
2413+
}
2414+
2415+
void World::ResetScheduledExitWarnings()
2416+
{
2417+
for (std::vector<ScheduledExitWarning>::iterator itr = m_scheduledExitWarnings.begin(); itr != m_scheduledExitWarnings.end(); ++itr)
2418+
{
2419+
itr->sent = false;
2420+
}
2421+
}
2422+
2423+
void World::SendScheduledExitWarnings()
2424+
{
2425+
if (!m_scheduledExitCountdownActive || !m_ShutdownTimer)
2426+
{
2427+
return;
2428+
}
2429+
2430+
for (std::vector<ScheduledExitWarning>::iterator itr = m_scheduledExitWarnings.begin(); itr != m_scheduledExitWarnings.end(); ++itr)
2431+
{
2432+
if (!itr->sent && m_ShutdownTimer <= itr->remainingSeconds)
2433+
{
2434+
SendScheduledExitWarning(*itr);
2435+
}
2436+
}
2437+
}
2438+
2439+
void World::SendScheduledExitWarning(ScheduledExitWarning& warning)
2440+
{
2441+
warning.sent = true;
2442+
SendServerMessage(SERVER_MSG_CUSTOM, warning.text.c_str());
2443+
}
2444+
2445+
/// Display a shutdown message to the user(s)
2446+
void World::ShutdownMsg(bool show /*= false*/, Player* player /*= NULL*/)
2447+
{
2448+
// not show messages for idle shutdown mode
2449+
if (m_ShutdownMask & SHUTDOWN_MASK_IDLE)
2450+
{
22602451
return;
22612452
}
22622453

@@ -2278,7 +2469,7 @@ void World::ShutdownMsg(bool show /*= false*/, Player* player /*= NULL*/)
22782469
}
22792470

22802471
/// Cancel a planned server shutdown
2281-
void World::ShutdownCancel()
2472+
void World::ShutdownCancel()
22822473
{
22832474
// nothing cancel or too later
22842475
if (!m_ShutdownTimer || m_stopEvent)
@@ -2288,8 +2479,10 @@ void World::ShutdownCancel()
22882479

22892480
ServerMessageType msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_CANCELLED : SERVER_MSG_SHUTDOWN_CANCELLED;
22902481

2291-
m_ShutdownMask = 0;
2292-
m_ShutdownTimer = 0;
2482+
m_ShutdownMask = 0;
2483+
m_ShutdownTimer = 0;
2484+
m_scheduledExitCountdownActive = false;
2485+
ResetScheduledExitWarnings();
22932486
m_ExitCode = SHUTDOWN_EXIT_CODE; // to default value
22942487
SendServerMessage(msgid);
22952488

0 commit comments

Comments
 (0)