From a74e06c27c592bbd9b4203fbb68c4a425ceff0be Mon Sep 17 00:00:00 2001 From: Exitare Date: Sun, 26 Jan 2025 00:37:32 -0800 Subject: [PATCH] feat(Core/Autobroacast): Add autobroadcast locale (#20946) --- .../rev_1734400454914932600.sql | 11 ++ .../Database/Implementation/LoginDatabase.cpp | 1 + .../Database/Implementation/LoginDatabase.h | 1 + .../game/Autobroadcast/AutobroadcastMgr.cpp | 116 ++++++++++++++---- .../game/Autobroadcast/AutobroadcastMgr.h | 12 +- src/server/game/World/World.cpp | 1 + 6 files changed, 112 insertions(+), 30 deletions(-) create mode 100644 data/sql/updates/pending_db_auth/rev_1734400454914932600.sql diff --git a/data/sql/updates/pending_db_auth/rev_1734400454914932600.sql b/data/sql/updates/pending_db_auth/rev_1734400454914932600.sql new file mode 100644 index 000000000..5018ad411 --- /dev/null +++ b/data/sql/updates/pending_db_auth/rev_1734400454914932600.sql @@ -0,0 +1,11 @@ +DROP TABLE IF EXISTS `autobroadcast_locale`; +CREATE TABLE `autobroadcast_locale` ( + `realmid` INT NOT NULL, + `id` INT NOT NULL, + `locale` VARCHAR(4) NOT NULL, + `text` VARCHAR(45) NULL, + PRIMARY KEY (`realmid`, `id`)) +CHARSET = utf8mb4 +COLLATE = utf8mb4_unicode_ci +ENGINE = InnoDB +; diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp index 51eb7d8ec..019e11c8d 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.cpp +++ b/src/server/database/Database/Implementation/LoginDatabase.cpp @@ -115,6 +115,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL, "SELECT allowedSecurityLevel from realmlist WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_DEL_ACCOUNT, "DELETE FROM account WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_AUTOBROADCAST, "SELECT id, weight, text FROM autobroadcast WHERE realmid = ? OR realmid = -1", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_AUTOBROADCAST_LOCALIZED, "SELECT id, locale, text FROM autobroadcast_locale WHERE realmid = ? OR realmid = -1", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_MOTD, "SELECT text FROM motd WHERE realmid = ? OR realmid = -1 ORDER BY realmid DESC", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_MOTD_LOCALE, "SELECT locale, text FROM motd_localized WHERE realmid = ? OR realmid = -1 ORDER BY realmid DESC", CONNECTION_SYNCH); PrepareStatement(LOGIN_INS_MOTD, "INSERT INTO motd (realmid, text) VALUES (?, ?) ON DUPLICATE KEY UPDATE text = ?", CONNECTION_ASYNC); diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h index f6791ac80..1c859695c 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.h +++ b/src/server/database/Database/Implementation/LoginDatabase.h @@ -97,6 +97,7 @@ enum LoginDatabaseStatements : uint32 LOGIN_SEL_REALMLIST_SECURITY_LEVEL, LOGIN_DEL_ACCOUNT, LOGIN_SEL_AUTOBROADCAST, + LOGIN_SEL_AUTOBROADCAST_LOCALIZED, LOGIN_SEL_MOTD, LOGIN_SEL_MOTD_LOCALE, LOGIN_INS_MOTD, diff --git a/src/server/game/Autobroadcast/AutobroadcastMgr.cpp b/src/server/game/Autobroadcast/AutobroadcastMgr.cpp index 8b31bf893..a7756c658 100644 --- a/src/server/game/Autobroadcast/AutobroadcastMgr.cpp +++ b/src/server/game/Autobroadcast/AutobroadcastMgr.cpp @@ -42,7 +42,6 @@ void AutobroadcastMgr::LoadAutobroadcasts() if (!result) { LOG_WARN("autobroadcast", ">> Loaded 0 autobroadcasts definitions. DB table `autobroadcast` is empty for this realm!"); - LOG_INFO("autobroadcast", " "); return; } @@ -54,35 +53,66 @@ void AutobroadcastMgr::LoadAutobroadcasts() _announceType = AnnounceType::World; } - uint32 count = 0; + do + { + Field* fields = result->Fetch(); + uint8 textId = fields[0].Get(); + + ObjectMgr::AddLocaleString(fields[2].Get(), DEFAULT_LOCALE, _autobroadcasts[textId]); + _autobroadcastsWeights[textId] = fields[1].Get(); + + } while (result->NextRow()); + + LOG_INFO("server.loading", ">> Loaded {} Autobroadcast Definitions in {} ms", _autobroadcasts.size(), GetMSTimeDiffToNow(oldMSTime)); +} + +void AutobroadcastMgr::LoadAutobroadcastsLocalized() +{ + uint32 oldMSTime = getMSTime(); + uint32 realmId = sConfigMgr->GetOption("RealmID", 0); + + if (_autobroadcasts.empty()) + return; + + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_AUTOBROADCAST_LOCALIZED); + stmt->SetData(0, realmId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + if (!result) + { + LOG_WARN("server.loading", ">> Loaded 0 localized autobroadcasts definitions. DB table `autobroadcast_localized` is empty for this realm!"); + LOG_INFO("server.loading", " "); + return; + } + + uint8 count = 0; do { Field* fields = result->Fetch(); - uint8 id = fields[0].Get(); + uint8 textId = fields[0].Get(); + LocaleConstant locale = GetLocaleByName(fields[1].Get()); - _autobroadcasts[id] = fields[2].Get(); - _autobroadcastsWeights[id] = fields[1].Get(); + if (locale == DEFAULT_LOCALE || ObjectMgr::GetLocaleString(_autobroadcasts[textId], DEFAULT_LOCALE).empty()) + continue; - ++count; + ObjectMgr::AddLocaleString(fields[2].Get(), locale, _autobroadcasts[textId]); + count++; } while (result->NextRow()); - LOG_INFO("autobroadcast", ">> Loaded {} Autobroadcast Definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); - LOG_INFO("autobroadcast", " "); + LOG_INFO("server.loading", ">> Loaded {} Localized Autobroadcast Definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); + LOG_INFO("server.loading", " "); } void AutobroadcastMgr::SendAutobroadcasts() { if (_autobroadcasts.empty()) - { return; - } uint32 weight = 0; + uint8 textId = 0; AutobroadcastsWeightMap selectionWeights; - std::string msg; - for (AutobroadcastsWeightMap::const_iterator it = _autobroadcastsWeights.begin(); it != _autobroadcastsWeights.end(); ++it) { if (it->second) @@ -101,42 +131,78 @@ void AutobroadcastMgr::SendAutobroadcasts() weight += it->second; if (selectedWeight < weight) { - msg = _autobroadcasts[it->first]; + textId = it->first; break; } } } else { - msg = _autobroadcasts[urand(0, _autobroadcasts.size())]; + textId = urand(0, _autobroadcasts.size()); } switch (_announceType) { case AnnounceType::World: - SendWorldAnnouncement(msg); + SendWorldAnnouncement(textId); break; case AnnounceType::Notification: - SendNotificationAnnouncement(msg); + SendNotificationAnnouncement(textId); break; case AnnounceType::Both: - SendWorldAnnouncement(msg); - SendNotificationAnnouncement(msg); + SendWorldAnnouncement(textId); + SendNotificationAnnouncement(textId); default: break; } - LOG_DEBUG("autobroadcast", "AutobroadcastMgr::SendAutobroadcasts: '{}'", msg); + LOG_DEBUG("autobroadcast", "AutobroadcastMgr::SendAutobroadcasts: '{}'", textId); } -void AutobroadcastMgr::SendWorldAnnouncement(std::string msg) +void AutobroadcastMgr::SendWorldAnnouncement(uint8 textId) { - ChatHandler(nullptr).SendWorldTextOptional(LANG_AUTO_BROADCAST, ANNOUNCER_FLAG_DISABLE_AUTOBROADCAST, msg.data()); + // Send localized messages to all sessions + ChatHandler(nullptr).DoForAllValidSessions([&](Player* player) + { + // Get player's locale + LocaleConstant locale = player->GetSession()->GetSessionDbLocaleIndex(); + + if (!_autobroadcasts.empty()) + return; + + std::string_view localizedMessage = ObjectMgr::GetLocaleString(_autobroadcasts[textId], locale); + + // Check if there is a localized message if not use default one. + if (localizedMessage.empty()) + localizedMessage = ObjectMgr::GetLocaleString(_autobroadcasts[textId], DEFAULT_LOCALE); + + // Send the localized or fallback message + ChatHandler(player->GetSession()).SendWorldTextOptional(localizedMessage, ANNOUNCER_FLAG_DISABLE_AUTOBROADCAST); + }); } -void AutobroadcastMgr::SendNotificationAnnouncement(std::string msg) +void AutobroadcastMgr::SendNotificationAnnouncement(uint8 textId) { - WorldPacket data(SMSG_NOTIFICATION, (msg.size() + 1)); - data << msg.data(); - sWorld->SendGlobalMessage(&data); + ChatHandler(nullptr).DoForAllValidSessions([&](Player* player) + { + // Retrieve player's locale + LocaleConstant locale = player->GetSession()->GetSessionDbLocaleIndex(); + + if (!_autobroadcasts.count(textId)) + return; + + // Get localized message + std::string_view localizedMessage = ObjectMgr::GetLocaleString(_autobroadcasts[textId], locale); + + // Check if there is a localized message if not use default one. + if (localizedMessage.empty()) + localizedMessage = ObjectMgr::GetLocaleString(_autobroadcasts[textId], DEFAULT_LOCALE); + + // Prepare the WorldPacket + WorldPacket data(SMSG_NOTIFICATION, (localizedMessage.size() + 1)); + data << localizedMessage; + + // Send packet to the player + player->GetSession()->SendPacket(&data); + }); } diff --git a/src/server/game/Autobroadcast/AutobroadcastMgr.h b/src/server/game/Autobroadcast/AutobroadcastMgr.h index 3f4066e91..05dc6319e 100644 --- a/src/server/game/Autobroadcast/AutobroadcastMgr.h +++ b/src/server/game/Autobroadcast/AutobroadcastMgr.h @@ -20,6 +20,7 @@ #include "Common.h" #include +#include enum class AnnounceType : uint8 { @@ -34,17 +35,18 @@ public: static AutobroadcastMgr* instance(); void LoadAutobroadcasts(); + void LoadAutobroadcastsLocalized(); void SendAutobroadcasts(); private: - void SendWorldAnnouncement(std::string msg); - void SendNotificationAnnouncement(std::string msg); + void SendWorldAnnouncement(uint8 textId); + void SendNotificationAnnouncement(uint8 textId); - typedef std::map AutobroadcastsMap; + typedef std::map> AutobroadcastsMap; typedef std::map AutobroadcastsWeightMap; - AutobroadcastsMap _autobroadcasts; - AutobroadcastsWeightMap _autobroadcastsWeights; + AutobroadcastsMap _autobroadcasts; // autobroadcast messages + AutobroadcastsWeightMap _autobroadcastsWeights; // Weights for each message AnnounceType _announceType; }; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index a6bf64577..3e7dd681b 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -2028,6 +2028,7 @@ void World::SetInitialWorldSettings() ///- Load AutoBroadCast LOG_INFO("server.loading", "Loading Autobroadcasts..."); sAutobroadcastMgr->LoadAutobroadcasts(); + sAutobroadcastMgr->LoadAutobroadcastsLocalized(); ///- Load Motd LOG_INFO("server.loading", "Loading Motd...");