summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKargatum <dowlandtop@yandex.com>2021-05-27 05:12:46 +0700
committerGitHub <noreply@github.com>2021-05-27 00:12:46 +0200
commitea5f5f20727bb80f92c7dd085c19b805af5e4c7c (patch)
treee098abf514dd4e901ce47bc98646c57f5173fad0
parent78e1719c80e8c3174461dcee3a25bcd77438b450 (diff)
feat(Core/RealmList): port TrinityCore realm api (#5626)
* feat(Core/RealmList): port TrinityCore realm api * 1 * whitespace cleanup * Update data/sql/updates/pending_db_auth/rev_1620114805872279900.sql Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> * 1 * 2 * Update data/sql/updates/pending_db_auth/rev_1620114805872279900.sql Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> * ` * 1 * small corrects * finish maybe * realm.Id.Realm * ws * 1 Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>
-rw-r--r--data/sql/updates/pending_db_auth/rev_1620114805872279900.sql35
-rw-r--r--src/common/Common.h1
-rw-r--r--src/server/authserver/Authentication/AuthCodes.cpp58
-rw-r--r--src/server/authserver/Authentication/AuthCodes.h19
-rw-r--r--src/server/authserver/Main.cpp2
-rw-r--r--src/server/authserver/Server/AuthSocket.cpp178
-rw-r--r--src/server/game/Chat/Chat.cpp3
-rw-r--r--src/server/game/Entities/Player/Player.cpp1
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp7
-rw-r--r--src/server/game/Handlers/Socialhandler.cpp3
-rw-r--r--src/server/game/Server/WorldSocket.cpp14
-rw-r--r--src/server/game/World/World.cpp27
-rw-r--r--src/server/game/World/World.h20
-rw-r--r--src/server/scripts/Commands/cs_account.cpp7
-rw-r--r--src/server/scripts/Commands/cs_gm.cpp3
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp3
-rw-r--r--src/server/scripts/Commands/cs_ticket.cpp5
-rw-r--r--src/server/shared/Realms/Realm.h73
-rw-r--r--src/server/shared/Realms/RealmList.cpp215
-rw-r--r--src/server/shared/Realms/RealmList.h72
-rw-r--r--src/server/worldserver/Main.cpp2
-rw-r--r--src/server/worldserver/Master.cpp72
-rw-r--r--src/test/mocks/WorldMock.h1
23 files changed, 526 insertions, 295 deletions
diff --git a/data/sql/updates/pending_db_auth/rev_1620114805872279900.sql b/data/sql/updates/pending_db_auth/rev_1620114805872279900.sql
new file mode 100644
index 0000000000..56ef2198e1
--- /dev/null
+++ b/data/sql/updates/pending_db_auth/rev_1620114805872279900.sql
@@ -0,0 +1,35 @@
+INSERT INTO `version_db_auth` (`sql_rev`) VALUES ('1620114805872279900');
+
+--
+-- Table structure for table `build_info`
+--
+DROP TABLE IF EXISTS `build_info`;
+CREATE TABLE `build_info` (
+ `build` INT NOT NULL,
+ `majorVersion` INT DEFAULT NULL,
+ `minorVersion` INT DEFAULT NULL,
+ `bugfixVersion` INT DEFAULT NULL,
+ `hotfixVersion` CHAR(3) DEFAULT NULL,
+ `winAuthSeed` VARCHAR(32) DEFAULT NULL,
+ `win64AuthSeed` VARCHAR(32) DEFAULT NULL,
+ `mac64AuthSeed` VARCHAR(32) DEFAULT NULL,
+ `winChecksumSeed` VARCHAR(40) DEFAULT NULL,
+ `macChecksumSeed` VARCHAR(40) DEFAULT NULL,
+ PRIMARY KEY (`build`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+--
+-- Dumping data for table `build_info`
+--
+INSERT INTO `build_info` VALUES
+(5875,1,12,1,NULL,NULL,NULL,NULL,'95EDB27C7823B363CBDDAB56A392E7CB73FCCA20','8D173CC381961EEBABF336F5E6675B101BB513E5'),
+(6005,1,12,2,NULL,NULL,NULL,NULL,NULL,NULL),
+(6141,1,12,3,NULL,NULL,NULL,NULL,NULL,NULL),
+(8606,2,4,3,NULL,NULL,NULL,NULL,'319AFAA3F2559682F9FF658BE01456255F456FB1','D8B0ECFE534BC1131E19BAD1D4C0E813EEE4994F'),
+(9947,3,1,3,NULL,NULL,NULL,NULL,NULL,NULL),
+(10505,3,2,2,'a',NULL,NULL,NULL,NULL,NULL),
+(11159,3,3,0,'a',NULL,NULL,NULL,NULL,NULL),
+(11403,3,3,2,NULL,NULL,NULL,NULL,NULL,NULL),
+(11723,3,3,3,'a',NULL,NULL,NULL,NULL,NULL),
+(12340,3,3,5,'a',NULL,NULL,NULL,'CDCBBD5188315E6B4D19449D492DBCFAF156A347','B706D13FF2F4018839729461E3F8A0E2B5FDC034'),
+(13930,3,3,5,'a',NULL,NULL,NULL,NULL,NULL);
diff --git a/src/common/Common.h b/src/common/Common.h
index bc25cc24c5..6acc2c7295 100644
--- a/src/common/Common.h
+++ b/src/common/Common.h
@@ -14,6 +14,7 @@
#include <utility>
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
+#include <ace/config-all.h>
#include <ws2tcpip.h>
#if AC_COMPILER == AC_COMPILER_INTEL
# if !defined(BOOST_ASIO_HAS_MOVE)
diff --git a/src/server/authserver/Authentication/AuthCodes.cpp b/src/server/authserver/Authentication/AuthCodes.cpp
index f5002b64b1..9777de4836 100644
--- a/src/server/authserver/Authentication/AuthCodes.cpp
+++ b/src/server/authserver/Authentication/AuthCodes.cpp
@@ -5,66 +5,24 @@
*/
#include "AuthCodes.h"
-#include <cstddef>
+#include "RealmList.h"
namespace AuthHelper
{
- static RealmBuildInfo const PostBcAcceptedClientBuilds[] =
- {
- {15595, 4, 3, 4, ' '},
- {14545, 4, 2, 2, ' '},
- {13623, 4, 0, 6, 'a'},
- {12340, 3, 3, 5, 'a'},
- {11723, 3, 3, 3, 'a'},
- {11403, 3, 3, 2, ' '},
- {11159, 3, 3, 0, 'a'},
- {10505, 3, 2, 2, 'a'},
- {9947, 3, 1, 3, ' '},
- {8606, 2, 4, 3, ' '},
- {0, 0, 0, 0, ' '} // terminator
- };
-
- static RealmBuildInfo const PreBcAcceptedClientBuilds[] =
- {
- {6141, 1, 12, 3, ' '},
- {6005, 1, 12, 2, ' '},
- {5875, 1, 12, 1, ' '},
- {0, 0, 0, 0, ' '} // terminator
- };
-
- bool IsPreBCAcceptedClientBuild(int build)
- {
- for (int i = 0; PreBcAcceptedClientBuilds[i].Build; ++i)
- if (PreBcAcceptedClientBuilds[i].Build == build)
- return true;
+ constexpr static uint32 MAX_PRE_BC_CLIENT_BUILD = 6141;
- return false;
- }
-
- bool IsPostBCAcceptedClientBuild(int build)
+ bool IsPreBCAcceptedClientBuild(uint32 build)
{
- for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i)
- if (PostBcAcceptedClientBuilds[i].Build == build)
- return true;
-
- return false;
+ return build <= MAX_PRE_BC_CLIENT_BUILD && sRealmList->GetBuildInfo(build);
}
- bool IsAcceptedClientBuild(int build)
+ bool IsPostBCAcceptedClientBuild(uint32 build)
{
- return (IsPostBCAcceptedClientBuild(build) || IsPreBCAcceptedClientBuild(build));
+ return build > MAX_PRE_BC_CLIENT_BUILD && sRealmList->GetBuildInfo(build);
}
- RealmBuildInfo const* GetBuildInfo(int build)
+ bool IsAcceptedClientBuild(uint32 build)
{
- for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i)
- if (PostBcAcceptedClientBuilds[i].Build == build)
- return &PostBcAcceptedClientBuilds[i];
-
- for (int i = 0; PreBcAcceptedClientBuilds[i].Build; ++i)
- if (PreBcAcceptedClientBuilds[i].Build == build)
- return &PreBcAcceptedClientBuilds[i];
-
- return nullptr;
+ return sRealmList->GetBuildInfo(build) != nullptr;
}
};
diff --git a/src/server/authserver/Authentication/AuthCodes.h b/src/server/authserver/Authentication/AuthCodes.h
index 6bb1a7f742..be079b7367 100644
--- a/src/server/authserver/Authentication/AuthCodes.h
+++ b/src/server/authserver/Authentication/AuthCodes.h
@@ -7,6 +7,9 @@
#ifndef _AUTHCODES_H
#define _AUTHCODES_H
+#include "Define.h"
+#include <array>
+
enum AuthResult
{
WOW_SUCCESS = 0x00,
@@ -65,21 +68,13 @@ enum ExpansionFlags
NO_VALID_EXP_FLAG = 0x0
};
-struct RealmBuildInfo
-{
- int Build;
- int MajorVersion;
- int MinorVersion;
- int BugfixVersion;
- int HotfixVersion;
-};
+struct RealmBuildInfo;
namespace AuthHelper
{
- RealmBuildInfo const* GetBuildInfo(int build);
- bool IsAcceptedClientBuild(int build);
- bool IsPostBCAcceptedClientBuild(int build);
- bool IsPreBCAcceptedClientBuild(int build);
+ bool IsAcceptedClientBuild(uint32 build);
+ bool IsPostBCAcceptedClientBuild(uint32 build);
+ bool IsPreBCAcceptedClientBuild(uint32 build);
};
#endif
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
index 772832937b..1552362888 100644
--- a/src/server/authserver/Main.cpp
+++ b/src/server/authserver/Main.cpp
@@ -135,7 +135,7 @@ extern int main(int argc, char** argv)
// Get the list of realms for the server
sRealmList->Initialize(sConfigMgr->GetOption<int32>("RealmsStateUpdateDelay", 20));
- if (sRealmList->size() == 0)
+ if (sRealmList->GetRealms().empty())
{
LOG_ERROR("server.authserver", "No valid realms specified.");
return 1;
diff --git a/src/server/authserver/Server/AuthSocket.cpp b/src/server/authserver/Server/AuthSocket.cpp
index 3a17dd7c21..c8c6eb0d7c 100644
--- a/src/server/authserver/Server/AuthSocket.cpp
+++ b/src/server/authserver/Server/AuthSocket.cpp
@@ -165,6 +165,8 @@ private:
Patches _patches;
};
+std::array<uint8, 16> VersionChallenge = { { 0xBA, 0xA3, 0x1E, 0x99, 0xA0, 0x0B, 0x21, 0x57, 0xFC, 0x37, 0x3F, 0xB3, 0x69, 0xCD, 0xD2, 0xF1 } };
+
const AuthHandler table[] =
{
{ AUTH_LOGON_CHALLENGE, STATUS_CHALLENGE, &AuthSocket::_HandleLogonChallenge },
@@ -366,6 +368,10 @@ bool AuthSocket::_HandleLogonChallenge()
// Restore string order as its byte order is reversed
std::reverse(_os.begin(), _os.end());
+ _localizationName.resize(4);
+ for (int i = 0; i < 4; ++i)
+ _localizationName[i] = ch->country[4 - i - 1];
+
ByteBuffer pkt;
pkt << uint8(AUTH_LOGON_CHALLENGE);
pkt << uint8(0x00);
@@ -487,9 +493,6 @@ bool AuthSocket::_HandleLogonChallenge()
fields[10].GetBinary<acore::Crypto::SRP6::SALT_LENGTH>(),
fields[11].GetBinary<acore::Crypto::SRP6::VERIFIER_LENGTH>());
- BigNumber unk3;
- unk3.SetRand(16 * 8);
-
// Fill the response packet with the result
if (!AuthHelper::IsAcceptedClientBuild(_build))
{
@@ -507,8 +510,7 @@ bool AuthSocket::_HandleLogonChallenge()
pkt << uint8(32);
pkt.append(_srp6->N);
pkt.append(_srp6->s);
- pkt.append(unk3.ToByteArray<16>());
-
+ pkt.append(VersionChallenge.data(), VersionChallenge.size());
pkt << uint8(securityFlags); // security flags (0x0...0x04)
if (securityFlags & 0x01) // PIN input
@@ -529,11 +531,7 @@ bool AuthSocket::_HandleLogonChallenge()
if (securityFlags & 0x04) // Security token input
pkt << uint8(1);
- _localizationName.resize(4);
- for (int i = 0; i < 4; ++i)
- _localizationName[i] = ch->country[4 - i - 1];
-
- LOG_DEBUG("network", "'%s:%d' [AuthChallenge] account %s is using locale (%u)",
+ LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] account %s is using locale (%u)",
ipAddress.c_str(), port, _accountInfo.Login.c_str(), GetLocaleByName(_localizationName));
///- All good, await client's proof
@@ -546,9 +544,8 @@ bool AuthSocket::_HandleLogonChallenge()
// Logon Proof command handler
bool AuthSocket::_HandleLogonProof()
{
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
- LOG_DEBUG("network", "Entering _HandleLogonProof");
-#endif
+ LOG_TRACE("server.authserver", "Entering _HandleLogonProof");
+
// Read the packet
sAuthLogonProof_C lp;
@@ -571,20 +568,6 @@ bool AuthSocket::_HandleLogonProof()
if (std::optional<SessionKey> K = _srp6->VerifyChallengeResponse(lp.A, lp.clientM))
{
_sessionKey = *K;
- LOG_DEBUG("network", "'%s:%d' User '%s' successfully authenticated", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _accountInfo.Login.c_str());
-
- // Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
- // No SQL injection (escaped user name) and IP address as received by socket
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF);
- stmt->setBinary(0, _sessionKey);
- stmt->setString(1, socket().getRemoteAddress().c_str());
- stmt->setUInt32(2, GetLocaleByName(_localizationName));
- stmt->setString(3, _os);
- stmt->setString(4, _accountInfo.Login);
- LoginDatabase.DirectExecute(stmt);
-
- // Finish SRP6 and send the final result to the client
- acore::Crypto::SHA1::Digest M2 = acore::Crypto::SRP6::GetSessionVerifier(lp.A, lp.clientM, _sessionKey);
// Check auth token
bool tokenSuccess = false;
@@ -613,6 +596,21 @@ bool AuthSocket::_HandleLogonProof()
socket().send(data, sizeof(data));
}
+ LOG_DEBUG("network", "'%s:%d' User '%s' successfully authenticated", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _accountInfo.Login.c_str());
+
+ // Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
+ // No SQL injection (escaped user name) and IP address as received by socket
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF);
+ stmt->setBinary(0, _sessionKey);
+ stmt->setString(1, socket().getRemoteAddress().c_str());
+ stmt->setUInt32(2, GetLocaleByName(_localizationName));
+ stmt->setString(3, _os);
+ stmt->setString(4, _accountInfo.Login);
+ LoginDatabase.DirectExecute(stmt);
+
+ // Finish SRP6 and send the final result to the client
+ acore::Crypto::SHA1::Digest M2 = acore::Crypto::SRP6::GetSessionVerifier(lp.A, lp.clientM, _sessionKey);
+
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
{
sAuthLogonProof_S proof;
@@ -621,7 +619,7 @@ bool AuthSocket::_HandleLogonProof()
proof.error = 0;
proof.unk1 = 0x00800000; // Accountflags. 0x01 = GM, 0x08 = Trial, 0x00800000 = Pro pass (arena tournament)
proof.unk2 = 0x00; // SurveyId
- proof.unk3 = 0x00;
+ proof.unk3 = 0x00; // 0x1 = has account message
socket().send((char*)&proof, sizeof(proof));
}
else
@@ -642,9 +640,8 @@ bool AuthSocket::_HandleLogonProof()
char data[4] = { AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0 };
socket().send(data, sizeof(data));
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
- LOG_DEBUG("network", "'%s:%d' [AuthChallenge] account %s tried to login with invalid password!", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _accountInfo.Login.c_str());
-#endif
+ LOG_INFO("server.authserver.hack", "'%s:%d' [AuthChallenge] account %s tried to login with invalid password!",
+ socket().getRemoteAddress().c_str(), socket().getRemotePort(), _accountInfo.Login.c_str());
uint32 MaxWrongPassCount = sConfigMgr->GetOption<int32>("WrongPass.MaxCount", 0);
@@ -666,42 +663,30 @@ bool AuthSocket::_HandleLogonProof()
stmt->setString(0, _accountInfo.Login);
LoginDatabase.Execute(stmt);
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_FAILEDLOGINS);
- stmt->setString(0, _accountInfo.Login);
-
- if (PreparedQueryResult loginfail = LoginDatabase.Query(stmt))
+ if (++_accountInfo.FailedLogins >= MaxWrongPassCount)
{
- uint32 failed_logins = (*loginfail)[1].GetUInt32();
+ uint32 WrongPassBanTime = sConfigMgr->GetOption<int32>("WrongPass.BanTime", 600);
+ bool WrongPassBanType = sConfigMgr->GetOption<bool>("WrongPass.BanType", false);
- if (failed_logins >= MaxWrongPassCount)
+ if (WrongPassBanType)
{
- uint32 WrongPassBanTime = sConfigMgr->GetOption<int32>("WrongPass.BanTime", 600);
- bool WrongPassBanType = sConfigMgr->GetOption<bool>("WrongPass.BanType", false);
-
- if (WrongPassBanType)
- {
- uint32 acc_id = (*loginfail)[0].GetUInt32();
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED);
- stmt->setUInt32(0, acc_id);
- stmt->setUInt32(1, WrongPassBanTime);
- LoginDatabase.Execute(stmt);
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED);
+ stmt->setUInt32(0, _accountInfo.Id);
+ stmt->setUInt32(1, WrongPassBanTime);
+ LoginDatabase.Execute(stmt);
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
- LOG_DEBUG("network", "'%s:%d' [AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _accountInfo.Login.c_str(), WrongPassBanTime, failed_logins);
-#endif
- }
- else
- {
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_IP_AUTO_BANNED);
- stmt->setString(0, socket().getRemoteAddress());
- stmt->setUInt32(1, WrongPassBanTime);
- LoginDatabase.Execute(stmt);
+ LOG_DEBUG("network", "'%s:%d' [AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times",
+ socket().getRemoteAddress().c_str(), socket().getRemotePort(), _accountInfo.Login.c_str(), WrongPassBanTime, _accountInfo.FailedLogins);
+ }
+ else
+ {
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_IP_AUTO_BANNED);
+ stmt->setString(0, socket().getRemoteAddress());
+ stmt->setUInt32(1, WrongPassBanTime);
+ LoginDatabase.Execute(stmt);
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
- LOG_DEBUG("network", "'%s:%d' [AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times",
- socket().getRemoteAddress().c_str(), socket().getRemotePort(), socket().getRemoteAddress().c_str(), WrongPassBanTime, _accountInfo.Login.c_str(), failed_logins);
-#endif
- }
+ LOG_DEBUG("network", "'%s:%d' [AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times",
+ socket().getRemoteAddress().c_str(), socket().getRemotePort(), socket().getRemoteAddress().c_str(), WrongPassBanTime, _accountInfo.Login.c_str(), _accountInfo.FailedLogins);
}
}
}
@@ -713,9 +698,8 @@ bool AuthSocket::_HandleLogonProof()
// Reconnect Challenge command handler
bool AuthSocket::_HandleReconnectChallenge()
{
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
- LOG_DEBUG("network", "Entering _HandleReconnectChallenge");
-#endif
+ LOG_TRACE("network", "Entering _HandleReconnectChallenge");
+
if (socket().recv_len() < sizeof(sAuthLogonChallenge_C))
return false;
@@ -751,6 +735,15 @@ bool AuthSocket::_HandleReconnectChallenge()
#endif
std::string login((char const*)ch->I, ch->I_len);
+ LOG_DEBUG("server.authserver", "[ReconnectChallenge] '%s'", login.c_str());
+
+ // Reinitialize build, expansion and the account securitylevel
+ _build = ch->build;
+ _expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG));
+ _os = (const char*)ch->os;
+
+ if (_os.size() > 4)
+ return false;
auto* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RECONNECTCHALLENGE);
stmt->setString(0, login);
@@ -768,14 +761,6 @@ bool AuthSocket::_HandleReconnectChallenge()
Field* fields = result->Fetch();
_accountInfo.LoadResult(fields);
- // Reinitialize build, expansion and the account securitylevel
- _build = ch->build;
- _expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG));
- _os = (const char*)ch->os;
-
- if (_os.size() > 4)
- return false;
-
// Restore string order as its byte order is reversed
std::reverse(_os.begin(), _os.end());
@@ -788,9 +773,9 @@ bool AuthSocket::_HandleReconnectChallenge()
// Sending response
ByteBuffer pkt;
pkt << uint8(AUTH_RECONNECT_CHALLENGE);
- pkt << uint8(0x00);
+ pkt << uint8(WOW_SUCCESS);
pkt.append(_reconnectProof); // 16 bytes random
- pkt << uint64(0x00) << uint64(0x00); // 16 bytes zeros
+ pkt.append(VersionChallenge.data(), VersionChallenge.size());
socket().send((char const*)pkt.contents(), pkt.size());
return true;
}
@@ -837,7 +822,8 @@ bool AuthSocket::_HandleReconnectProof()
}
else
{
- LOG_ERROR("server", "'%s:%d' [ERROR] user %s tried to login, but session is invalid.", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _accountInfo.Login.c_str());
+ LOG_ERROR("server.authserver.hack", "'%s:%d' [ERROR] user %s tried to login, but session is invalid.",
+ socket().getRemoteAddress().c_str(), socket().getRemotePort(), _accountInfo.Login.c_str());
socket().shutdown();
return false;
}
@@ -849,20 +835,22 @@ ACE_INET_Addr const& AuthSocket::GetAddressForClient(Realm const& realm, ACE_INE
if (clientAddr.is_loopback())
{
// Try guessing if realm is also connected locally
- if (realm.LocalAddress.is_loopback() || realm.ExternalAddress.is_loopback())
+ if (realm.LocalAddress->is_loopback() || realm.ExternalAddress->is_loopback())
return clientAddr;
// Assume that user connecting from the machine that authserver is located on
// has all realms available in his local network
- return realm.LocalAddress;
+ return *realm.LocalAddress;
}
// Check if connecting client is in the same network
- if (IsIPAddrInNetwork(realm.LocalAddress, clientAddr, realm.LocalSubnetMask))
- return realm.LocalAddress;
+ if (IsIPAddrInNetwork(*realm.LocalAddress, clientAddr, *realm.LocalSubnetMask))
+ {
+ return *realm.LocalAddress;
+ }
// Return external IP
- return realm.ExternalAddress;
+ return *realm.ExternalAddress;
}
// Realm List command handler
@@ -900,17 +888,17 @@ bool AuthSocket::_HandleRealmList()
// Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm)
ByteBuffer pkt;
-
size_t RealmListSize = 0;
- for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i)
+
+ for (auto& [realmHandle, realm] : sRealmList->GetRealms())
{
- const Realm& realm = i->second;
// don't work with realms which not compatible with the client
- bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && realm.gamebuild == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(realm.gamebuild));
+ bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && realm.Build == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(realm.Build));
// No SQL injection. id of realm is controlled by the database.
- uint32 flag = realm.flag;
- RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.gamebuild);
+ uint32 flag = realm.Flags;
+
+ RealmBuildInfo const* buildInfo = sRealmList->GetBuildInfo(realm.Build);
if (!okBuild)
{
if (!buildInfo)
@@ -922,7 +910,7 @@ bool AuthSocket::_HandleRealmList()
if (!buildInfo)
flag &= ~REALM_FLAG_SPECIFYBUILD;
- std::string name = i->first;
+ std::string name = realm.Name;
if (_expversion & PRE_BC_EXP_FLAG && flag & REALM_FLAG_SPECIFYBUILD)
{
std::ostringstream ss;
@@ -931,29 +919,29 @@ bool AuthSocket::_HandleRealmList()
}
// We don't need the port number from which client connects with but the realm's port
- clientAddr.set_port_number(realm.ExternalAddress.get_port_number());
+ clientAddr.set_port_number(realm.ExternalAddress->get_port_number());
- uint8 lock = (realm.allowedSecurityLevel > _accountInfo.SecurityLevel) ? 1 : 0;
+ uint8 lock = (realm.AllowedSecurityLevel > _accountInfo.SecurityLevel) ? 1 : 0;
uint8 AmountOfCharacters = 0;
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_NUM_CHARS_ON_REALM);
- stmt->setUInt32(0, realm.m_ID);
+ stmt->setUInt32(0, realm.Id.Realm);
stmt->setUInt32(1, id);
result = LoginDatabase.Query(stmt);
if (result)
AmountOfCharacters = (*result)[0].GetUInt8();
- pkt << realm.icon; // realm type
+ pkt << realm.Type; // realm type
if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients
pkt << lock; // if 1, then realm locked
pkt << uint8(flag); // RealmFlags
pkt << name;
pkt << GetAddressString(GetAddressForClient(realm, clientAddr));
- pkt << realm.populationLevel;
+ pkt << realm.PopulationLevel;
pkt << AmountOfCharacters;
- pkt << realm.timezone; // realm category
+ pkt << realm.Timezone; // realm category
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
- pkt << uint8(realm.m_ID);
+ pkt << uint8(realm.Id.Realm);
else
pkt << uint8(0x0); // 1.12.1 and 1.12.2 clients
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 9137f4423c..aa1eb2ee35 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -16,6 +16,7 @@
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
+#include "Realm.h"
#include "ScriptMgr.h"
#include "SpellMgr.h"
#include "UpdateMask.h"
@@ -114,7 +115,7 @@ bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_ac
if (target)
target_sec = target->GetSecurity();
else if (target_account)
- target_sec = AccountMgr::GetSecurity(target_account, realmID);
+ target_sec = AccountMgr::GetSecurity(target_account, realm.Id.Realm);
else
return true; // caller must report error for (target == nullptr && target_account == 0)
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 58111d16e9..c018207ddb 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -57,6 +57,7 @@
#include "QuestDef.h"
#include "ReputationMgr.h"
#include "revision.h"
+#include "Realm.h"
#include "SavingSystem.h"
#include "ScriptMgr.h"
#include "SkillDiscovery.h"
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 25d8a50e21..c3744c6dae 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -26,6 +26,7 @@
#include "Pet.h"
#include "Player.h"
#include "PlayerDump.h"
+#include "Realm.h"
#include "ReputationMgr.h"
#include "ScriptMgr.h"
#include "ServerMotd.h"
@@ -647,13 +648,13 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM);
stmt->setUInt32(0, GetAccountId());
- stmt->setUInt32(1, realmID);
+ stmt->setUInt32(1, realm.Id.Realm);
trans->Append(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS);
stmt->setUInt32(0, createInfo->CharCount);
stmt->setUInt32(1, GetAccountId());
- stmt->setUInt32(2, realmID);
+ stmt->setUInt32(2, realm.Id.Realm);
trans->Append(stmt);
LoginDatabase.CommitTransaction(trans);
@@ -996,7 +997,7 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder* holder)
CharacterDatabase.Execute(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_ONLINE);
- stmt->setUInt32(0, realmID);
+ stmt->setUInt32(0, realm.Id.Realm);
stmt->setUInt32(1, GetAccountId());
LoginDatabase.Execute(stmt);
diff --git a/src/server/game/Handlers/Socialhandler.cpp b/src/server/game/Handlers/Socialhandler.cpp
index 07453f6162..9869545023 100644
--- a/src/server/game/Handlers/Socialhandler.cpp
+++ b/src/server/game/Handlers/Socialhandler.cpp
@@ -10,6 +10,7 @@
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Player.h"
+#include "Realm.h"
#include "SocialMgr.h"
#include "World.h"
#include "WorldSession.h"
@@ -52,7 +53,7 @@ void WorldSession::HandleAddFriendOpcode(WorldPacket& recv_data)
TeamId teamId = Player::TeamIdForRace(playerData->race);
FriendsResult friendResult = FRIEND_NOT_FOUND;
- if (!AccountMgr::IsPlayerAccount(GetSecurity()) || sWorld->getBoolConfig(CONFIG_ALLOW_GM_FRIEND)|| AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realmID)))
+ if (!AccountMgr::IsPlayerAccount(GetSecurity()) || sWorld->getBoolConfig(CONFIG_ALLOW_GM_FRIEND)|| AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realm.Id.Realm)))
{
if (friendGuid)
{
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index d7383e92c1..f7e6d1f124 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -15,6 +15,7 @@
#include "Opcodes.h"
#include "PacketLog.h"
#include "Player.h"
+#include "Realm.h"
#include "ScriptMgr.h"
#include "SharedDefines.h"
#include "Util.h"
@@ -791,7 +792,7 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
{
// NOTE: ATM the socket is singlethread, have this in mind ...
- uint32 loginServerID, loginServerType, regionID, battlegroupID, realm;
+ uint32 loginServerID, loginServerType, regionID, battlegroupID, realmid;
uint64 DosResponse;
uint32 BuiltNumberClient;
std::string accountName;
@@ -817,7 +818,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
recvPacket.read(clientSeed);
recvPacket >> regionID;
recvPacket >> battlegroupID;
- recvPacket >> realm;
+ recvPacket >> realmid;
recvPacket >> DosResponse;
recvPacket.read(digest);
@@ -829,7 +830,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// 0 1 2 3 4 5 6 7 8 9 10
// SELECT id, sessionkey, last_ip, locked, lock_country, expansion, mutetime, locale, recruiter, os, totaltime FROM account WHERE username = ?
auto* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME);
- stmt->setInt32(0, int32(realmID));
+ stmt->setInt32(0, int32(realm.Id.Realm));
stmt->setString(1, accountName);
PreparedQueryResult result = LoginDatabase.Query(stmt);
@@ -856,11 +857,10 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_ATTEMPT_IP);
stmt->setString(0, address);
stmt->setString(1, accountName);
-
LoginDatabase.Execute(stmt);
// This also allows to check for possible "hack" attempts on account
- // even if auth credentials are bad, try using the session key we have - client cannot read auth response error without it
+ // even if auth credentials are bad, try using the session key we have - client cannot read auth response error without it
m_Crypt.Init(account.SessionKey);
// First reject the connection if packet contains invalid data or realm state doesn't allow logging in
@@ -875,14 +875,14 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
return -1;
}
- if (realm != realmID)
+ if (realmid != realm.Id.Realm)
{
packet.Initialize(SMSG_AUTH_RESPONSE, 1);
packet << uint8(REALM_LIST_REALM_NOT_FOUND);
SendPacket(packet);
LOG_ERROR("server", "WorldSocket::HandleAuthSession: Client %s requested connecting with realm id %u but this realm has id %u set in config.",
- address.c_str(), realm, realmID);
+ address.c_str(), realmid, realm.Id.Realm);
sScriptMgr->OnFailedAccountLogin(account.Id);
return -1;
}
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 7ebb804b3f..705b4136bf 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -54,6 +54,7 @@
#include "PetitionMgr.h"
#include "Player.h"
#include "PoolMgr.h"
+#include "Realm.h"
#include "SavingSystem.h"
#include "ScriptMgr.h"
#include "ServerMotd.h"
@@ -91,6 +92,8 @@ float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
float World::m_MaxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE;
float World::m_MaxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
+Realm realm;
+
/// World constructor
World::World()
{
@@ -428,7 +431,7 @@ void World::LoadConfigSettings(bool reload)
}
// Set realm id and enable db logging
- sLog->SetRealmId(realmID);
+ sLog->SetRealmId(realm.Id.Realm);
#ifdef ELUNA
///- Initialize Lua Engine
@@ -1488,7 +1491,7 @@ void World::SetInitialWorldSettings()
uint32 realm_zone = getIntConfig(CONFIG_REALM_ZONE);
- LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID); // One-time query
+ LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realm.Id.Realm); // One-time query
///- Custom Hook for loading DB items
sScriptMgr->OnLoadCustomDatabaseTable();
@@ -1938,7 +1941,7 @@ void World::SetInitialWorldSettings()
m_startTime = m_gameTime;
LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES(%u, %u, 0, '%s')",
- realmID, uint32(m_startTime), GitRevision::GetFullVersion()); // One-time query
+ realm.Id.Realm, uint32(m_startTime), GitRevision::GetFullVersion()); // One-time query
m_timers[WUPDATE_WEATHERS].SetInterval(1 * IN_MILLISECONDS);
m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE * IN_MILLISECONDS);
@@ -2316,7 +2319,7 @@ void World::Update(uint32 diff)
stmt->setUInt32(0, tmpDiff);
stmt->setUInt16(1, uint16(maxOnlinePlayers));
- stmt->setUInt32(2, realmID);
+ stmt->setUInt32(2, realm.Id.Realm);
stmt->setUInt32(3, uint32(m_startTime));
LoginDatabase.Execute(stmt);
@@ -2854,13 +2857,13 @@ void World::_UpdateRealmCharCount(PreparedQueryResult resultCharCount)
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM);
stmt->setUInt32(0, accountId);
- stmt->setUInt32(1, realmID);
+ stmt->setUInt32(1, realm.Id.Realm);
trans->Append(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS);
stmt->setUInt8(0, charCount);
stmt->setUInt32(1, accountId);
- stmt->setUInt32(2, realmID);
+ stmt->setUInt32(2, realm.Id.Realm);
trans->Append(stmt);
LoginDatabase.CommitTransaction(trans);
@@ -2988,7 +2991,7 @@ void World::ResetDailyQuests()
void World::LoadDBAllowedSecurityLevel()
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL);
- stmt->setInt32(0, int32(realmID));
+ stmt->setInt32(0, int32(realm.Id.Realm));
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (result)
@@ -3451,3 +3454,13 @@ void World::RemoveOldCorpses()
{
m_timers[WUPDATE_CORPSES].SetCurrent(m_timers[WUPDATE_CORPSES].GetInterval());
}
+
+bool World::IsPvPRealm() const
+{
+ return getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP;
+}
+
+bool World::IsFFAPvPRealm() const
+{
+ return getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP;
+}
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 8134a58171..b2005d2073 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -29,7 +29,9 @@ class WorldPacket;
class WorldSocket;
class SystemMgr;
-extern uint32 realmID;
+struct Realm;
+
+AC_GAME_API extern Realm realm;
enum ShutdownMask
{
@@ -74,18 +76,6 @@ enum BillingPlanFlags
SESSION_ENABLE_CAIS = 0x80,
};
-/// Type of server, this is values from second column of Cfg_Configs.dbc
-enum RealmType
-{
- REALM_TYPE_NORMAL = 0,
- REALM_TYPE_PVP = 1,
- REALM_TYPE_NORMAL2 = 4,
- REALM_TYPE_RP = 6,
- REALM_TYPE_RPPVP = 8,
- REALM_TYPE_FFA_PVP = 16 // custom, free for all pvp mode like arena PvP in all zones except rest activated places and sanctuaries
- // replaced by REALM_PVP in realm list
-};
-
enum RealmZone
{
REALM_ZONE_UNKNOWN = 0, // any language
@@ -335,8 +325,8 @@ public:
void LoadWorldStates();
/// Are we on a "Player versus Player" server?
- bool IsPvPRealm() const { return (getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP); }
- bool IsFFAPvPRealm() const { return getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP; }
+ [[nodiscard]] bool IsPvPRealm() const;
+ [[nodiscard]] bool IsFFAPvPRealm() const;
void KickAll();
void KickAllLess(AccountTypes sec);
diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp
index be57b08554..f5385b417e 100644
--- a/src/server/scripts/Commands/cs_account.cpp
+++ b/src/server/scripts/Commands/cs_account.cpp
@@ -18,6 +18,7 @@ EndScriptData */
#include "CryptoGenerics.h"
#include "Language.h"
#include "Player.h"
+#include "Realm.h"
#include "ScriptMgr.h"
#include "SecretMgr.h"
#include "StringConvert.h"
@@ -796,7 +797,7 @@ public:
}
}
- // Check if provided realmID has a negative value other than -1
+ // Check if provided realm.Id.Realm has a negative value other than -1
if (gmRealmID < -1)
{
handler->SendSysMessage(LANG_INVALID_REALMID);
@@ -804,7 +805,7 @@ public:
return false;
}
- // If gmRealmID is -1, delete all values for the account id, else, insert values for the specific realmID
+ // If gmRealmID is -1, delete all values for the account id, else, insert values for the specific realm.Id.Realm
PreparedStatement* stmt;
if (gmRealmID == -1)
@@ -818,7 +819,7 @@ public:
stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM);
stmt->setUInt32(0, targetAccountId);
- stmt->setUInt32(1, realmID);
+ stmt->setUInt32(1, realm.Id.Realm);
}
LoginDatabase.Execute(stmt);
diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp
index 718c924126..899d6cfad1 100644
--- a/src/server/scripts/Commands/cs_gm.cpp
+++ b/src/server/scripts/Commands/cs_gm.cpp
@@ -17,6 +17,7 @@ EndScriptData */
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
+#include "Realm.h"
#include "ScriptMgr.h"
#include "World.h"
@@ -156,7 +157,7 @@ public:
///- Get the accounts with GM Level >0
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_GM_ACCOUNTS);
stmt->setUInt8(0, uint8(SEC_MODERATOR));
- stmt->setInt32(1, int32(realmID));
+ stmt->setInt32(1, int32(realm.Id.Realm));
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (result)
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 95f45e4632..bf1b93be03 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -24,6 +24,7 @@
#include "Opcodes.h"
#include "Pet.h"
#include "Player.h"
+#include "Realm.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "TargetedMovementGenerator.h"
@@ -1909,7 +1910,7 @@ public:
// Query the prepared statement for login data
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO);
- stmt->setInt32(0, int32(realmID));
+ stmt->setInt32(0, int32(realm.Id.Realm));
stmt->setUInt32(1, accId);
PreparedQueryResult accInfoResult = LoginDatabase.Query(stmt);
diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp
index 178b8a396a..cefc7758cd 100644
--- a/src/server/scripts/Commands/cs_ticket.cpp
+++ b/src/server/scripts/Commands/cs_ticket.cpp
@@ -17,6 +17,7 @@ EndScriptData */
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
+#include "Realm.h"
#include "ScriptMgr.h"
#include "TicketMgr.h"
@@ -84,7 +85,7 @@ public:
// Get target information
ObjectGuid targetGuid = sObjectMgr->GetPlayerGUIDByName(target.c_str());
uint32 targetAccountId = sObjectMgr->GetPlayerAccountIdByGUID(targetGuid.GetCounter());
- uint32 targetGmLevel = AccountMgr::GetSecurity(targetAccountId, realmID);
+ uint32 targetGmLevel = AccountMgr::GetSecurity(targetAccountId, realm.Id.Realm);
// Target must exist and have administrative rights
if (!targetGuid || AccountMgr::IsPlayerAccount(targetGmLevel))
@@ -382,7 +383,7 @@ public:
{
ObjectGuid guid = ticket->GetAssignedToGUID();
uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(guid.GetCounter());
- security = AccountMgr::GetSecurity(accountId, realmID);
+ security = AccountMgr::GetSecurity(accountId, realm.Id.Realm);
}
// Check security
diff --git a/src/server/shared/Realms/Realm.h b/src/server/shared/Realms/Realm.h
new file mode 100644
index 0000000000..e95e197c5a
--- /dev/null
+++ b/src/server/shared/Realms/Realm.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
+ * Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
+ */
+
+#ifndef Realm_h__
+#define Realm_h__
+
+#include "Common.h"
+// #include "AsioHacksFwd.h"
+#include <ace/INET_Addr.h>
+
+enum RealmFlags
+{
+ REALM_FLAG_NONE = 0x00,
+ REALM_FLAG_VERSION_MISMATCH = 0x01,
+ REALM_FLAG_OFFLINE = 0x02,
+ REALM_FLAG_SPECIFYBUILD = 0x04,
+ REALM_FLAG_UNK1 = 0x08,
+ REALM_FLAG_UNK2 = 0x10,
+ REALM_FLAG_RECOMMENDED = 0x20,
+ REALM_FLAG_NEW = 0x40,
+ REALM_FLAG_FULL = 0x80
+};
+
+struct AC_SHARED_API RealmHandle
+{
+ RealmHandle() : Realm(0) { }
+ RealmHandle(uint32 index) : Realm(index) { }
+
+ uint32 Realm; // primary key in `realmlist` table
+
+ bool operator<(RealmHandle const& r) const
+ {
+ return Realm < r.Realm;
+ }
+};
+
+/// Type of server, this is values from second column of Cfg_Configs.dbc
+enum RealmType
+{
+ REALM_TYPE_NORMAL = 0,
+ REALM_TYPE_PVP = 1,
+ REALM_TYPE_NORMAL2 = 4,
+ REALM_TYPE_RP = 6,
+ REALM_TYPE_RPPVP = 8,
+
+ MAX_CLIENT_REALM_TYPE = 14,
+
+ REALM_TYPE_FFA_PVP = 16 // custom, free for all pvp mode like arena PvP in all zones except rest activated places and sanctuaries
+ // replaced by REALM_PVP in realm list
+};
+
+// Storage object for a realm
+struct AC_SHARED_API Realm
+{
+ RealmHandle Id;
+ uint32 Build;
+ std::unique_ptr<ACE_INET_Addr> ExternalAddress;
+ std::unique_ptr<ACE_INET_Addr> LocalAddress;
+ std::unique_ptr<ACE_INET_Addr> LocalSubnetMask;
+ uint16 Port;
+ std::string Name;
+ uint8 Type;
+ RealmFlags Flags;
+ uint8 Timezone;
+ AccountTypes AllowedSecurityLevel;
+ float PopulationLevel;
+
+ // boost::asio::ip::tcp_endpoint GetAddressForClient(boost::asio::ip::address const& clientAddr) const;
+};
+
+#endif // Realm_h__
diff --git a/src/server/shared/Realms/RealmList.cpp b/src/server/shared/Realms/RealmList.cpp
index 3e550d44ad..1bdeaee1ff 100644
--- a/src/server/shared/Realms/RealmList.cpp
+++ b/src/server/shared/Realms/RealmList.cpp
@@ -4,11 +4,14 @@
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*/
-#include "Common.h"
-#include "DatabaseEnv.h"
#include "RealmList.h"
+#include "DatabaseEnv.h"
+#include "Log.h"
+#include "Optional.h"
+#include "Util.h"
-RealmList::RealmList() : m_NextUpdateTime(time(nullptr)) { }
+RealmList::RealmList() :
+ _updateInterval(0) { }
RealmList* RealmList::instance()
{
@@ -19,81 +22,209 @@ RealmList* RealmList::instance()
// Load the realm list from the database
void RealmList::Initialize(uint32 updateInterval)
{
- m_UpdateInterval = updateInterval;
+ _updateInterval = updateInterval;
+
+ LoadBuildInfo();
// Get the content of the realmlist table in the database
- UpdateRealms(true);
+ UpdateRealms();
}
-void RealmList::UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build)
+void RealmList::LoadBuildInfo()
+{
+ // 0 1 2 3 4 5 6
+ if (QueryResult result = LoginDatabase.Query("SELECT majorVersion, minorVersion, bugfixVersion, hotfixVersion, build, winChecksumSeed, macChecksumSeed FROM build_info ORDER BY build ASC"))
+ {
+ do
+ {
+ Field* fields = result->Fetch();
+ RealmBuildInfo& build = _builds.emplace_back();
+ build.MajorVersion = fields[0].GetUInt32();
+ build.MinorVersion = fields[1].GetUInt32();
+ build.BugfixVersion = fields[2].GetUInt32();
+ std::string hotfixVersion = fields[3].GetString();
+
+ if (hotfixVersion.length() < build.HotfixVersion.size())
+ {
+ std::copy(hotfixVersion.begin(), hotfixVersion.end(), build.HotfixVersion.begin());
+ }
+ else
+ {
+ std::fill(hotfixVersion.begin(), hotfixVersion.end(), '\0');
+ }
+
+ build.Build = fields[4].GetUInt32();
+ std::string windowsHash = fields[5].GetString();
+
+ if (windowsHash.length() == build.WindowsHash.size() * 2)
+ {
+ HexStrToByteArray(windowsHash, build.WindowsHash);
+ }
+
+ std::string macHash = fields[6].GetString();
+
+ if (macHash.length() == build.MacHash.size() * 2)
+ {
+ HexStrToByteArray(macHash, build.MacHash);
+ }
+ } while (result->NextRow());
+ }
+}
+
+void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, std::string const& name,
+ ACE_INET_Addr&& address, ACE_INET_Addr&& localAddr, ACE_INET_Addr&& localSubmask,
+ uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population)
{
// Create new if not exist or update existed
- Realm& realm = m_realms[name];
-
- realm.m_ID = id;
- realm.name = name;
- realm.icon = icon;
- realm.flag = flag;
- realm.timezone = timezone;
- realm.allowedSecurityLevel = allowedSecurityLevel;
- realm.populationLevel = popu;
-
- // Append port to IP address.
- realm.ExternalAddress = address;
- realm.LocalAddress = localAddr;
- realm.LocalSubnetMask = localSubmask;
- realm.gamebuild = build;
+ Realm& realm = _realms[id];
+
+ realm.Id = id;
+ realm.Build = build;
+ realm.Name = name;
+ realm.Type = icon;
+ realm.Flags = flag;
+ realm.Timezone = timezone;
+ realm.AllowedSecurityLevel = allowedSecurityLevel;
+ realm.PopulationLevel = population;
+
+ if (!realm.ExternalAddress || *realm.ExternalAddress != address)
+ {
+ realm.ExternalAddress = std::make_unique<ACE_INET_Addr>(std::move(address));
+ }
+
+ if (!realm.LocalAddress || *realm.LocalAddress != localAddr)
+ {
+ realm.LocalAddress = std::make_unique<ACE_INET_Addr>(std::move(localAddr));
+ }
+
+ if (!realm.LocalSubnetMask || *realm.LocalSubnetMask != localSubmask)
+ {
+ realm.LocalSubnetMask = std::make_unique<ACE_INET_Addr>(std::move(localSubmask));
+ }
+
+ realm.Port = port;
}
void RealmList::UpdateIfNeed()
{
// maybe disabled or updated recently
- if (!m_UpdateInterval || m_NextUpdateTime > time(nullptr))
+ if (!_updateInterval || _nextUpdateTime > time(nullptr))
+ {
return;
+ }
- m_NextUpdateTime = time(nullptr) + m_UpdateInterval;
-
- // Clears Realm list
- m_realms.clear();
+ _nextUpdateTime = time(nullptr) + _updateInterval;
// Get the content of the realmlist table in the database
UpdateRealms();
}
-void RealmList::UpdateRealms(bool init)
+void RealmList::UpdateRealms()
{
- LOG_INFO("server", "Updating Realm List...");
+ LOG_DEBUG("server.authserver", "Updating Realm List...");
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST);
PreparedQueryResult result = LoginDatabase.Query(stmt);
+ std::map<RealmHandle, std::string> existingRealms;
+ for (auto const& [handle, realm] : _realms)
+ {
+ existingRealms[handle] = realm.Name;
+ }
+
+ _realms.clear();
+
// Circle through results and add them to the realm map
if (result)
{
do
{
- Field* fields = result->Fetch();
- uint32 realmId = fields[0].GetUInt32();
- std::string name = fields[1].GetString();
- std::string externalAddress = fields[2].GetString();
- std::string localAddress = fields[3].GetString();
- std::string localSubmask = fields[4].GetString();
- uint16 port = fields[5].GetUInt16();
- uint8 icon = fields[6].GetUInt8();
+ Field* fields = result->Fetch();
+ uint32 realmId = fields[0].GetUInt32();
+ std::string name = fields[1].GetString();
+ std::string externalAddressString = fields[2].GetString();
+ std::string localAddressString = fields[3].GetString();
+ std::string localSubmaskString = fields[4].GetString();
+ uint16 port = fields[5].GetUInt16();
+
+ Optional<ACE_INET_Addr> externalAddress = ACE_INET_Addr(port, externalAddressString.c_str(), AF_INET);
+ if (!externalAddress)
+ {
+ LOG_ERROR("server.authserver", "Could not resolve address %s for realm \"%s\" id %u", externalAddressString.c_str(), name.c_str(), realmId);
+ continue;
+ }
+
+ Optional<ACE_INET_Addr> localAddress = ACE_INET_Addr(port, localAddressString.c_str(), AF_INET);
+ if (!localAddress)
+ {
+ LOG_ERROR("server.authserver", "Could not resolve localAddress %s for realm \"%s\" id %u", localAddressString.c_str(), name.c_str(), realmId);
+ continue;
+ }
+
+ Optional<ACE_INET_Addr> localSubmask = ACE_INET_Addr(0, localSubmaskString.c_str(), AF_INET);
+ if (!localSubmask)
+ {
+ LOG_ERROR("server.authserver", "Could not resolve localSubnetMask %s for realm \"%s\" id %u", localSubmaskString.c_str(), name.c_str(), realmId);
+ continue;
+ }
+
+ uint8 icon = fields[6].GetUInt8();
+
+ if (icon == REALM_TYPE_FFA_PVP)
+ {
+ icon = REALM_TYPE_PVP;
+ }
+
+ if (icon >= MAX_CLIENT_REALM_TYPE)
+ {
+ icon = REALM_TYPE_NORMAL;
+ }
+
RealmFlags flag = RealmFlags(fields[7].GetUInt8());
uint8 timezone = fields[8].GetUInt8();
uint8 allowedSecurityLevel = fields[9].GetUInt8();
float pop = fields[10].GetFloat();
uint32 build = fields[11].GetUInt32();
- ACE_INET_Addr externalAddr(port, externalAddress.c_str(), AF_INET);
- ACE_INET_Addr localAddr(port, localAddress.c_str(), AF_INET);
- ACE_INET_Addr submask(0, localSubmask.c_str(), AF_INET);
+ RealmHandle id{ realmId };
+
+ UpdateRealm(id, build, name, std::move(externalAddress.value()), std::move(localAddress.value()), std::move(localSubmask.value()), port, icon, flag,
+ timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
- UpdateRealm(realmId, name, externalAddr, localAddr, submask, icon, flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build);
+ if (!existingRealms.count(id))
+ {
+ LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddressString.c_str(), port);
+ }
+ else
+ {
+ LOG_DEBUG("server.authserver", "Updating realm \"%s\" at %s:%u.", name.c_str(), externalAddressString.c_str(), port);
+ }
- if (init)
- LOG_INFO("server", "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.get_host_addr(), port);
+ existingRealms.erase(id);
} while (result->NextRow());
}
}
+
+Realm const* RealmList::GetRealm(RealmHandle const& id) const
+{
+ auto itr = _realms.find(id);
+ if (itr != _realms.end())
+ {
+ return &itr->second;
+ }
+
+ return nullptr;
+}
+
+RealmBuildInfo const* RealmList::GetBuildInfo(uint32 build) const
+{
+ for (RealmBuildInfo const& clientBuild : _builds)
+ {
+ if (clientBuild.Build == build)
+ {
+ return &clientBuild;
+ }
+ }
+
+ return nullptr;
+}
diff --git a/src/server/shared/Realms/RealmList.h b/src/server/shared/Realms/RealmList.h
index 1b951e51c1..938fb5aa36 100644
--- a/src/server/shared/Realms/RealmList.h
+++ b/src/server/shared/Realms/RealmList.h
@@ -7,43 +7,29 @@
#ifndef _REALMLIST_H
#define _REALMLIST_H
-#include "Common.h"
-#include <ace/INET_Addr.h>
-
-enum RealmFlags
-{
- REALM_FLAG_NONE = 0x00,
- REALM_FLAG_INVALID = 0x01,
- REALM_FLAG_OFFLINE = 0x02,
- REALM_FLAG_SPECIFYBUILD = 0x04,
- REALM_FLAG_UNK1 = 0x08,
- REALM_FLAG_UNK2 = 0x10,
- REALM_FLAG_RECOMMENDED = 0x20,
- REALM_FLAG_NEW = 0x40,
- REALM_FLAG_FULL = 0x80
-};
-
-// Storage object for a realm
-struct Realm
+#include "Define.h"
+#include "Realm.h"
+#include <array>
+#include <map>
+#include <vector>
+#include <unordered_set>
+
+struct RealmBuildInfo
{
- ACE_INET_Addr ExternalAddress;
- ACE_INET_Addr LocalAddress;
- ACE_INET_Addr LocalSubnetMask;
- std::string name;
- uint8 icon;
- RealmFlags flag;
- uint8 timezone;
- uint32 m_ID;
- AccountTypes allowedSecurityLevel;
- float populationLevel;
- uint32 gamebuild;
+ uint32 Build;
+ uint32 MajorVersion;
+ uint32 MinorVersion;
+ uint32 BugfixVersion;
+ std::array<char, 4> HotfixVersion;
+ std::array<uint8, 20> WindowsHash;
+ std::array<uint8, 20> MacHash;
};
/// Storage object for the list of realms on the server
-class RealmList
+class AC_SHARED_API RealmList
{
public:
- typedef std::map<std::string, Realm> RealmMap;
+ typedef std::map<RealmHandle, Realm> RealmMap;
RealmList();
~RealmList() = default;
@@ -52,19 +38,23 @@ public:
void Initialize(uint32 updateInterval);
void UpdateIfNeed();
- void AddRealm(const Realm& NewRealm) { m_realms[NewRealm.name] = NewRealm; }
- [[nodiscard]] RealmMap::const_iterator begin() const { return m_realms.begin(); }
- [[nodiscard]] RealmMap::const_iterator end() const { return m_realms.end(); }
- [[nodiscard]] uint32 size() const { return m_realms.size(); }
+ RealmMap const& GetRealms() const { return _realms; }
+ Realm const* GetRealm(RealmHandle const& id) const;
-private:
- void UpdateRealms(bool init = false);
- void UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build);
+ RealmBuildInfo const* GetBuildInfo(uint32 build) const;
- RealmMap m_realms;
- uint32 m_UpdateInterval{0};
- time_t m_NextUpdateTime;
+private:
+ void LoadBuildInfo();
+ void UpdateRealms();
+ void UpdateRealm(RealmHandle const& id, uint32 build, std::string const& name,
+ ACE_INET_Addr&& address, ACE_INET_Addr&& localAddr, ACE_INET_Addr&& localSubmask,
+ uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population);
+
+ std::vector<RealmBuildInfo> _builds;
+ RealmMap _realms;
+ uint32 _updateInterval;
+ time_t _nextUpdateTime;
};
#define sRealmList RealmList::instance()
diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp
index 62e840d461..0567be32ff 100644
--- a/src/server/worldserver/Main.cpp
+++ b/src/server/worldserver/Main.cpp
@@ -39,8 +39,6 @@ char serviceDescription[] = "AzerothCore World of Warcraft emulator world servic
int m_ServiceStatus = -1;
#endif
-uint32 realmID; ///< Id of the realm
-
/// Print out the usage string for this program on the console.
void usage(const char* prog)
{
diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp
index 7fe941aaa1..35f4ea78a1 100644
--- a/src/server/worldserver/Master.cpp
+++ b/src/server/worldserver/Master.cpp
@@ -20,7 +20,7 @@
#include "Master.h"
#include "OpenSSLCrypto.h"
#include "RARunnable.h"
-#include "RealmList.h"
+#include "Realm.h"
#include "ScriptMgr.h"
#include "SignalHandler.h"
#include "Timer.h"
@@ -30,6 +30,7 @@
#include "WorldSocket.h"
#include "WorldSocketMgr.h"
#include "DatabaseLoader.h"
+#include "Optional.h"
#include "SecretMgr.h"
#include <ace/Sig_Handler.h>
@@ -100,6 +101,8 @@ public:
}
};
+bool LoadRealmInfo();
+
Master* Master::instance()
{
static Master instance;
@@ -131,7 +134,9 @@ int Master::Run()
return 1;
// set server offline (not connectable)
- LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = (flag & ~%u) | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, REALM_FLAG_INVALID, realmID);
+ LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = (flag & ~%u) | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, REALM_FLAG_VERSION_MISMATCH, realm.Id.Realm);
+
+ LoadRealmInfo();
// Loading modules configs
sConfigMgr->LoadModulesConfigs();
@@ -271,7 +276,7 @@ int Master::Run()
}
// set server online (allow connecting now)
- LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag & ~%u, population = 0 WHERE id = '%u'", REALM_FLAG_INVALID, realmID);
+ LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag & ~%u, population = 0 WHERE id = '%u'", REALM_FLAG_VERSION_MISMATCH, realm.Id.Realm);
LOG_INFO("server", "%s (worldserver-daemon) ready...", GitRevision::GetFullVersion());
@@ -295,7 +300,7 @@ int Master::Run()
}
// set server offline
- LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realmID);
+ LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realm.Id.Realm);
///- Clean database before leaving
ClearOnlineAccounts();
@@ -379,16 +384,16 @@ bool Master::_StartDB()
return false;
///- Get the realm Id from the configuration file
- realmID = sConfigMgr->GetOption<int32>("RealmID", 0);
- if (!realmID)
+ realm.Id.Realm = sConfigMgr->GetOption<int32>("RealmID", 0);
+ if (!realm.Id.Realm)
{
LOG_ERROR("server", "Realm ID not defined in configuration file");
return false;
}
- else if (realmID > 255)
+ else if (realm.Id.Realm > 255)
{
/*
- * Due to the client only being able to read a realmID
+ * Due to the client only being able to read a realm.Id.Realm
* with a size of uint8 we can "only" store up to 255 realms
* anything further the client will behave anormaly
*/
@@ -396,7 +401,7 @@ bool Master::_StartDB()
return false;
}
- LOG_INFO("server", "Realm running as realm ID %d", realmID);
+ LOG_INFO("server", "Realm running as realm ID %d", realm.Id.Realm);
///- Clean the database before starting
ClearOnlineAccounts();
@@ -424,8 +429,55 @@ void Master::ClearOnlineAccounts()
{
// Reset online status for all accounts with characters on the current realm
// pussywizard: tc query would set online=0 even if logged in on another realm >_>
- LoginDatabase.DirectPExecute("UPDATE account SET online = 0 WHERE online = %u", realmID);
+ LoginDatabase.DirectPExecute("UPDATE account SET online = 0 WHERE online = %u", realm.Id.Realm);
// Reset online status for all characters
CharacterDatabase.DirectExecute("UPDATE characters SET online = 0 WHERE online <> 0");
}
+
+bool LoadRealmInfo()
+{
+ QueryResult result = LoginDatabase.PQuery("SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild FROM realmlist WHERE id = %u", realm.Id.Realm);
+ if (!result)
+ {
+ LOG_ERROR("server.worldserver", "> Not found realm with ID %u", realm.Id.Realm);
+ return false;
+ }
+
+ Field* fields = result->Fetch();
+ realm.Name = fields[1].GetString();
+ realm.Port = fields[5].GetUInt16();
+
+ Optional<ACE_INET_Addr> externalAddress = ACE_INET_Addr(realm.Port, fields[2].GetCString(), AF_INET);
+ if (!externalAddress)
+ {
+ LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[2].GetString().c_str());
+ return false;
+ }
+
+ Optional<ACE_INET_Addr> localAddress = ACE_INET_Addr(realm.Port, fields[3].GetCString(), AF_INET);
+ if (!localAddress)
+ {
+ LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[3].GetString().c_str());
+ return false;
+ }
+
+ Optional<ACE_INET_Addr> localSubmask = ACE_INET_Addr(0, fields[4].GetCString(), AF_INET);
+ if (!localSubmask)
+ {
+ LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[4].GetString().c_str());
+ return false;
+ }
+
+ realm.ExternalAddress = std::make_unique<ACE_INET_Addr>(*externalAddress);
+ realm.LocalAddress = std::make_unique<ACE_INET_Addr>(*localAddress);
+ realm.LocalSubnetMask = std::make_unique<ACE_INET_Addr>(*localSubmask);
+
+ realm.Type = fields[6].GetUInt8();
+ realm.Flags = RealmFlags(fields[7].GetUInt8());
+ realm.Timezone = fields[8].GetUInt8();
+ realm.AllowedSecurityLevel = AccountTypes(fields[9].GetUInt8());
+ realm.PopulationLevel = fields[10].GetFloat();
+ realm.Build = fields[11].GetUInt32();
+ return true;
+}
diff --git a/src/test/mocks/WorldMock.h b/src/test/mocks/WorldMock.h
index 059497bd46..f58be22e22 100644
--- a/src/test/mocks/WorldMock.h
+++ b/src/test/mocks/WorldMock.h
@@ -12,7 +12,6 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
-uint32 realmID;
void AddScripts() {}
bool ArenaSpectator::HandleSpectatorSpectateCommand(ChatHandler* handler, char const* args) { return false; }