diff --git a/data/sql/updates/pending_db_world/rev_1783176822547680700.sql b/data/sql/updates/pending_db_world/rev_1783176822547680700.sql new file mode 100644 index 0000000000..9766608c14 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1783176822547680700.sql @@ -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.', 'Идёт битва за Ледяную Грудь. Плановое обслуживание сервера отложено.'); diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index c688d98d1d..7b16a07cbe 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -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 + # ################################################################################################### diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 20bd52792c..a3cf7b59da 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -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 diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 9c2147dc20..c416a6080e 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -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) { diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index b0499a7412..0f2eb0e80d 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -242,6 +242,7 @@ public: protected: void _UpdateGameTime(); + bool RescheduleShutdownForWintergrasp(); // callback for UpdateRealmCharacters void _UpdateRealmCharCount(PreparedQueryResult resultCharCount,uint32 accountId); diff --git a/src/server/game/World/WorldConfig.cpp b/src/server/game/World/WorldConfig.cpp index 0a45ae06ed..1cc9cd9975 100644 --- a/src/server/game/World/WorldConfig.cpp +++ b/src/server/game/World/WorldConfig.cpp @@ -613,6 +613,7 @@ void WorldConfig::BuildConfigCache() SetConfigValue(CONFIG_WINTERGRASP_SKIP_BATTLE_SESSION_COUNT, "Wintergrasp.SkipBattleSessionCount", 3500); SetConfigValue(CONFIG_WINTERGRASP_KICK_VOA_PLAYERS, "Wintergrasp.KickVoAPlayers", true, ConfigValueCache::Reloadable::No); SetConfigValue(CONFIG_WINTERGRASP_ESSENCE_BOTH_FACTIONS, "Wintergrasp.EssenceBothFactions", false); + SetConfigValue(CONFIG_WINTERGRASP_DEFER_SHUTDOWN, "Wintergrasp.DeferShutdownTimer", 0); SetConfigValue(CONFIG_BIRTHDAY_TIME, "BirthdayTime", 1222964635); SetConfigValue(CONFIG_MINIGOB_MANABONK, "Minigob.Manabonk.Enable", true); diff --git a/src/server/game/World/WorldConfig.h b/src/server/game/World/WorldConfig.h index ce358389ed..dd0707fcef 100644 --- a/src/server/game/World/WorldConfig.h +++ b/src/server/game/World/WorldConfig.h @@ -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,