feat(Core/Battlefield): defer server restart during Wintergrasp (#26461)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Andrew
2026-07-04 15:53:10 -03:00
committed by GitHub
parent f8a0c2f608
commit f76595cf80
7 changed files with 64 additions and 5 deletions
@@ -0,0 +1,4 @@
--
DELETE FROM `acore_string` WHERE `entry` = 35455;
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
(35455, 'A Wintergrasp battle is in progress. The scheduled server maintenance has been postponed.', '겨울손아귀 전투가 진행 중입니다. 예정된 서버 점검이 연기되었습니다.', 'Une bataille du Joug-d''hiver est en cours. La maintenance programmée du serveur a été reportée.', 'Eine Schlacht um Tausendwinter ist im Gange. Die geplante Serverwartung wurde verschoben.', '冬拥湖战斗正在进行中。计划中的服务器维护已被推迟。', '冬擁湖戰鬥正在進行中。排定的伺服器維護已延後。', 'Hay una batalla de Templo Helado en curso. El mantenimiento programado del servidor se ha pospuesto.', 'Hay una batalla de Templo Helado en curso. El mantenimiento programado del servidor se ha pospuesto.', 'Идёт битва за Ледяную Грудь. Плановое обслуживание сервера отложено.');
@@ -3734,6 +3734,17 @@ Wintergrasp.KickVoAPlayers = 1
Wintergrasp.EssenceBothFactions = 0
#
# Wintergrasp.DeferShutdownTimer
# Description: Defer a scheduled server shutdown/restart if a Wintergrasp battle
# is still in progress when the countdown elapses. It is rescheduled
# to the battle's remaining time plus this many minutes of buffer.
# Idle shutdowns are not affected.
# Default: 0 - (Disabled)
# N - (Enabled, defer to remaining battle time + N minutes)
Wintergrasp.DeferShutdownTimer = 0
#
###################################################################################################
+4 -1
View File
@@ -1517,6 +1517,9 @@ enum AcoreStrings
// Pet rename command
LANG_PET_RENAME_INVALID = 35453,
LANG_PET_RENAME_SUCCESS = 35454
LANG_PET_RENAME_SUCCESS = 35454,
// Wintergrasp shutdown deferral
LANG_WG_SHUTDOWN_DEFERRED = 35455
};
#endif
+42 -4
View File
@@ -56,6 +56,7 @@
#include "InstanceSaveMgr.h"
#include "ItemEnchantmentMgr.h"
#include "LFGMgr.h"
#include "Language.h"
#include "Log.h"
#include "LootItemStorage.h"
#include "LootMgr.h"
@@ -1450,10 +1451,15 @@ void World::_UpdateGameTime()
///- ... and it is overdue, stop the world (set m_stopEvent)
if (_shutdownTimer <= elapsed.count())
{
if (!(_shutdownMask & SHUTDOWN_MASK_IDLE) || sWorldSessionMgr->GetActiveAndQueuedSessionCount() == 0)
_stopEvent = true; // exist code already set
else
_shutdownTimer = 1; // minimum timer value to wait idle state
///- ... unless a Wintergrasp battle is running and deferral is enabled, in which case the
/// shutdown/restart is pushed past the end of the current battle and the world keeps running
if (!RescheduleShutdownForWintergrasp())
{
if (!(_shutdownMask & SHUTDOWN_MASK_IDLE) || sWorldSessionMgr->GetActiveAndQueuedSessionCount() == 0)
_stopEvent = true; // exist code already set
else
_shutdownTimer = 1; // minimum timer value to wait idle state
}
}
///- ... else decrease it and if necessary display a shutdown countdown to the users
else
@@ -1465,6 +1471,38 @@ void World::_UpdateGameTime()
}
}
/// Defer a pending shutdown/restart if a Wintergrasp battle is currently running.
/// Returns true when the shutdown timer was extended (world should keep running).
bool World::RescheduleShutdownForWintergrasp()
{
uint32 const bufferMinutes = getIntConfig(CONFIG_WINTERGRASP_DEFER_SHUTDOWN);
if (!bufferMinutes)
return false;
// Idle shutdowns wait for an empty server anyway; don't interfere with them
if (_shutdownMask & SHUTDOWN_MASK_IDLE)
return false;
Battlefield* wg = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG);
if (!wg || !wg->IsEnabled() || !wg->IsWarTime())
return false;
// GetTimer() is the battle time remaining in milliseconds
_shutdownTimer = wg->GetTimer() / IN_MILLISECONDS + bufferMinutes * MINUTE;
LOG_INFO("server.worldserver", "Server {} deferred: Wintergrasp battle in progress, rescheduled in {}",
(_shutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shutdown"), secsToTimeString(_shutdownTimer));
sWorldSessionMgr->DoForAllOnlinePlayers([](Player* player)
{
LocaleConstant locale = player->GetSession()->GetSessionDbLocaleIndex();
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, sObjectMgr->GetAcoreString(LANG_WG_SHUTDOWN_DEFERRED, locale), player);
});
ShutdownMsg(true);
return true;
}
/// Shutdown the server
void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode, std::string const& reason)
{
+1
View File
@@ -242,6 +242,7 @@ public:
protected:
void _UpdateGameTime();
bool RescheduleShutdownForWintergrasp();
// callback for UpdateRealmCharacters
void _UpdateRealmCharCount(PreparedQueryResult resultCharCount,uint32 accountId);
+1
View File
@@ -613,6 +613,7 @@ void WorldConfig::BuildConfigCache()
SetConfigValue<uint32>(CONFIG_WINTERGRASP_SKIP_BATTLE_SESSION_COUNT, "Wintergrasp.SkipBattleSessionCount", 3500);
SetConfigValue<bool>(CONFIG_WINTERGRASP_KICK_VOA_PLAYERS, "Wintergrasp.KickVoAPlayers", true, ConfigValueCache::Reloadable::No);
SetConfigValue<bool>(CONFIG_WINTERGRASP_ESSENCE_BOTH_FACTIONS, "Wintergrasp.EssenceBothFactions", false);
SetConfigValue<uint32>(CONFIG_WINTERGRASP_DEFER_SHUTDOWN, "Wintergrasp.DeferShutdownTimer", 0);
SetConfigValue<uint32>(CONFIG_BIRTHDAY_TIME, "BirthdayTime", 1222964635);
SetConfigValue<bool>(CONFIG_MINIGOB_MANABONK, "Minigob.Manabonk.Enable", true);
+1
View File
@@ -332,6 +332,7 @@ enum ServerConfigs
CONFIG_WINTERGRASP_SKIP_BATTLE_SESSION_COUNT,
CONFIG_WINTERGRASP_KICK_VOA_PLAYERS,
CONFIG_WINTERGRASP_ESSENCE_BOTH_FACTIONS,
CONFIG_WINTERGRASP_DEFER_SHUTDOWN,
CONFIG_PACKET_SPOOF_BANMODE,
CONFIG_PACKET_SPOOF_BANDURATION,
CONFIG_WARDEN_CLIENT_RESPONSE_DELAY,