mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Misc: Replace database query in WorldSession::HandleAddFriendOpcode with async version
This commit is contained in:
@@ -82,8 +82,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 1 FROM account WHERE id = ? AND sha_pass_hash = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT 1 FROM account WHERE username = ? AND sha_pass_hash = ?", CONNECTION_SYNCH);
|
||||
|
||||
@@ -81,7 +81,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,
|
||||
|
||||
@@ -283,15 +283,6 @@ uint32 AccountMgr::GetId(std::string const& username)
|
||||
return (result) ? (*result)[0].GetUInt32() : 0;
|
||||
}
|
||||
|
||||
uint32 AccountMgr::GetSecurity(uint32 accountId)
|
||||
{
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL);
|
||||
stmt->setUInt32(0, accountId);
|
||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||
|
||||
return (result) ? (*result)[0].GetUInt8() : uint32(SEC_PLAYER);
|
||||
}
|
||||
|
||||
uint32 AccountMgr::GetSecurity(uint32 accountId, int32 realmId)
|
||||
{
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID);
|
||||
@@ -302,6 +293,17 @@ uint32 AccountMgr::GetSecurity(uint32 accountId, int32 realmId)
|
||||
return (result) ? (*result)[0].GetUInt8() : uint32(SEC_PLAYER);
|
||||
}
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_USERNAME_BY_ID);
|
||||
@@ -548,7 +550,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);
|
||||
|
||||
|
||||
@@ -67,8 +67,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);
|
||||
|
||||
@@ -151,7 +151,7 @@ void PlayerSocial::SendSocialList(Player* player, uint32 flags)
|
||||
continue;
|
||||
|
||||
++totalCount;
|
||||
sSocialMgr->GetFriendInfo(player, v.first, v.second);
|
||||
SocialMgr::GetFriendInfo(player, v.first, v.second);
|
||||
|
||||
data << uint64(v.first); // player guid
|
||||
data << uint32(contactFlags); // player flag (0x1 = Friend, 0x2 = Ignored, 0x4 = Muted)
|
||||
|
||||
@@ -142,7 +142,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);
|
||||
|
||||
@@ -45,43 +45,76 @@ void WorldSession::HandleAddFriendOpcode(WorldPacket& recvData)
|
||||
TC_LOG_DEBUG("network", "WorldSession::HandleAddFriendOpcode: %s asked to add friend: %s",
|
||||
GetPlayer()->GetName().c_str(), friendName.c_str());
|
||||
|
||||
FriendsResult friendResult = FRIEND_NOT_FOUND;
|
||||
ObjectGuid friendGuid = sCharacterCache->GetCharacterGuidByName(friendName);
|
||||
if (!friendGuid.IsEmpty())
|
||||
CharacterCacheEntry const* friendCharacterInfo = sCharacterCache->GetCharacterCacheByName(friendName);
|
||||
if (!friendCharacterInfo)
|
||||
{
|
||||
if (CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(friendGuid))
|
||||
{
|
||||
uint32 team = Player::TeamForRace(characterInfo->Race);
|
||||
uint32 friendAccountId = characterInfo->AccountId;
|
||||
|
||||
if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realm.Id.Realm)))
|
||||
{
|
||||
if (friendGuid)
|
||||
{
|
||||
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
|
||||
{
|
||||
Player* pFriend = ObjectAccessor::FindPlayer(friendGuid);
|
||||
if (pFriend && pFriend->IsVisibleGloballyFor(GetPlayer()))
|
||||
friendResult = FRIEND_ADDED_ONLINE;
|
||||
else
|
||||
friendResult = FRIEND_ADDED_OFFLINE;
|
||||
if (GetPlayer()->GetSocial()->AddToSocialList(friendGuid, SOCIAL_FLAG_FRIEND))
|
||||
GetPlayer()->GetSocial()->SetFriendNote(friendGuid, friendNote);
|
||||
else
|
||||
friendResult = FRIEND_LIST_FULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_NOT_FOUND, ObjectGuid::Empty);
|
||||
return;
|
||||
}
|
||||
|
||||
sSocialMgr->SendFriendStatus(GetPlayer(), friendResult, friendGuid);
|
||||
auto processFriendRequest = [this,
|
||||
playerGuid = _player->GetGUID(),
|
||||
friendGuid = friendCharacterInfo->Guid,
|
||||
team = Player::TeamForRace(friendCharacterInfo->Race),
|
||||
friendNote = std::move(friendNote)]()
|
||||
{
|
||||
if (playerGuid.GetCounter() != GetGUIDLow())
|
||||
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
|
||||
{
|
||||
Player* pFriend = ObjectAccessor::FindPlayer(friendGuid);
|
||||
if (pFriend && pFriend->IsVisibleGloballyFor(GetPlayer()))
|
||||
friendResult = FRIEND_ADDED_ONLINE;
|
||||
else
|
||||
friendResult = FRIEND_ADDED_OFFLINE;
|
||||
if (GetPlayer()->GetSocial()->AddToSocialList(friendGuid, 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;
|
||||
}
|
||||
|
||||
// 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(WorldPacket& recvData)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user