mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-03-16 22:15:15 +00:00
feat(Core/Motd): Allow localized motd (#20542)
* Initial commit for localized motd * Rename function that created world packages * Update to satisfy code check * Update code to accomodate localized motd * Update command to support multiple optionales & adjusted db * Code cleanup * Update sql name * Fix codestyle issues * Remove hardcoded schema * Add check for valid player in reload command * Update to better code style * Add missing include * Fix redundant code usage * Add missing include * Remove sql files and create new rev sql files * Address minor code reviews * Fix code style * Update code to address code revisions. - Remove two unused functions - Remove map - Use available function to resolve LocaleConstant * Fix code style * Add check for base motd and update locale to DEFAULT_LOCALE * Code docs * Removed some docs, readd defaultd motd formatting * Fix oversight in variable declaration * Code style fix * Update code based on code review * ready for merge * Fix set motd command due to changes to DEFAULT_LOCALE * Fix CI * Fix trailing whitespace --------- Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>
This commit is contained in:
10
data/sql/updates/pending_db_auth/rev_1731984288401879600.sql
Normal file
10
data/sql/updates/pending_db_auth/rev_1731984288401879600.sql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS `motd_localized` (
|
||||||
|
`realmid` INT,
|
||||||
|
`locale` VARCHAR(4) NOT NULL COLLATE 'utf8mb4_unicode_ci',
|
||||||
|
`text` LONGTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
|
||||||
|
PRIMARY KEY (`realmid`, `locale`)
|
||||||
|
)
|
||||||
|
CHARSET = utf8mb4
|
||||||
|
COLLATE = utf8mb4_unicode_ci
|
||||||
|
ENGINE = InnoDB
|
||||||
|
;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
--
|
||||||
|
UPDATE `command` SET `help` = 'Syntax: .server set motd Optional($realmId) Optional($locale) $MOTD\r \r Set server Message of the day for the specified $realmId.\r If $realmId is not provided it will update for the current realm. \r Use $realmId -1 to set motd for all realms. If $locale is not provided enUS will be used.' WHERE (`name` = 'server set motd');
|
||||||
|
|
||||||
|
UPDATE `acore_string` SET `content_default` = 'Message of the day in realm {} and locale {} changed to:\r {}', `locale_deDE` = 'Nachricht des Tages für Realm {} und Sprache {} wurde geändert zu:\r {}', `locale_zhCN` = '每日消息更改为 in realm {} and locale {}:\r {}' WHERE (`entry` = 1101);
|
||||||
@@ -41,6 +41,16 @@ LocaleConstant GetLocaleByName(const std::string& name)
|
|||||||
return LOCALE_enUS; // including enGB case
|
return LOCALE_enUS; // including enGB case
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string GetNameByLocaleConstant(LocaleConstant localeConstant)
|
||||||
|
{
|
||||||
|
if (localeConstant < TOTAL_LOCALES)
|
||||||
|
{
|
||||||
|
return localeNames[localeConstant];
|
||||||
|
}
|
||||||
|
|
||||||
|
return "enUS"; // Default value for unsupported or invalid LocaleConstant
|
||||||
|
}
|
||||||
|
|
||||||
void CleanStringForMysqlQuery(std::string& str)
|
void CleanStringForMysqlQuery(std::string& str)
|
||||||
{
|
{
|
||||||
std::string::size_type n = 0;
|
std::string::size_type n = 0;
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ enum LocaleConstant
|
|||||||
AC_COMMON_API extern char const* localeNames[TOTAL_LOCALES];
|
AC_COMMON_API extern char const* localeNames[TOTAL_LOCALES];
|
||||||
|
|
||||||
AC_COMMON_API LocaleConstant GetLocaleByName(const std::string& name);
|
AC_COMMON_API LocaleConstant GetLocaleByName(const std::string& name);
|
||||||
|
AC_COMMON_API const std::string GetNameByLocaleConstant(LocaleConstant localeConstant);
|
||||||
AC_COMMON_API void CleanStringForMysqlQuery(std::string& str);
|
AC_COMMON_API void CleanStringForMysqlQuery(std::string& str);
|
||||||
|
|
||||||
#define MAX_QUERY_LEN 32*1024
|
#define MAX_QUERY_LEN 32*1024
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ void RASession::Start()
|
|||||||
LOG_INFO("commands.ra", "User {} (IP: {}) authenticated correctly to RA", username, GetRemoteIpAddress());
|
LOG_INFO("commands.ra", "User {} (IP: {}) authenticated correctly to RA", username, GetRemoteIpAddress());
|
||||||
|
|
||||||
// Authentication successful, send the motd
|
// Authentication successful, send the motd
|
||||||
Send(std::string(std::string(sMotdMgr->GetMotd()) + "\r\n").c_str());
|
Send(std::string(std::string(sMotdMgr->GetMotd(DEFAULT_LOCALE)) + "\r\n").c_str());
|
||||||
|
|
||||||
// Read commands
|
// Read commands
|
||||||
for (;;)
|
for (;;)
|
||||||
|
|||||||
@@ -116,7 +116,9 @@ void LoginDatabaseConnection::DoPrepareStatements()
|
|||||||
PrepareStatement(LOGIN_DEL_ACCOUNT, "DELETE FROM account WHERE id = ?", CONNECTION_ASYNC);
|
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, "SELECT id, weight, text FROM autobroadcast 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, "SELECT text FROM motd WHERE realmid = ? OR realmid = -1 ORDER BY realmid DESC", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_REP_MOTD, "REPLACE INTO motd (realmid, text) VALUES (?, ?)", CONNECTION_ASYNC);
|
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);
|
||||||
|
PrepareStatement(LOGIN_INS_MOTD_LOCALE, "INSERT INTO motd_localized (realmid, locale, text) VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE text = ?;", CONNECTION_ASYNC);
|
||||||
PrepareStatement(LOGIN_INS_ACCOUNT_MUTE, "INSERT INTO account_muted VALUES (?, UNIX_TIMESTAMP(), ?, ?, ?)", CONNECTION_ASYNC);
|
PrepareStatement(LOGIN_INS_ACCOUNT_MUTE, "INSERT INTO account_muted VALUES (?, UNIX_TIMESTAMP(), ?, ?, ?)", CONNECTION_ASYNC);
|
||||||
PrepareStatement(LOGIN_SEL_ACCOUNT_MUTE_INFO, "SELECT mutedate, mutetime, mutereason, mutedby FROM account_muted WHERE guid = ? ORDER BY mutedate ASC", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_ACCOUNT_MUTE_INFO, "SELECT mutedate, mutetime, mutereason, mutedby FROM account_muted WHERE guid = ? ORDER BY mutedate ASC", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_DEL_ACCOUNT_MUTED, "DELETE FROM account_muted WHERE guid = ?", CONNECTION_ASYNC);
|
PrepareStatement(LOGIN_DEL_ACCOUNT_MUTED, "DELETE FROM account_muted WHERE guid = ?", CONNECTION_ASYNC);
|
||||||
|
|||||||
@@ -98,7 +98,9 @@ enum LoginDatabaseStatements : uint32
|
|||||||
LOGIN_DEL_ACCOUNT,
|
LOGIN_DEL_ACCOUNT,
|
||||||
LOGIN_SEL_AUTOBROADCAST,
|
LOGIN_SEL_AUTOBROADCAST,
|
||||||
LOGIN_SEL_MOTD,
|
LOGIN_SEL_MOTD,
|
||||||
LOGIN_REP_MOTD,
|
LOGIN_SEL_MOTD_LOCALE,
|
||||||
|
LOGIN_INS_MOTD,
|
||||||
|
LOGIN_INS_MOTD_LOCALE,
|
||||||
LOGIN_SEL_LAST_ATTEMPT_IP,
|
LOGIN_SEL_LAST_ATTEMPT_IP,
|
||||||
LOGIN_SEL_LAST_IP,
|
LOGIN_SEL_LAST_IP,
|
||||||
LOGIN_INS_ALDL_IP_LOGGING,
|
LOGIN_INS_ALDL_IP_LOGGING,
|
||||||
|
|||||||
@@ -830,7 +830,7 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
|
|||||||
|
|
||||||
// Send MOTD
|
// Send MOTD
|
||||||
{
|
{
|
||||||
SendPacket(sMotdMgr->GetMotdPacket());
|
SendPacket(sMotdMgr->GetMotdPacket(pCurrChar->GetSession()->GetSessionDbLocaleIndex()));
|
||||||
|
|
||||||
// send server info
|
// send server info
|
||||||
if (sWorld->getIntConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1)
|
if (sWorld->getIntConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1)
|
||||||
@@ -1153,7 +1153,7 @@ void WorldSession::HandlePlayerLoginToCharInWorld(Player* pCurrChar)
|
|||||||
|
|
||||||
// Send MOTD
|
// Send MOTD
|
||||||
{
|
{
|
||||||
SendPacket(sMotdMgr->GetMotdPacket());
|
SendPacket(sMotdMgr->GetMotdPacket(pCurrChar->GetSession()->GetSessionDbLocaleIndex()));
|
||||||
|
|
||||||
// send server info
|
// send server info
|
||||||
if (sWorld->getIntConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1)
|
if (sWorld->getIntConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1)
|
||||||
|
|||||||
@@ -27,8 +27,10 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
WorldPacket MotdPacket;
|
// Stores translated worldpackets
|
||||||
std::string FormattedMotd;
|
std::unordered_map<LocaleConstant, WorldPacket> MotdPackets;
|
||||||
|
// Stores the localized motd to prevent database queries
|
||||||
|
std::unordered_map<LocaleConstant, std::string> MotdMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
MotdMgr* MotdMgr::instance()
|
MotdMgr* MotdMgr::instance()
|
||||||
@@ -37,69 +39,143 @@ MotdMgr* MotdMgr::instance()
|
|||||||
return &instance;
|
return &instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotdMgr::SetMotd(std::string motd)
|
bool MotdMgr::IsValidLocale(std::string const& locale) {
|
||||||
|
// Use std::find to search for the locale in the array
|
||||||
|
return std::find(std::begin(localeNames), std::end(localeNames), locale) != std::end(localeNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotdMgr::SetMotd(std::string motd, LocaleConstant locale)
|
||||||
{
|
{
|
||||||
// scripts may change motd
|
// scripts may change motd
|
||||||
sScriptMgr->OnMotdChange(motd);
|
sScriptMgr->OnMotdChange(motd, locale);
|
||||||
|
|
||||||
WorldPacket data(SMSG_MOTD); // new in 2.0.1
|
MotdMap[locale] = motd;
|
||||||
|
MotdPackets[locale] = CreateWorldPacket(motd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotdMgr::CreateWorldPackages()
|
||||||
|
{
|
||||||
|
for (auto const& [locale, motd] : MotdMap)
|
||||||
|
// Store the constructed packet in MotdPackets with the locale as the key
|
||||||
|
MotdPackets[locale] = CreateWorldPacket(motd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotdMgr::LoadMotd()
|
||||||
|
{
|
||||||
|
uint32 realmId = sConfigMgr->GetOption<int32>("RealmID", 0);
|
||||||
|
|
||||||
|
// Load the main motd for the realm and assign it to enUS if available
|
||||||
|
std::string motd = LoadDefaultMotd(realmId);
|
||||||
|
|
||||||
|
// Check if motd was loaded; if not, set default only for enUS
|
||||||
|
if (motd.empty())
|
||||||
|
SetDefaultMotd(); // Only sets enUS default if motd is empty
|
||||||
|
else
|
||||||
|
MotdMap[DEFAULT_LOCALE] = motd; // Assign the loaded motd to enUS
|
||||||
|
|
||||||
|
// Load localized texts if available
|
||||||
|
LoadLocalizedMotds(realmId);
|
||||||
|
|
||||||
|
// Create all world packages after loading motd and localized texts
|
||||||
|
CreateWorldPackages();
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* MotdMgr::GetMotd(LocaleConstant locale)
|
||||||
|
{
|
||||||
|
// Return localized motd if available, otherwise fallback to enUS
|
||||||
|
auto it = MotdMap.find(locale);
|
||||||
|
if (it != MotdMap.end())
|
||||||
|
return it->second.c_str();
|
||||||
|
|
||||||
|
return MotdMap[DEFAULT_LOCALE].c_str(); // Fallback to enUS if locale is not found
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPacket const* MotdMgr::GetMotdPacket(LocaleConstant locale)
|
||||||
|
{
|
||||||
|
// Return localized packet if available, otherwise fallback to enUS
|
||||||
|
auto it = MotdPackets.find(locale);
|
||||||
|
if (it != MotdPackets.end())
|
||||||
|
return &it->second;
|
||||||
|
|
||||||
|
return &MotdPackets[DEFAULT_LOCALE]; // Fallback to enUS if locale is not found
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MotdMgr::LoadDefaultMotd(uint32 realmId)
|
||||||
|
{
|
||||||
|
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_MOTD);
|
||||||
|
stmt->SetData(0, realmId);
|
||||||
|
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
Field* fields = result->Fetch();
|
||||||
|
return fields[0].Get<std::string>(); // Return the main motd if found
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""; // Return empty string if no motd found
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotdMgr::SetDefaultMotd()
|
||||||
|
{
|
||||||
|
std::string motd = /* fctlsup << //0x338// "63"+"cx""d2"+"1e""dd"+"cx""ds"+"ce""dd"+"ce""7D"+ << */
|
||||||
|
/*"d3"+"ce"*/ std::string("@|") + "cf" +/*"as"+"k4"*/"fF" + "F4" +/*"d5"+"f3"*/"A2" + "DT"/*"F4"+"Az"*/ + "hi" + "s "
|
||||||
|
/*"fd"+"hy"*/ + "se" + "rv" +/*"nh"+"k3"*/"er" + " r" +/*"x1"+"A2"*/"un" + "s "/*"F2"+"Ay"*/ + "on" + " Az"
|
||||||
|
/*"xs"+"5n"*/ + "er" + "ot" +/*"xs"+"A2"*/"hC" + "or" +/*"a4"+"f3"*/"e|" + "r "/*"f2"+"A2"*/ + "|c" + "ff"
|
||||||
|
/*"5g"+"A2"*/ + "3C" + "E7" +/*"k5"+"AX"*/"FF" + "ww" +/*"sx"+"Gj"*/"w." + "az"/*"a1"+"vf"*/ + "er" + "ot"
|
||||||
|
/*"ds"+"sx"*/ + "hc" + "or" +/*"F4"+"k5"*/"e." + "or" +/*"po"+"xs"*/"g|r"/*"F4"+"p2"+"o4"+"A2"+"i2"*/;
|
||||||
|
|
||||||
|
MotdMap[DEFAULT_LOCALE] = motd;
|
||||||
|
|
||||||
|
// Log that no motd was found and a default is being used for enUS
|
||||||
|
LOG_WARN("server.loading", ">> Loaded 0 motd definitions. DB table `motd` is empty for this realm!");
|
||||||
|
LOG_INFO("server.loading", " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotdMgr::LoadLocalizedMotds(uint32 realmId) {
|
||||||
|
// First, check if base MOTD exists
|
||||||
|
LoginDatabasePreparedStatement* baseStmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_MOTD);
|
||||||
|
baseStmt->SetData(0, realmId);
|
||||||
|
PreparedQueryResult baseResult = LoginDatabase.Query(baseStmt);
|
||||||
|
|
||||||
|
if (!baseResult)
|
||||||
|
{
|
||||||
|
LOG_ERROR("server.loading", "No base MOTD found for realm %u. Localized MOTDs will not be loaded.", realmId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now load localized versions
|
||||||
|
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_MOTD_LOCALE);
|
||||||
|
stmt->SetData(0, realmId);
|
||||||
|
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
Field* fields = result->Fetch();
|
||||||
|
// fields[0] is the locale string and fields[1] is the localized motd text
|
||||||
|
std::string localizedText = fields[1].Get<std::string>();
|
||||||
|
// Convert locale string to LocaleConstant
|
||||||
|
LocaleConstant localeId = GetLocaleByName(fields[0].Get<std::string>());
|
||||||
|
|
||||||
|
if (localeId == DEFAULT_LOCALE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MotdMap[localeId] = localizedText;
|
||||||
|
} while (result->NextRow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPacket MotdMgr::CreateWorldPacket(std::string const& motd)
|
||||||
|
{
|
||||||
|
// Create a new WorldPacket for this locale
|
||||||
|
WorldPacket data(SMSG_MOTD); // new in 2.0.1
|
||||||
|
|
||||||
|
// Tokenize the motd string by '@'
|
||||||
std::vector<std::string_view> motdTokens = Acore::Tokenize(motd, '@', true);
|
std::vector<std::string_view> motdTokens = Acore::Tokenize(motd, '@', true);
|
||||||
data << uint32(motdTokens.size()); // line count
|
data << uint32(motdTokens.size()); // line count
|
||||||
|
|
||||||
for (std::string_view token : motdTokens)
|
for (std::string_view token : motdTokens)
|
||||||
data << token;
|
data << token;
|
||||||
|
|
||||||
MotdPacket = data;
|
return data;
|
||||||
|
|
||||||
if (!motdTokens.size())
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::ostringstream oss;
|
|
||||||
std::copy(motdTokens.begin(), motdTokens.end() - 1, std::ostream_iterator<std::string_view>(oss, "\n"));
|
|
||||||
oss << *(motdTokens.end() - 1); // copy back element
|
|
||||||
FormattedMotd = oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MotdMgr::LoadMotd()
|
|
||||||
{
|
|
||||||
uint32 oldMSTime = getMSTime();
|
|
||||||
|
|
||||||
uint32 realmId = sConfigMgr->GetOption<int32>("RealmID", 0);
|
|
||||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_MOTD);
|
|
||||||
stmt->SetData(0, realmId);
|
|
||||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
|
||||||
std::string motd;
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
Field* fields = result->Fetch();
|
|
||||||
motd = fields[0].Get<std::string>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_WARN("server.loading", ">> Loaded 0 motd definitions. DB table `motd` is empty for this realm!");
|
|
||||||
LOG_INFO("server.loading", " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
motd = /* fctlsup << //0x338// "63"+"cx""d2"+"1e""dd"+"cx""ds"+"ce""dd"+"ce""7D"+ << */ motd
|
|
||||||
/*"d3"+"ce"*/ + "@|" + "cf" +/*"as"+"k4"*/"fF" + "F4" +/*"d5"+"f3"*/"A2" + "DT"/*"F4"+"Az"*/ + "hi" + "s "
|
|
||||||
/*"fd"+"hy"*/ + "se" + "rv" +/*"nh"+"k3"*/"er" + " r" +/*"x1"+"A2"*/"un" + "s "/*"F2"+"Ay"*/ + "on" + " Az"
|
|
||||||
/*"xs"+"5n"*/ + "er" + "ot" +/*"xs"+"A2"*/"hC" + "or" +/*"a4"+"f3"*/"e|" + "r "/*"f2"+"A2"*/ + "|c" + "ff"
|
|
||||||
/*"5g"+"A2"*/ + "3C" + "E7" +/*"k5"+"AX"*/"FF" + "ww" +/*"sx"+"Gj"*/"w." + "az"/*"a1"+"vf"*/ + "er" + "ot"
|
|
||||||
/*"ds"+"sx"*/ + "hc" + "or" +/*"F4"+"k5"*/"e." + "or" +/*"po"+"xs"*/"g|r"/*"F4"+"p2"+"o4"+"A2"+"i2"*/;;
|
|
||||||
MotdMgr::SetMotd(motd);
|
|
||||||
|
|
||||||
LOG_INFO("server.loading", ">> Loaded Motd Definitions in {} ms", GetMSTimeDiffToNow(oldMSTime));
|
|
||||||
LOG_INFO("server.loading", " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
char const* MotdMgr::GetMotd()
|
|
||||||
{
|
|
||||||
return FormattedMotd.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldPacket const* MotdMgr::GetMotdPacket()
|
|
||||||
{
|
|
||||||
return &MotdPacket;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "Define.h"
|
#include "Define.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "Common.h"
|
||||||
|
|
||||||
class WorldPacket;
|
class WorldPacket;
|
||||||
|
|
||||||
@@ -28,17 +29,33 @@ class AC_GAME_API MotdMgr
|
|||||||
public:
|
public:
|
||||||
static MotdMgr* instance();
|
static MotdMgr* instance();
|
||||||
|
|
||||||
|
/// Converts the localized string to world packages
|
||||||
|
void CreateWorldPackages();
|
||||||
|
|
||||||
/// Set a new Message of the Day
|
/// Set a new Message of the Day
|
||||||
void SetMotd(std::string motd);
|
void SetMotd(std::string motd, LocaleConstant locale);
|
||||||
|
|
||||||
/// Load Message of the Day
|
/// Load Message of the Day
|
||||||
void LoadMotd();
|
void LoadMotd();
|
||||||
|
|
||||||
/// Get the current Message of the Day
|
/// Get the current Message of the Day
|
||||||
char const* GetMotd();
|
char const* GetMotd(LocaleConstant locale);
|
||||||
|
|
||||||
/// Get the motd packet to send at login
|
/// Returns the current motd packet for the given locale
|
||||||
WorldPacket const* GetMotdPacket();
|
WorldPacket const* GetMotdPacket(LocaleConstant locale);
|
||||||
|
|
||||||
|
// Checks if string is valid locale
|
||||||
|
bool IsValidLocale(std::string const& locale);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Loads the default motd from the motd table
|
||||||
|
std::string LoadDefaultMotd(uint32 realmId);
|
||||||
|
// Loads all available localized motd for the realm
|
||||||
|
void LoadLocalizedMotds(uint32 realmId);
|
||||||
|
// Sets the default mode if none is found in the database
|
||||||
|
void SetDefaultMotd();
|
||||||
|
// Create a worldpacket for a given motd localization
|
||||||
|
WorldPacket CreateWorldPacket(std::string const& motd);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define sMotdMgr MotdMgr::instance()
|
#define sMotdMgr MotdMgr::instance()
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ void ScriptMgr::OnBeforeConfigLoad(bool reload)
|
|||||||
CALL_ENABLED_HOOKS(WorldScript, WORLDHOOK_ON_BEFORE_CONFIG_LOAD, script->OnBeforeConfigLoad(reload));
|
CALL_ENABLED_HOOKS(WorldScript, WORLDHOOK_ON_BEFORE_CONFIG_LOAD, script->OnBeforeConfigLoad(reload));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMgr::OnMotdChange(std::string& newMotd)
|
void ScriptMgr::OnMotdChange(std::string& newMotd, LocaleConstant& locale)
|
||||||
{
|
{
|
||||||
CALL_ENABLED_HOOKS(WorldScript, WORLDHOOK_ON_MOTD_CHANGE, script->OnMotdChange(newMotd));
|
CALL_ENABLED_HOOKS(WorldScript, WORLDHOOK_ON_MOTD_CHANGE, script->OnMotdChange(newMotd, locale));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMgr::OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask)
|
void ScriptMgr::OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#ifndef SCRIPT_OBJECT_WORLD_SCRIPT_H_
|
#ifndef SCRIPT_OBJECT_WORLD_SCRIPT_H_
|
||||||
#define SCRIPT_OBJECT_WORLD_SCRIPT_H_
|
#define SCRIPT_OBJECT_WORLD_SCRIPT_H_
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
#include "ScriptObject.h"
|
#include "ScriptObject.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ public:
|
|||||||
virtual void OnBeforeConfigLoad(bool /*reload*/) { }
|
virtual void OnBeforeConfigLoad(bool /*reload*/) { }
|
||||||
|
|
||||||
// Called before the message of the day is changed.
|
// Called before the message of the day is changed.
|
||||||
virtual void OnMotdChange(std::string& /*newMotd*/) { }
|
virtual void OnMotdChange(std::string& /*newMotd*/, LocaleConstant& /*locale*/) { }
|
||||||
|
|
||||||
// Called when a world shutdown is initiated.
|
// Called when a world shutdown is initiated.
|
||||||
virtual void OnShutdownInitiate(ShutdownExitCode /*code*/, ShutdownMask /*mask*/) { }
|
virtual void OnShutdownInitiate(ShutdownExitCode /*code*/, ShutdownMask /*mask*/) { }
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ public: /* WorldScript */
|
|||||||
void OnBeforeConfigLoad(bool reload);
|
void OnBeforeConfigLoad(bool reload);
|
||||||
void OnAfterConfigLoad(bool reload);
|
void OnAfterConfigLoad(bool reload);
|
||||||
void OnBeforeFinalizePlayerWorldSession(uint32& cacheVersion);
|
void OnBeforeFinalizePlayerWorldSession(uint32& cacheVersion);
|
||||||
void OnMotdChange(std::string& newMotd);
|
void OnMotdChange(std::string& newMotd, LocaleConstant& locale);
|
||||||
void OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask);
|
void OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask);
|
||||||
void OnShutdownCancel();
|
void OnShutdownCancel();
|
||||||
void OnWorldUpdate(uint32 diff);
|
void OnWorldUpdate(uint32 diff);
|
||||||
|
|||||||
@@ -414,7 +414,12 @@ public:
|
|||||||
LOG_INFO("server.loading", "Reloading Motd...");
|
LOG_INFO("server.loading", "Reloading Motd...");
|
||||||
sMotdMgr->LoadMotd();
|
sMotdMgr->LoadMotd();
|
||||||
handler->SendGlobalGMSysMessage("DB table `motd` reloaded.");
|
handler->SendGlobalGMSysMessage("DB table `motd` reloaded.");
|
||||||
handler->SendGlobalSysMessage(sMotdMgr->GetMotd());
|
LocaleConstant locale = DEFAULT_LOCALE;
|
||||||
|
|
||||||
|
if (Player* player = handler->GetPlayer())
|
||||||
|
locale = player->GetSession()->GetSessionDbLocaleIndex();
|
||||||
|
|
||||||
|
handler->SendGlobalSysMessage(sMotdMgr->GetMotd(locale));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "Chat.h"
|
#include "Chat.h"
|
||||||
#include "CommandScript.h"
|
#include "CommandScript.h"
|
||||||
|
#include "Common.h"
|
||||||
#include "GameTime.h"
|
#include "GameTime.h"
|
||||||
#include "GitRevision.h"
|
#include "GitRevision.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
@@ -288,7 +289,11 @@ public:
|
|||||||
// Display the 'Message of the day' for the realm
|
// Display the 'Message of the day' for the realm
|
||||||
static bool HandleServerMotdCommand(ChatHandler* handler)
|
static bool HandleServerMotdCommand(ChatHandler* handler)
|
||||||
{
|
{
|
||||||
handler->PSendSysMessage(LANG_MOTD_CURRENT, sMotdMgr->GetMotd());
|
LocaleConstant localeConstant = DEFAULT_LOCALE;
|
||||||
|
if (Player* player = handler->GetPlayer())
|
||||||
|
localeConstant = player->GetSession()->GetSessionDbLocaleIndex();
|
||||||
|
|
||||||
|
handler->PSendSysMessage(LANG_MOTD_CURRENT, sMotdMgr->GetMotd(localeConstant));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,32 +525,84 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Define the 'Message of the day' for the realm
|
// Define the 'Message of the day' for the realm
|
||||||
static bool HandleServerSetMotdCommand(ChatHandler* handler, Optional<int32> realmId, Tail motd)
|
static bool HandleServerSetMotdCommand(ChatHandler* handler, Optional<int32> realmId, Optional<std::string> locale, Tail motd)
|
||||||
{
|
{
|
||||||
std::wstring wMotd = std::wstring();
|
std::wstring wMotd = std::wstring();
|
||||||
std::string strMotd = std::string();
|
std::string strMotd = std::string();
|
||||||
|
|
||||||
|
// Default realmId to the current realm if not provided
|
||||||
if (!realmId)
|
if (!realmId)
|
||||||
realmId = static_cast<int32>(realm.Id.Realm);
|
realmId = static_cast<int32>(realm.Id.Realm);
|
||||||
|
|
||||||
if (motd.empty())
|
if (motd.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!Utf8toWStr(motd, wMotd))
|
// Convert Tail (motd) to std::string
|
||||||
|
std::ostringstream motdStream;
|
||||||
|
motdStream << motd;
|
||||||
|
std::string motdString = motdStream.str(); // Convert Tail to std::string
|
||||||
|
// Determine the locale; default to "enUS" if not provided
|
||||||
|
LocaleConstant localeConstant = DEFAULT_LOCALE;
|
||||||
|
if (locale.has_value())
|
||||||
|
{
|
||||||
|
if (sMotdMgr->IsValidLocale(locale.value()))
|
||||||
|
{
|
||||||
|
localeConstant = GetLocaleByName(locale.value());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
motdStream.str("");
|
||||||
|
motdStream << locale.value() << " " << motd;
|
||||||
|
motdString = motdStream.str();
|
||||||
|
localeConstant = DEFAULT_LOCALE;
|
||||||
|
locale = GetNameByLocaleConstant(localeConstant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set to default locale string
|
||||||
|
localeConstant = DEFAULT_LOCALE;
|
||||||
|
locale = GetNameByLocaleConstant(localeConstant);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the concatenated motdString to UTF-8 and ensure encoding consistency
|
||||||
|
if (!Utf8toWStr(motdString, wMotd))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!WStrToUtf8(wMotd, strMotd))
|
if (!WStrToUtf8(wMotd, strMotd))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Start a transaction for the database operations
|
||||||
LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction();
|
LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction();
|
||||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_REP_MOTD);
|
|
||||||
stmt->SetData(0, realmId.value());
|
if (localeConstant == DEFAULT_LOCALE)
|
||||||
stmt->SetData(1, strMotd);
|
{
|
||||||
trans->Append(stmt);
|
// Insert or update in the main motd table for enUS
|
||||||
|
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_MOTD);
|
||||||
|
stmt->SetData(0, realmId.value()); // realmId for insertion
|
||||||
|
stmt->SetData(1, strMotd); // motd text for insertion
|
||||||
|
stmt->SetData(2, strMotd); // motd text for ON DUPLICATE KEY UPDATE
|
||||||
|
trans->Append(stmt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Insert or update in the motd_localized table for other locales
|
||||||
|
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_MOTD_LOCALE);
|
||||||
|
stmt->SetData(0, realmId.value()); // realmId for insertion
|
||||||
|
stmt->SetData(1, locale.value()); // locale for insertion
|
||||||
|
stmt->SetData(2, strMotd); // motd text for insertion
|
||||||
|
stmt->SetData(3, strMotd); // motd text for ON DUPLICATE KEY UPDATE
|
||||||
|
trans->Append(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit the transaction & update db
|
||||||
LoginDatabase.CommitTransaction(trans);
|
LoginDatabase.CommitTransaction(trans);
|
||||||
|
|
||||||
sMotdMgr->LoadMotd();
|
// Update the in-memory maps for the current realm. Otherwise, do not update
|
||||||
handler->PSendSysMessage(LANG_MOTD_NEW, realmId.value(), strMotd);
|
if (realmId == -1 || realmId == static_cast<int32>(realm.Id.Realm))
|
||||||
|
sMotdMgr->SetMotd(strMotd, localeConstant);
|
||||||
|
|
||||||
|
handler->PSendSysMessage(LANG_MOTD_NEW, realmId.value(), locale.value(), strMotd);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user