diff options
author | Duarte Duarte <dnpd.dd@gmail.com> | 2016-03-07 00:06:37 +0000 |
---|---|---|
committer | Duarte Duarte <dnpd.dd@gmail.com> | 2016-03-07 00:06:37 +0000 |
commit | 2e1e6084503a69cec712c52140f60e876a260973 (patch) | |
tree | dcd357e753d3389423afa52532729970db95cf35 | |
parent | 83e8deaa8f9dffad33169090a7acabf001526582 (diff) | |
parent | 7b687be4ba523bc50d3caca894855275a4810c65 (diff) |
Merge pull request #16696 from TrinityCore/realm6xto335
Core: Backport 6.x realm changes
23 files changed, 284 insertions, 147 deletions
diff --git a/src/server/authserver/CMakeLists.txt b/src/server/authserver/CMakeLists.txt index d87847d6740..34e7ed8a43f 100644 --- a/src/server/authserver/CMakeLists.txt +++ b/src/server/authserver/CMakeLists.txt @@ -57,6 +57,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/database ${CMAKE_SOURCE_DIR}/src/server/database/Database ${CMAKE_SOURCE_DIR}/src/server/database/Logging + ${CMAKE_SOURCE_DIR}/src/server/shared ${CMAKE_SOURCE_DIR}/src/server/shared/Networking ${CMAKE_SOURCE_DIR}/src/server/shared/Packets ${CMAKE_SOURCE_DIR}/src/server/shared/Service diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index 0618ec437b6..939d15ceca8 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -134,7 +134,7 @@ int main(int argc, char** argv) // Get the list of realms for the server sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 20)); - if (sRealmList->size() == 0) + if (sRealmList->GetRealms().empty()) { TC_LOG_ERROR("server.authserver", "No valid realms specified."); StopDB(); @@ -194,6 +194,8 @@ int main(int argc, char** argv) sAuthSocketMgr.StopNetwork(); + sRealmList->Close(); + // Close the Database Pool and library StopDB(); diff --git a/src/server/authserver/Realms/RealmList.cpp b/src/server/authserver/Realms/RealmList.cpp index 53aeff6133b..f1b25d8554d 100644 --- a/src/server/authserver/Realms/RealmList.cpp +++ b/src/server/authserver/Realms/RealmList.cpp @@ -16,69 +16,62 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <boost/asio/ip/tcp.hpp> #include "Common.h" -#include "RealmList.h" #include "Database/DatabaseEnv.h" +#include "RealmList.h" +#include <boost/asio/ip/tcp.hpp> namespace boost { namespace asio { namespace ip { class address; } } } -RealmList::RealmList() : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)), _resolver(nullptr) { } +RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr) { } RealmList::~RealmList() { delete _resolver; + delete _updateTimer; } // Load the realm list from the database void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInterval) { + _updateInterval = updateInterval; + _updateTimer = new boost::asio::deadline_timer(ioService); _resolver = new boost::asio::ip::tcp::resolver(ioService); - m_UpdateInterval = updateInterval; // Get the content of the realmlist table in the database - UpdateRealms(true); + UpdateRealms(true, boost::system::error_code()); } -void RealmList::UpdateRealm(uint32 id, const std::string& name, ip::address const& address, ip::address const& localAddr, - ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build) +void RealmList::Close() { - // 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 = population; - - // Append port to IP address. + _updateTimer->cancel(); +} +void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr, + ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, + float population) +{ + // Create new if not exist or update existed + 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; realm.ExternalAddress = address; realm.LocalAddress = localAddr; realm.LocalSubnetMask = localSubmask; - realm.port = port; - realm.gamebuild = build; + realm.Port = port; } -void RealmList::UpdateIfNeed() +void RealmList::UpdateRealms(bool init, boost::system::error_code const& error) { - // maybe disabled or updated recently - if (!m_UpdateInterval || m_NextUpdateTime > time(NULL)) + if (error) return; - m_NextUpdateTime = time(NULL) + m_UpdateInterval; - - // Clears Realm list - m_realms.clear(); - - // Get the content of the realmlist table in the database - UpdateRealms(); -} - -void RealmList::UpdateRealms(bool init) -{ TC_LOG_INFO("server.authserver", "Updating Realm List..."); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST); @@ -130,17 +123,23 @@ void RealmList::UpdateRealms(bool init) uint16 port = fields[5].GetUInt16(); 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(); - UpdateRealm(realmId, name, externalAddress, localAddress, localSubmask, port, icon, flag, timezone, - (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build); + RealmHandle id{ realmId }; + + UpdateRealm(id, build, name, externalAddress, localAddress, localSubmask, port, icon, flag, + timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop); if (init) - TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.to_string().c_str(), port); + TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port); } catch (std::exception& ex) { @@ -150,4 +149,19 @@ void RealmList::UpdateRealms(bool init) } while (result->NextRow()); } + + if (_updateInterval) + { + _updateTimer->expires_from_now(boost::posix_time::seconds(_updateInterval)); + _updateTimer->async_wait(std::bind(&RealmList::UpdateRealms, this, false, std::placeholders::_1)); + } +} + +Realm const* RealmList::GetRealm(RealmHandle const& id) const +{ + auto itr = _realms.find(id); + if (itr != _realms.end()) + return &itr->second; + + return NULL; } diff --git a/src/server/authserver/Realms/RealmList.h b/src/server/authserver/Realms/RealmList.h index cc5c88c01f2..e35975b215a 100644 --- a/src/server/authserver/Realms/RealmList.h +++ b/src/server/authserver/Realms/RealmList.h @@ -19,48 +19,20 @@ #ifndef _REALMLIST_H #define _REALMLIST_H +#include "Common.h" +#include "Realm/Realm.h" #include <boost/asio/ip/address.hpp> #include <boost/asio/ip/tcp.hpp> #include <boost/asio/io_service.hpp> -#include "Common.h" +#include <boost/asio/deadline_timer.hpp> using namespace boost::asio; -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 -{ - ip::address ExternalAddress; - ip::address LocalAddress; - ip::address LocalSubnetMask; - uint16 port; - std::string name; - uint8 icon; - RealmFlags flag; - uint8 timezone; - uint32 m_ID; - AccountTypes allowedSecurityLevel; - float populationLevel; - uint32 gamebuild; -}; - /// Storage object for the list of realms on the server class RealmList { public: - typedef std::map<std::string, Realm> RealmMap; + typedef std::map<RealmHandle, Realm> RealmMap; static RealmList* instance() { @@ -71,25 +43,21 @@ public: ~RealmList(); void Initialize(boost::asio::io_service& ioService, uint32 updateInterval); + void Close(); - void UpdateIfNeed(); - - void AddRealm(const Realm& NewRealm) { m_realms[NewRealm.name] = NewRealm; } - - RealmMap::const_iterator begin() const { return m_realms.begin(); } - RealmMap::const_iterator end() const { return m_realms.end(); } - uint32 size() const { return m_realms.size(); } + RealmMap const& GetRealms() const { return _realms; } + Realm const* GetRealm(RealmHandle const& id) const; private: RealmList(); - void UpdateRealms(bool init = false); - void UpdateRealm(uint32 id, const std::string& name, ip::address const& address, ip::address const& localAddr, - ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build); + void UpdateRealms(bool init, boost::system::error_code const& error); + void UpdateRealm(RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr, + ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population); - RealmMap m_realms; - uint32 m_UpdateInterval; - time_t m_NextUpdateTime; + RealmMap _realms; + uint32 _updateInterval; + boost::asio::deadline_timer* _updateTimer; boost::asio::ip::tcp::resolver* _resolver; }; diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index 57e5d6682f2..e0b463b74ad 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -844,7 +844,7 @@ tcp::endpoint const GetAddressForClient(Realm const& realm, ip::address const& c realmIp = realm.ExternalAddress; } - tcp::endpoint endpoint(realmIp, realm.port); + tcp::endpoint endpoint(realmIp, realm.Port); // Return external IP return endpoint; @@ -880,22 +880,19 @@ void AuthSession::RealmListCallback(PreparedQueryResult result) } while (result->NextRow()); } - // Update realm list if need - sRealmList->UpdateIfNeed(); - // 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 (RealmList::RealmMap::value_type const& i : sRealmList->GetRealms()) { - const Realm &realm = i->second; + 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 = AuthHelper::GetBuildInfo(realm.Build); if (!okBuild) { if (!buildInfo) @@ -907,7 +904,7 @@ void AuthSession::RealmListCallback(PreparedQueryResult result) 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; @@ -915,19 +912,19 @@ void AuthSession::RealmListCallback(PreparedQueryResult result) name = ss.str(); } - uint8 lock = (realm.allowedSecurityLevel > _accountInfo.SecurityLevel) ? 1 : 0; + uint8 lock = (realm.AllowedSecurityLevel > _accountInfo.SecurityLevel) ? 1 : 0; - pkt << uint8(realm.icon); // realm type + pkt << uint8(realm.Type); // realm type if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients pkt << uint8(lock); // if 1, then realm locked pkt << uint8(flag); // RealmFlags pkt << name; pkt << boost::lexical_cast<std::string>(GetAddressForClient(realm, GetRemoteIpAddress())); - pkt << float(realm.populationLevel); - pkt << uint8(characterCounts[realm.m_ID]); - pkt << uint8(realm.timezone); // realm category + pkt << float(realm.PopulationLevel); + pkt << uint8(characterCounts[realm.Id.Realm]); + pkt << uint8(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/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 737e9f37195..a0bd6a08b2c 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -462,7 +462,7 @@ void AccountMgr::LoadRBAC() while (result->NextRow()); TC_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading default permissions"); - result = LoginDatabase.PQuery("SELECT secId, permissionId FROM rbac_default_permissions WHERE (realmId = %u OR realmId = -1) ORDER BY secId ASC", realmID); + result = LoginDatabase.PQuery("SELECT secId, permissionId FROM rbac_default_permissions WHERE (realmId = %u OR realmId = -1) ORDER BY secId ASC", realm.Id.Realm); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 default permission definitions. DB table `rbac_default_permissions` is empty."); diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index 035d9af4369..01ffc9f1093 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -130,7 +130,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction& else { bidderAccId = sObjectMgr->GetPlayerAccountIdByGUID(bidderGuid); - logGmTrade = AccountMgr::HasPermission(bidderAccId, rbac::RBAC_PERM_LOG_GM_TRADE, realmID); + logGmTrade = AccountMgr::HasPermission(bidderAccId, rbac::RBAC_PERM_LOG_GM_TRADE, realm.Id.Realm); if (logGmTrade && !sObjectMgr->GetPlayerNameByGUID(bidderGuid, bidderName)) bidderName = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN); diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index 4d41fbc32eb..58aec3aa1cf 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -196,6 +196,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference ${CMAKE_SOURCE_DIR}/src/server/shared/Networking ${CMAKE_SOURCE_DIR}/src/server/shared/Packets + ${CMAKE_SOURCE_DIR}/src/server/shared/Realm ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index aa0f6ce09fc..f0e98ee8c1f 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -108,7 +108,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 == NULL && target_account == 0) diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index e0d790312d2..7b1caffd84f 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -627,13 +627,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); diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 45cee59aec9..7e25699352b 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -569,7 +569,7 @@ void WorldSession::HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std team = Player::TeamForRace(fields[1].GetUInt8()); friendAccountId = fields[2].GetUInt32(); - if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realmID))) + if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realm.Id.Realm))) { if (friendGuid) { diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index c380c1a5627..34ed31a7813 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -1220,7 +1220,7 @@ void WorldSession::LoadPermissions() uint32 id = GetAccountId(); uint8 secLevel = GetSecurity(); - _RBACData = new rbac::RBACData(id, _accountName, realmID, secLevel); + _RBACData = new rbac::RBACData(id, _accountName, realm.Id.Realm, secLevel); _RBACData->LoadFromDB(); } @@ -1230,9 +1230,9 @@ PreparedQueryResultFuture WorldSession::LoadPermissionsAsync() uint8 secLevel = GetSecurity(); TC_LOG_DEBUG("rbac", "WorldSession::LoadPermissions [AccountId: %u, Name: %s, realmId: %d, secLevel: %u]", - id, _accountName.c_str(), realmID, secLevel); + id, _accountName.c_str(), realm.Id.Realm, secLevel); - _RBACData = new rbac::RBACData(id, _accountName, realmID, secLevel); + _RBACData = new rbac::RBACData(id, _accountName, realm.Id.Realm, secLevel); return _RBACData->LoadFromDBAsync(); } @@ -1310,7 +1310,7 @@ bool WorldSession::HasPermission(uint32 permission) bool hasPermission = _RBACData->HasPermission(permission); TC_LOG_DEBUG("rbac", "WorldSession::HasPermission [AccountId: %u, Name: %s, realmId: %d]", - _RBACData->GetId(), _RBACData->GetName().c_str(), realmID); + _RBACData->GetId(), _RBACData->GetName().c_str(), realm.Id.Realm); return hasPermission; } @@ -1318,7 +1318,7 @@ bool WorldSession::HasPermission(uint32 permission) void WorldSession::InvalidateRBACData() { TC_LOG_DEBUG("rbac", "WorldSession::Invalidaterbac::RBACData [AccountId: %u, Name: %s, realmId: %d]", - _RBACData->GetId(), _RBACData->GetName().c_str(), realmID); + _RBACData->GetId(), _RBACData->GetName().c_str(), realm.Id.Realm); delete _RBACData; _RBACData = NULL; } diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 36029113055..9447204e2b9 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -414,7 +414,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket) // Get the account information from the auth database PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME); - stmt->setInt32(0, int32(realmID)); + stmt->setInt32(0, int32(realm.Id.Realm)); stmt->setString(1, authSession->Account); _queryCallback = std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1); @@ -457,7 +457,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSes return; } - if (authSession->RealmID != realmID) + if (authSession->RealmID != realm.Id.Realm) { SendAuthResponseError(REALM_LIST_REALM_NOT_FOUND); TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (bad realm)."); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index b238b0a356d..f67930a849f 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1369,7 +1369,7 @@ void World::SetInitialWorldSettings() uint32 server_type = IsFFAPvPRealm() ? uint32(REALM_TYPE_PVP) : getIntConfig(CONFIG_GAME_TYPE); 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 ///- Load the DBC files TC_LOG_INFO("server.loading", "Initialize data stores..."); @@ -1790,7 +1790,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); @@ -2103,7 +2103,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); @@ -2826,13 +2826,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); LoginDatabase.Execute(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); LoginDatabase.Execute(stmt); } } @@ -2960,7 +2960,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) diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 2f1580d887c..bf7d2cb00f7 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -29,6 +29,7 @@ #include "SharedDefines.h" #include "QueryResult.h" #include "Callback.h" +#include "Realm/Realm.h" #include <atomic> #include <map> @@ -446,18 +447,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 @@ -882,7 +871,7 @@ class World std::deque<std::future<PreparedQueryResult>> m_realmCharCallbacks; }; -extern uint32 realmID; +extern Realm realm; #define sWorld World::instance() #endif diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp index e03942bc247..ffe8ea67816 100644 --- a/src/server/scripts/Commands/cs_gm.cpp +++ b/src/server/scripts/Commands/cs_gm.cpp @@ -164,7 +164,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 c70246f7fb5..78eb3584908 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1588,7 +1588,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 result = LoginDatabase.Query(stmt); diff --git a/src/server/scripts/Commands/cs_rbac.cpp b/src/server/scripts/Commands/cs_rbac.cpp index f7c2d21c12d..ab4bc4b631e 100644 --- a/src/server/scripts/Commands/cs_rbac.cpp +++ b/src/server/scripts/Commands/cs_rbac.cpp @@ -157,7 +157,7 @@ public: if (!rdata) { - data->rbac = new rbac::RBACData(accountId, accountName, realmID, AccountMgr::GetSecurity(accountId, realmID)); + data->rbac = new rbac::RBACData(accountId, accountName, realm.Id.Realm, AccountMgr::GetSecurity(accountId, realm.Id.Realm)); data->rbac->LoadFromDB(); data->needDelete = true; } diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index c5c85f5f3cc..899c5615206 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -95,7 +95,7 @@ public: ObjectGuid targetGuid = sObjectMgr->GetPlayerGUIDByName(target); uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(targetGuid); // Target must exist and have administrative rights - if (!AccountMgr::HasPermission(accountId, rbac::RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET, realmID)) + if (!AccountMgr::HasPermission(accountId, rbac::RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET, realm.Id.Realm)) { handler->SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A); return true; @@ -119,7 +119,7 @@ public: // Assign ticket SQLTransaction trans = SQLTransaction(NULL); - ticket->SetAssignedTo(targetGuid, AccountMgr::IsAdminAccount(AccountMgr::GetSecurity(accountId, realmID))); + ticket->SetAssignedTo(targetGuid, AccountMgr::IsAdminAccount(AccountMgr::GetSecurity(accountId, realm.Id.Realm))); ticket->SaveToDB(trans); sTicketMgr->UpdateLastChange(); @@ -387,7 +387,7 @@ public: { ObjectGuid guid = ticket->GetAssignedToGUID(); uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(guid); - security = AccountMgr::GetSecurity(accountId, realmID); + security = AccountMgr::GetSecurity(accountId, realm.Id.Realm); } // Check security diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt index b6e5c8b1c6f..64abecff8f7 100644 --- a/src/server/shared/CMakeLists.txt +++ b/src/server/shared/CMakeLists.txt @@ -16,6 +16,7 @@ file(GLOB_RECURSE sources_DataStores DataStores/*.cpp DataStores/*.h) file(GLOB_RECURSE sources_Dynamic Dynamic/*.cpp Dynamic/*.h) file(GLOB_RECURSE sources_Networking Networking/*.cpp Networking/*.h) file(GLOB_RECURSE sources_Packets Packets/*.cpp Packets/*.h) +file(GLOB_RECURSE sources_Realm Realm/*.cpp Realm/*.h) if( WIN32 ) file(GLOB_RECURSE sources_Service Service/*.cpp Service/*.h) endif( WIN32 ) @@ -36,6 +37,7 @@ set(shared_STAT_SRCS ${sources_Dynamic} ${sources_Networking} ${sources_Packets} + ${sources_Realm} ${sources_Utilities} ${sources_Service} ${sources_localdir} @@ -44,6 +46,7 @@ set(shared_STAT_SRCS include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Dynamic ${CMAKE_CURRENT_SOURCE_DIR}/Networking + ${CMAKE_CURRENT_SOURCE_DIR}/Realm ${CMAKE_SOURCE_DIR}/dep/cppformat ${CMAKE_SOURCE_DIR}/src/common/ ${CMAKE_SOURCE_DIR}/src/common/Debugging diff --git a/src/server/shared/Realm/Realm.cpp b/src/server/shared/Realm/Realm.cpp new file mode 100644 index 00000000000..0c8f4d1d492 --- /dev/null +++ b/src/server/shared/Realm/Realm.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Realm.h" diff --git a/src/server/shared/Realm/Realm.h b/src/server/shared/Realm/Realm.h new file mode 100644 index 00000000000..83a344dd817 --- /dev/null +++ b/src/server/shared/Realm/Realm.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef Realm_h__ +#define Realm_h__ + +#include "Common.h" +#include <boost/asio/ip/address.hpp> +#include <boost/asio/ip/tcp.hpp> + +using namespace boost::asio; + +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 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 Realm +{ + RealmHandle Id; + uint32 Build; + ip::address ExternalAddress; + ip::address LocalAddress; + ip::address LocalSubnetMask; + uint16 Port; + std::string Name; + uint8 Type; // icon + RealmFlags Flags; + uint8 Timezone; + AccountTypes AllowedSecurityLevel; + float PopulationLevel; +}; + +#endif // Realm_h__ diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 58ddce532c0..007a58ced79 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -34,7 +34,6 @@ #include "OpenSSLCrypto.h" #include "ProcessPriority.h" #include "BigNumber.h" -#include "RealmList.h" #include "World.h" #include "MapManager.h" #include "InstanceSaveMgr.h" @@ -47,6 +46,7 @@ #include "GitRevision.h" #include "WorldSocket.h" #include "WorldSocketMgr.h" +#include "Realm/Realm.h" #include "DatabaseLoader.h" #include "AppenderDB.h" @@ -81,7 +81,7 @@ uint32 _maxCoreStuckTimeInMs(0); WorldDatabaseWorkerPool WorldDatabase; ///< Accessor to the world database CharacterDatabaseWorkerPool CharacterDatabase; ///< Accessor to the character database LoginDatabaseWorkerPool LoginDatabase; ///< Accessor to the realm/login database -uint32 realmID; ///< Id of the realm +Realm realm; void SignalHandler(const boost::system::error_code& error, int signalNumber); void FreezeDetectorHandler(const boost::system::error_code& error); @@ -92,6 +92,7 @@ void WorldUpdateLoop(); void ClearOnlineAccounts(); void ShutdownCLIThread(std::thread* cliThread); void ShutdownThreadPool(std::vector<std::thread>& threadPool); +bool LoadRealmInfo(); variables_map GetConsoleArguments(int argc, char** argv, std::string& cfg_file, std::string& cfg_service); /// Launch the Trinity server @@ -188,7 +189,9 @@ extern int main(int argc, char** argv) } // 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 WHERE id = '%d'", REALM_FLAG_OFFLINE, realm.Id.Realm); + + LoadRealmInfo(); // Initialize the World sWorld->SetInitialWorldSettings(); @@ -223,7 +226,9 @@ extern int main(int argc, char** argv) sWorldSocketMgr.StartNetwork(_ioService, worldListener, worldPort); // 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_OFFLINE, realm.Id.Realm); + realm.PopulationLevel = 0.0f; + realm.Flags = RealmFlags(realm.Flags & ~uint32(REALM_FLAG_OFFLINE)); // Start the freeze check callback cycle in 5 seconds (cycle itself is 1 sec) if (int coreStuckTime = sConfigMgr->GetIntDefault("MaxCoreStuckTime", 0)) @@ -259,7 +264,7 @@ extern int main(int argc, char** argv) sScriptMgr->Unload(); // 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 up threads if any if (soapThread != nullptr) @@ -441,6 +446,59 @@ AsyncAcceptor* StartRaSocketAcceptor(boost::asio::io_service& ioService) return acceptor; } +bool LoadRealmInfo() +{ + boost::asio::ip::tcp::resolver resolver(_ioService); + boost::asio::ip::tcp::resolver::iterator end; + + 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) + return false; + + Field* fields = result->Fetch(); + realm.Name = fields[1].GetString(); + boost::asio::ip::tcp::resolver::query externalAddressQuery(ip::tcp::v4(), fields[2].GetString(), ""); + + boost::system::error_code ec; + boost::asio::ip::tcp::resolver::iterator endPoint = resolver.resolve(externalAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[2].GetString().c_str()); + return false; + } + + realm.ExternalAddress = (*endPoint).endpoint().address(); + + boost::asio::ip::tcp::resolver::query localAddressQuery(ip::tcp::v4(), fields[3].GetString(), ""); + endPoint = resolver.resolve(localAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[3].GetString().c_str()); + return false; + } + + realm.LocalAddress = (*endPoint).endpoint().address(); + + boost::asio::ip::tcp::resolver::query localSubmaskQuery(ip::tcp::v4(), fields[4].GetString(), ""); + endPoint = resolver.resolve(localSubmaskQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[4].GetString().c_str()); + return false; + } + + realm.LocalSubnetMask = (*endPoint).endpoint().address(); + + realm.Port = fields[5].GetUInt16(); + 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; +} + /// Initialize connection to the databases bool StartDB() { @@ -457,13 +515,14 @@ bool StartDB() return false; ///- Get the realm Id from the configuration file - realmID = sConfigMgr->GetIntDefault("RealmID", 0); - if (!realmID) + realm.Id.Realm = sConfigMgr->GetIntDefault("RealmID", 0); + if (!realm.Id.Realm) { TC_LOG_ERROR("server.worldserver", "Realm ID not defined in configuration file"); return false; } - TC_LOG_INFO("server.worldserver", "Realm running as realm ID %d", realmID); + + TC_LOG_INFO("server.worldserver", "Realm running as realm ID %d", realm.Id.Realm); ///- Clean the database before starting ClearOnlineAccounts(); @@ -490,7 +549,7 @@ void StopDB() void ClearOnlineAccounts() { // Reset online status for all accounts with characters on the current realm - LoginDatabase.DirectPExecute("UPDATE account SET online = 0 WHERE online > 0 AND id IN (SELECT acctid FROM realmcharacters WHERE realmid = %d)", realmID); + LoginDatabase.DirectPExecute("UPDATE account SET online = 0 WHERE online > 0 AND id IN (SELECT acctid FROM realmcharacters WHERE realmid = %d)", realm.Id.Realm); // Reset online status for all characters CharacterDatabase.DirectExecute("UPDATE characters SET online = 0 WHERE online <> 0"); |