diff options
author | Shauren <shauren.trinity@gmail.com> | 2020-07-30 17:41:20 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-01-24 13:38:40 +0100 |
commit | 54a6e603ffc8b4913669cf0f189a966d25b620d8 (patch) | |
tree | 3b0f83d7e12a899113715cb018c4c2b9315141ed /src/server | |
parent | 1977d26050d1b0c6f2d21fe3316147ae0df9fc64 (diff) |
Core/Misc: Replace database query in WorldSession::HandleAddFriendOpcode with async version
(cherry picked from commit 2f0893d279ddab86ae7c3e4fd1d7a47b15e938f7)
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/database/Database/Implementation/LoginDatabase.cpp | 3 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/LoginDatabase.h | 1 | ||||
-rw-r--r-- | src/server/game/Accounts/AccountMgr.cpp | 16 | ||||
-rw-r--r-- | src/server/game/Accounts/AccountMgr.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Player/SocialMgr.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Player/SocialMgr.h | 2 | ||||
-rw-r--r-- | src/server/game/Handlers/SocialHandler.cpp | 93 | ||||
-rw-r--r-- | src/server/worldserver/TCSoap/TCSoap.cpp | 3 |
8 files changed, 80 insertions, 42 deletions
diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp index b26b4565bad..199c298576a 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.cpp +++ b/src/server/database/Database/Implementation/LoginDatabase.cpp @@ -77,8 +77,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM, "DELETE FROM account_access WHERE AccountID = ? AND (RealmID = ? OR RealmID = -1)", CONNECTION_ASYNC); PrepareStatement(LOGIN_INS_ACCOUNT_ACCESS, "INSERT INTO account_access (AccountID, SecurityLevel, RealmID) VALUES (?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH); - PrepareStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL, "SELECT SecurityLevel FROM account_access WHERE AccountID = ?", CONNECTION_SYNCH); - PrepareStatement(LOGIN_GET_GMLEVEL_BY_REALMID, "SELECT SecurityLevel FROM account_access WHERE AccountID = ? AND (RealmID = ? OR RealmID = -1)", CONNECTION_SYNCH); + PrepareStatement(LOGIN_GET_GMLEVEL_BY_REALMID, "SELECT SecurityLevel FROM account_access WHERE AccountID = ? AND (RealmID = ? OR RealmID = -1) ORDER BY RealmID DESC", CONNECTION_BOTH); PrepareStatement(LOGIN_GET_USERNAME_BY_ID, "SELECT username FROM account WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT salt, verifier FROM account WHERE id = ? AND salt IS NOT NULL AND verifier IS NOT NULL", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT salt, verifier FROM account WHERE username = ? AND salt IS NOT NULL AND verifier IS NOT NULL", CONNECTION_SYNCH); diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h index 1f0d9ff6e52..e83675bd394 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.h +++ b/src/server/database/Database/Implementation/LoginDatabase.h @@ -77,7 +77,6 @@ enum LoginDatabaseStatements : uint32 LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM, LOGIN_INS_ACCOUNT_ACCESS, LOGIN_GET_ACCOUNT_ID_BY_USERNAME, - LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL, LOGIN_GET_GMLEVEL_BY_REALMID, LOGIN_GET_USERNAME_BY_ID, LOGIN_SEL_CHECK_PASSWORD, diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 7fc2a303926..2875a08179c 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -314,23 +314,25 @@ uint32 AccountMgr::GetId(std::string const& username) return (result) ? (*result)[0].GetUInt32() : 0; } -uint32 AccountMgr::GetSecurity(uint32 accountId) +uint32 AccountMgr::GetSecurity(uint32 accountId, int32 realmId) { - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL); + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID); stmt->setUInt32(0, accountId); + stmt->setInt32(1, realmId); PreparedQueryResult result = LoginDatabase.Query(stmt); return (result) ? (*result)[0].GetUInt8() : uint32(SEC_PLAYER); } -uint32 AccountMgr::GetSecurity(uint32 accountId, int32 realmId) +QueryCallback AccountMgr::GetSecurityAsync(uint32 accountId, int32 realmId, std::function<void(uint32)> callback) { LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID); stmt->setUInt32(0, accountId); stmt->setInt32(1, realmId); - PreparedQueryResult result = LoginDatabase.Query(stmt); - - return (result) ? (*result)[0].GetUInt8() : uint32(SEC_PLAYER); + return LoginDatabase.AsyncQuery(stmt).WithPreparedCallback([callback = std::move(callback)](PreparedQueryResult result) + { + callback(result ? uint32((*result)[0].GetUInt8()) : uint32(SEC_PLAYER)); + }); } bool AccountMgr::GetName(uint32 accountId, std::string& name) @@ -580,7 +582,7 @@ bool AccountMgr::HasPermission(uint32 accountId, uint32 permissionId, uint32 rea return false; } - rbac::RBACData rbac(accountId, "", realmId, GetSecurity(accountId)); + rbac::RBACData rbac(accountId, "", realmId, GetSecurity(accountId, realmId)); rbac.LoadFromDB(); bool hasPermission = rbac.HasPermission(permissionId); diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h index 45d8b8cf7ee..41a1948fdd4 100644 --- a/src/server/game/Accounts/AccountMgr.h +++ b/src/server/game/Accounts/AccountMgr.h @@ -68,8 +68,8 @@ class TC_GAME_API AccountMgr static bool CheckEmail(uint32 accountId, std::string newEmail); static uint32 GetId(std::string const& username); - static uint32 GetSecurity(uint32 accountId); static uint32 GetSecurity(uint32 accountId, int32 realmId); + [[nodiscard]] static QueryCallback GetSecurityAsync(uint32 accountId, int32 realmId, std::function<void(uint32)> callback); static bool GetName(uint32 accountId, std::string& name); static bool GetEmail(uint32 accountId, std::string& email); static uint32 GetCharactersCount(uint32 accountId); diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp index ecf60f20302..b00b3a2c9c5 100644 --- a/src/server/game/Entities/Player/SocialMgr.cpp +++ b/src/server/game/Entities/Player/SocialMgr.cpp @@ -164,7 +164,7 @@ void PlayerSocial::SendSocialList(Player* player, uint32 flags) if (++ignoredCount > SOCIALMGR_IGNORE_LIMIT) continue; - sSocialMgr->GetFriendInfo(player, v.first, v.second); + SocialMgr::GetFriendInfo(player, v.first, v.second); contactList.Contacts.emplace_back(v.first, v.second); } diff --git a/src/server/game/Entities/Player/SocialMgr.h b/src/server/game/Entities/Player/SocialMgr.h index af8590d07aa..f2db116aae7 100644 --- a/src/server/game/Entities/Player/SocialMgr.h +++ b/src/server/game/Entities/Player/SocialMgr.h @@ -144,7 +144,7 @@ class SocialMgr // Misc void RemovePlayerSocial(ObjectGuid const& guid) { _socialMap.erase(guid); } - void GetFriendInfo(Player* player, ObjectGuid const& friendGUID, FriendInfo& friendInfo); + static void GetFriendInfo(Player* player, ObjectGuid const& friendGUID, FriendInfo& friendInfo); // Packet send's void SendFriendStatus(Player* player, FriendsResult result, ObjectGuid const& friendGuid, bool broadcast = false); diff --git a/src/server/game/Handlers/SocialHandler.cpp b/src/server/game/Handlers/SocialHandler.cpp index 98fddfb491f..e84c64ab1f0 100644 --- a/src/server/game/Handlers/SocialHandler.cpp +++ b/src/server/game/Handlers/SocialHandler.cpp @@ -23,6 +23,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Player.h" +#include "QueryCallback.h" #include "RBAC.h" #include "Realm.h" #include "SocialMgr.h" @@ -43,41 +44,77 @@ void WorldSession::HandleAddFriendOpcode(WorldPackets::Social::AddFriend& packet TC_LOG_DEBUG("network", "WorldSession::HandleAddFriendOpcode: %s asked to add friend: %s", GetPlayerInfo().c_str(), packet.Name.c_str()); - FriendsResult friendResult = FRIEND_NOT_FOUND; - ObjectGuid friendGuid; - - if (CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByName(packet.Name)) + CharacterCacheEntry const* friendCharacterInfo = sCharacterCache->GetCharacterCacheByName(packet.Name); + if (!friendCharacterInfo) { - friendGuid = characterInfo->Guid; - ObjectGuid friendAccountGuid = ObjectGuid::Create<HighGuid::WowAccount>(characterInfo->AccountId); - uint32 team = Player::TeamForRace(characterInfo->Race); - uint32 friendAccountId = characterInfo->AccountId; + sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_NOT_FOUND, ObjectGuid::Empty); + return; + } - if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realm.Id.Realm))) + auto processFriendRequest = [this, + playerGuid = _player->GetGUID(), + friendGuid = friendCharacterInfo->Guid, + friendAccountGuid = ObjectGuid::Create<HighGuid::WowAccount>(friendCharacterInfo->AccountId), + team = Player::TeamForRace(friendCharacterInfo->Race), + friendNote = std::move(packet.Notes)]() + { + if (playerGuid.GetCounter() != m_GUIDLow) + return; // not the player initiating request, do nothing + + FriendsResult friendResult = FRIEND_NOT_FOUND; + if (friendGuid == GetPlayer()->GetGUID()) + friendResult = FRIEND_SELF; + else if (GetPlayer()->GetTeam() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND)) + friendResult = FRIEND_ENEMY; + else if (GetPlayer()->GetSocial()->HasFriend(friendGuid)) + friendResult = FRIEND_ALREADY; + else { - if (friendGuid == GetPlayer()->GetGUID()) - friendResult = FRIEND_SELF; - else if (GetPlayer()->GetTeam() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND)) - friendResult = FRIEND_ENEMY; - else if (GetPlayer()->GetSocial()->HasFriend(friendGuid)) - friendResult = FRIEND_ALREADY; + Player* pFriend = ObjectAccessor::FindPlayer(friendGuid); + if (pFriend && pFriend->IsVisibleGloballyFor(GetPlayer())) + friendResult = FRIEND_ADDED_ONLINE; else - { - Player* playerFriend = ObjectAccessor::FindPlayer(friendGuid); - if (playerFriend && playerFriend->IsVisibleGloballyFor(GetPlayer())) - friendResult = FRIEND_ADDED_ONLINE; - else - friendResult = FRIEND_ADDED_OFFLINE; - - if (GetPlayer()->GetSocial()->AddToSocialList(friendGuid, friendAccountGuid, SOCIAL_FLAG_FRIEND)) - GetPlayer()->GetSocial()->SetFriendNote(friendGuid, packet.Notes); - else - friendResult = FRIEND_LIST_FULL; - } + friendResult = FRIEND_ADDED_OFFLINE; + if (GetPlayer()->GetSocial()->AddToSocialList(friendGuid, friendAccountGuid, SOCIAL_FLAG_FRIEND)) + GetPlayer()->GetSocial()->SetFriendNote(friendGuid, friendNote); + else + friendResult = FRIEND_LIST_FULL; + } + + sSocialMgr->SendFriendStatus(GetPlayer(), friendResult, friendGuid); + }; + + if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND)) + { + processFriendRequest(); + return; + } + + // First try looking up friend candidate security from online object + if (Player* friendPlayer = ObjectAccessor::FindPlayer(friendCharacterInfo->Guid)) + { + if (!AccountMgr::IsPlayerAccount(friendPlayer->GetSession()->GetSecurity())) + { + sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_NOT_FOUND, ObjectGuid::Empty); + return; } + + processFriendRequest(); + return; } - sSocialMgr->SendFriendStatus(GetPlayer(), friendResult, friendGuid); + // When not found, consult database + GetQueryProcessor().AddCallback(AccountMgr::GetSecurityAsync(friendCharacterInfo->AccountId, realm.Id.Realm, + [this, continuation = std::move(processFriendRequest)](uint32 friendSecurity) + { + if (!AccountMgr::IsPlayerAccount(friendSecurity)) + { + sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_NOT_FOUND, ObjectGuid::Empty); + return; + } + + continuation(); + })); } void WorldSession::HandleDelFriendOpcode(WorldPackets::Social::DelFriend& packet) diff --git a/src/server/worldserver/TCSoap/TCSoap.cpp b/src/server/worldserver/TCSoap/TCSoap.cpp index 996e9d5e82e..868c649e0e8 100644 --- a/src/server/worldserver/TCSoap/TCSoap.cpp +++ b/src/server/worldserver/TCSoap/TCSoap.cpp @@ -18,6 +18,7 @@ #include "TCSoap.h" #include "soapH.h" #include "soapStub.h" +#include "Realm.h" #include "World.h" #include "AccountMgr.h" #include "Log.h" @@ -95,7 +96,7 @@ int ns1__executeCommand(soap* soap, char* command, char** result) return 401; } - if (AccountMgr::GetSecurity(accountId) < SEC_ADMINISTRATOR) + if (AccountMgr::GetSecurity(accountId, realm.Id.Realm) < SEC_ADMINISTRATOR) { TC_LOG_INFO("network.soap", "%s's gmlevel is too low", soap->userid); return 403; |