From 755e30f916d1cc0075a25edf1e21658636ea46a2 Mon Sep 17 00:00:00 2001 From: Viste Date: Fri, 4 Dec 2020 00:20:35 +0000 Subject: [PATCH] fix(Core/Social): cleanup + fix crash in friend system (#3832) fix crash when a friend or ignore get GUID 0 and also double friend list --- src/server/game/Entities/Player/Player.cpp | 4 +- src/server/game/Entities/Player/SocialMgr.cpp | 169 +++++++++-------- src/server/game/Entities/Player/SocialMgr.h | 97 +++++----- src/server/game/Handlers/MiscHandler.cpp | 172 ------------------ src/server/game/Handlers/Socialhandler.cpp | 151 +++++++++++++++ 5 files changed, 283 insertions(+), 310 deletions(-) create mode 100644 src/server/game/Handlers/Socialhandler.cpp diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4faa12840..f0eaa0be8 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -4940,7 +4940,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC { if (Player* pFriend = ObjectAccessor::FindPlayerInOrOutOfWorld(MAKE_NEW_GUID((*resultFriends)[0].GetUInt32(), 0, HIGHGUID_PLAYER))) { - pFriend->GetSocial()->RemoveFromSocialList(guid, false); + pFriend->GetSocial()->RemoveFromSocialList(guid, SOCIAL_FLAG_ALL); sSocialMgr->SendFriendStatus(pFriend, FRIEND_REMOVED, guid, false); } } while (resultFriends->NextRow()); @@ -23268,7 +23268,7 @@ void Player::SetGroup(Group* group, int8 subgroup) void Player::SendInitialPacketsBeforeAddToMap() { /// Pass 'this' as argument because we're not stored in ObjectAccessor yet - GetSocial()->SendSocialList(this); + GetSocial()->SendSocialList(this, SOCIAL_FLAG_ALL); // guild bank list wtf? diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp index 804ef0b69..bd03d687b 100644 --- a/src/server/game/Entities/Player/SocialMgr.cpp +++ b/src/server/game/Entities/Player/SocialMgr.cpp @@ -11,63 +11,45 @@ #include "WorldPacket.h" #include "Player.h" #include "ObjectMgr.h" -#include "World.h" #include "Util.h" #include "AccountMgr.h" -PlayerSocial::PlayerSocial() -{ - m_playerGUID = 0; -} - -PlayerSocial::~PlayerSocial() -{ - m_playerSocialMap.clear(); -} +PlayerSocial::PlayerSocial(): m_playerGUID() { } uint32 PlayerSocial::GetNumberOfSocialsWithFlag(SocialFlag flag) const { uint32 counter = 0; - for (PlayerSocialMap::const_iterator itr = m_playerSocialMap.begin(); itr != m_playerSocialMap.end(); ++itr) - if (itr->second.Flags & flag) + for (const auto& itr : m_playerSocialMap) + { + if ((itr.second.Flags & flag) != 0) ++counter; - + } return counter; } -bool PlayerSocial::AddToSocialList(uint32 friendGuid, bool ignore) +bool PlayerSocial::AddToSocialList(uint64 friendGuid, SocialFlag flag) { // check client limits - if (ignore) - { - if (GetNumberOfSocialsWithFlag(SOCIAL_FLAG_IGNORED) >= SOCIALMGR_IGNORE_LIMIT) - return false; - } - else - { - if (GetNumberOfSocialsWithFlag(SOCIAL_FLAG_FRIEND) >= SOCIALMGR_FRIEND_LIMIT) - return false; - } + if (GetNumberOfSocialsWithFlag(flag) >= (((flag & SOCIAL_FLAG_FRIEND) != 0) ? SOCIALMGR_FRIEND_LIMIT : SOCIALMGR_IGNORE_LIMIT)) + return false; - uint8 flag = SOCIAL_FLAG_FRIEND; - if (ignore) - flag = SOCIAL_FLAG_IGNORED; - - PlayerSocialMap::const_iterator itr = m_playerSocialMap.find(friendGuid); + auto itr = m_playerSocialMap.find(friendGuid); if (itr != m_playerSocialMap.end()) { + itr->second.Flags |= flag; + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_CHARACTER_SOCIAL_FLAGS); - stmt->setUInt8(0, flag); + stmt->setUInt8(0, itr->second.Flags); stmt->setUInt32(1, GetPlayerGUID()); stmt->setUInt32(2, friendGuid); CharacterDatabase.Execute(stmt); - - m_playerSocialMap[friendGuid].Flags |= flag; } else { + m_playerSocialMap[friendGuid].Flags |= flag; + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_SOCIAL); stmt->setUInt32(0, GetPlayerGUID()); @@ -75,25 +57,18 @@ bool PlayerSocial::AddToSocialList(uint32 friendGuid, bool ignore) stmt->setUInt8(2, flag); CharacterDatabase.Execute(stmt); - - FriendInfo fi; - fi.Flags |= flag; - m_playerSocialMap[friendGuid] = fi; } return true; } -void PlayerSocial::RemoveFromSocialList(uint32 friendGuid, bool ignore) +void PlayerSocial::RemoveFromSocialList(uint64 friendGuid, SocialFlag flag) { - PlayerSocialMap::iterator itr = m_playerSocialMap.find(friendGuid); + auto itr = m_playerSocialMap.find(friendGuid); if (itr == m_playerSocialMap.end()) // not exist return; - uint8 flag = SOCIAL_FLAG_FRIEND; - if (ignore) - flag = SOCIAL_FLAG_IGNORED; - itr->second.Flags &= ~flag; + if (itr->second.Flags == 0) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_SOCIAL); @@ -117,9 +92,9 @@ void PlayerSocial::RemoveFromSocialList(uint32 friendGuid, bool ignore) } } -void PlayerSocial::SetFriendNote(uint32 friendGuid, std::string note) +void PlayerSocial::SetFriendNote(uint64 friendGuid, std::string note) { - PlayerSocialMap::const_iterator itr = m_playerSocialMap.find(friendGuid); + auto itr = m_playerSocialMap.find(friendGuid); if (itr == m_playerSocialMap.end()) // not exist return; @@ -136,56 +111,78 @@ void PlayerSocial::SetFriendNote(uint32 friendGuid, std::string note) m_playerSocialMap[friendGuid].Note = note; } -void PlayerSocial::SendSocialList(Player* player) +void PlayerSocial::SendSocialList(Player* player, uint32 flags) { if (!player) return; - uint32 size = m_playerSocialMap.size(); + uint32 friendsCount = 0; + uint32 ignoredCount = 0; + uint32 totalCount = 0; - WorldPacket data(SMSG_CONTACT_LIST, (4 + 4 + size * 25)); // just can guess size - data << uint32(7); // 0x1 = Friendlist update. 0x2 = Ignorelist update. 0x4 = Mutelist update. - data << uint32(size); // friends count + WorldPacket data(SMSG_CONTACT_LIST, (4 + 4 + m_playerSocialMap.size() * 25)); // just can guess size + data << uint32(flags); // 0x1 = Friendlist update. 0x2 = Ignorelist update. 0x4 = Mutelist update. + size_t countPos = data.wpos(); + data << uint32(0); // contacts count placeholder - for (PlayerSocialMap::iterator itr = m_playerSocialMap.begin(); itr != m_playerSocialMap.end(); ++itr) + for (auto& itr : m_playerSocialMap) { - sSocialMgr->GetFriendInfo(player, itr->first, itr->second); + FriendInfo& friendInfo = itr.second; + uint8 contactFlags = friendInfo.Flags; + if (!(contactFlags & flags)) + continue; - data << uint64(itr->first); // player guid - data << uint32(itr->second.Flags); // player flag (0x1 = Friend, 0x2 = Ignored, 0x4 = Muted) - data << itr->second.Note; // string note - if (itr->second.Flags & SOCIAL_FLAG_FRIEND) // if IsFriend() + // Check client limit for friends list + if (contactFlags & SOCIAL_FLAG_FRIEND) + if (++friendsCount > SOCIALMGR_FRIEND_LIMIT) + continue; + + // Check client limit for ignore list + if (contactFlags & SOCIAL_FLAG_IGNORED) + if (++ignoredCount > SOCIALMGR_IGNORE_LIMIT) + continue; + + ++totalCount; + + sSocialMgr->GetFriendInfo(player, itr.first, friendInfo); + + data << uint64(itr.first); // player guid + data << uint32(contactFlags); // player flag (0x1 = Friend, 0x2 = Ignored, 0x4 = Muted) + data << friendInfo.Note; // string note + if (contactFlags & SOCIAL_FLAG_FRIEND) // if IsFriend() { - data << uint8(itr->second.Status); // online/offline/etc? - if (itr->second.Status) // if online + data << uint8(friendInfo.Status); // online/offline/etc? + if (friendInfo.Status) // if online { - data << uint32(itr->second.Area); // player area - data << uint32(itr->second.Level); // player level - data << uint32(itr->second.Class); // player class + data << uint32(friendInfo.Area); // player area + data << uint32(friendInfo.Level); // player level + data << uint32(friendInfo.Class); // player class } } } + data.put(countPos, totalCount); player->GetSession()->SendPacket(&data); -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_CONTACT_LIST"); -#endif } -bool PlayerSocial::HasFriend(uint32 friend_guid) const +bool PlayerSocial::_checkContact(uint64 guid, SocialFlag flags) const { - PlayerSocialMap::const_iterator itr = m_playerSocialMap.find(friend_guid); + const auto& itr = m_playerSocialMap.find(guid); if (itr != m_playerSocialMap.end()) - return itr->second.Flags & SOCIAL_FLAG_FRIEND; + return (itr->second.Flags & flags) != 0; + return false; } -bool PlayerSocial::HasIgnore(uint32 ignore_guid) const +bool PlayerSocial::HasFriend(uint64 friend_guid) const { - PlayerSocialMap::const_iterator itr = m_playerSocialMap.find(ignore_guid); - if (itr != m_playerSocialMap.end()) - return itr->second.Flags & SOCIAL_FLAG_IGNORED; - return false; + return _checkContact(friend_guid, SOCIAL_FLAG_FRIEND); +} + +bool PlayerSocial::HasIgnore(uint64 ignore_guid) const +{ + return _checkContact(ignore_guid, SOCIAL_FLAG_IGNORED); } SocialMgr::SocialMgr() @@ -202,7 +199,7 @@ SocialMgr* SocialMgr::instance() return &instance; } -void SocialMgr::GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo& friendInfo) +void SocialMgr::GetFriendInfo(Player* player, uint64 friendGUID, FriendInfo& friendInfo) { if (!player) return; @@ -221,7 +218,7 @@ void SocialMgr::GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo& fri bool allowTwoSideWhoList = sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); AccountTypes gmLevelInWhoList = AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST)); - PlayerSocialMap::iterator itr = player->GetSocial()->m_playerSocialMap.find(friendGUID); + auto const& itr = player->GetSocial()->m_playerSocialMap.find(friendGUID); if (itr != player->GetSocial()->m_playerSocialMap.end()) friendInfo.Note = itr->second.Note; @@ -240,20 +237,21 @@ void SocialMgr::GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo& fri } } -void SocialMgr::MakeFriendStatusPacket(FriendsResult result, uint32 guid, WorldPacket* data) +void SocialMgr::MakeFriendStatusPacket(FriendsResult result, uint64 guid, WorldPacket* data) { data->Initialize(SMSG_FRIEND_STATUS, 9); *data << uint8(result); *data << uint64(guid); } -void SocialMgr::SendFriendStatus(Player* player, FriendsResult result, uint32 friendGuid, bool broadcast) +void SocialMgr::SendFriendStatus(Player* player, FriendsResult result, uint64 friendGuid, bool broadcast) { FriendInfo fi; - - WorldPacket data; - MakeFriendStatusPacket(result, friendGuid, &data); GetFriendInfo(player, friendGuid, fi); + + WorldPacket data(SMSG_FRIEND_STATUS, 9); + data << uint8(result); + data << friendGuid; switch (result) { case FRIEND_ADDED_OFFLINE: @@ -294,12 +292,12 @@ void SocialMgr::BroadcastToFriendListers(Player* player, WorldPacket* packet) bool allowTwoSideWhoList = sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); AccountTypes gmLevelInWhoList = AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST)); - for (SocialMap::const_iterator itr = m_socialMap.begin(); itr != m_socialMap.end(); ++itr) + for (auto const& itr : m_socialMap) { - PlayerSocialMap::const_iterator itr2 = itr->second.m_playerSocialMap.find(guid); - if (itr2 != itr->second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND)) + auto const& itr2 = itr.second.m_playerSocialMap.find(guid); + if (itr2 != itr.second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND)) { - Player* pFriend = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)); + Player* pFriend = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr.first, 0, HIGHGUID_PLAYER)); // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters // MODERATOR, GAME MASTER, ADMINISTRATOR can see all @@ -309,7 +307,7 @@ void SocialMgr::BroadcastToFriendListers(Player* player, WorldPacket* packet) } } -PlayerSocial* SocialMgr::LoadFromDB(PreparedQueryResult result, uint32 guid) +PlayerSocial* SocialMgr::LoadFromDB(PreparedQueryResult result, uint64 guid) { PlayerSocial* social = &m_socialMap[guid]; social->SetPlayerGUID(guid); @@ -317,7 +315,6 @@ PlayerSocial* SocialMgr::LoadFromDB(PreparedQueryResult result, uint32 guid) if (!result) return social; - uint32 friendGuid = 0; uint8 flags = 0; std::string note = ""; @@ -325,15 +322,11 @@ PlayerSocial* SocialMgr::LoadFromDB(PreparedQueryResult result, uint32 guid) { Field* fields = result->Fetch(); - friendGuid = fields[0].GetUInt32(); + auto friendGuid = fields[0].GetUInt32(); flags = fields[1].GetUInt8(); note = fields[2].GetString(); social->m_playerSocialMap[friendGuid] = FriendInfo(flags, note); - - // client's friends list and ignore list limit - if (social->m_playerSocialMap.size() >= (SOCIALMGR_FRIEND_LIMIT + SOCIALMGR_IGNORE_LIMIT)) - break; } while (result->NextRow()); return social; diff --git a/src/server/game/Entities/Player/SocialMgr.h b/src/server/game/Entities/Player/SocialMgr.h index f9b358698..82d9765e7 100644 --- a/src/server/game/Entities/Player/SocialMgr.h +++ b/src/server/game/Entities/Player/SocialMgr.h @@ -9,9 +9,8 @@ #include "Common.h" #include "DatabaseEnv.h" +#include -class SocialMgr; -class PlayerSocial; class Player; class WorldPacket; @@ -29,7 +28,9 @@ enum SocialFlag SOCIAL_FLAG_FRIEND = 0x01, SOCIAL_FLAG_IGNORED = 0x02, SOCIAL_FLAG_MUTED = 0x04, // guessed - SOCIAL_FLAG_UNK = 0x08 // Unknown - does not appear to be RaF + SOCIAL_FLAG_UNK = 0x08, // Unknown - does not appear to be RaF + + SOCIAL_FLAG_ALL = SOCIAL_FLAG_FRIEND | SOCIAL_FLAG_IGNORED | SOCIAL_FLAG_MUTED }; struct FriendInfo @@ -48,11 +49,8 @@ struct FriendInfo { } }; -typedef std::map PlayerSocialMap; -typedef std::map SocialMap; - /// Results of friend related commands -enum FriendsResult +enum FriendsResult : uint8 { FRIEND_DB_ERROR = 0x00, FRIEND_LIST_FULL = 0x01, @@ -79,57 +77,60 @@ enum FriendsResult FRIEND_MUTE_ADDED = 0x16, FRIEND_MUTE_REMOVED = 0x17, FRIEND_MUTE_AMBIGUOUS = 0x18, // That name is ambiguous, type more of the player's server name - FRIEND_UNK7 = 0x19, // no message at client - FRIEND_UNKNOWN = 0x1A // Unknown friend response from server + FRIEND_UNK1 = 0x19, // no message at client + FRIEND_UNK2 = 0x1A, + FRIEND_UNK3 = 0x1B, + FRIEND_UNKNOWN = 0x1C // Unknown friend response from server }; -#define SOCIALMGR_FRIEND_LIMIT 50 -#define SOCIALMGR_IGNORE_LIMIT 50 +#define SOCIALMGR_FRIEND_LIMIT 50u +#define SOCIALMGR_IGNORE_LIMIT 50u class PlayerSocial { friend class SocialMgr; -public: - PlayerSocial(); - ~PlayerSocial(); - // adding/removing - bool AddToSocialList(uint32 friend_guid, bool ignore); - void RemoveFromSocialList(uint32 friend_guid, bool ignore); - void SetFriendNote(uint32 friendGuid, std::string note); - // Packet send's - void SendSocialList(Player* player); - // Misc - bool HasFriend(uint32 friend_guid) const; - bool HasIgnore(uint32 ignore_guid) const; - uint32 GetPlayerGUID() const { return m_playerGUID; } - void SetPlayerGUID(uint32 guid) { m_playerGUID = guid; } - uint32 GetNumberOfSocialsWithFlag(SocialFlag flag) const; -private: - PlayerSocialMap m_playerSocialMap; - uint32 m_playerGUID; + + public: + PlayerSocial(); + // adding/removing + bool AddToSocialList(uint64 friend_guid, SocialFlag flag); + void RemoveFromSocialList(uint64 friend_guid, SocialFlag flag); + void SetFriendNote(uint64 friendGuid, std::string note); + // Packet send's + void SendSocialList(Player* player, uint32 flags); + // Misc + bool HasFriend(uint64 friend_guid) const; + bool HasIgnore(uint64 ignore_guid) const; + uint64 GetPlayerGUID() const { return m_playerGUID; } + void SetPlayerGUID(uint64 guid) { m_playerGUID = guid; } + uint32 GetNumberOfSocialsWithFlag(SocialFlag flag) const; + private: + bool _checkContact(uint64 guid, SocialFlag flags) const; + typedef std::map PlayerSocialMap; + PlayerSocialMap m_playerSocialMap; + uint64 m_playerGUID; }; class SocialMgr { -private: - SocialMgr(); - ~SocialMgr(); - -public: - static SocialMgr* instance(); - - // Misc - void RemovePlayerSocial(uint32 guid) { m_socialMap.erase(guid); } - - void GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo& friendInfo); - // Packet management - void MakeFriendStatusPacket(FriendsResult result, uint32 friend_guid, WorldPacket* data); - void SendFriendStatus(Player* player, FriendsResult result, uint32 friend_guid, bool broadcast); - void BroadcastToFriendListers(Player* player, WorldPacket* packet); - // Loading - PlayerSocial* LoadFromDB(PreparedQueryResult result, uint32 guid); -private: - SocialMap m_socialMap; + private: + SocialMgr(); + ~SocialMgr(); + + public: + static SocialMgr* instance(); + // Misc + void RemovePlayerSocial(uint64 guid) { m_socialMap.erase(guid); } + static void GetFriendInfo(Player* player, uint64 friendGUID, FriendInfo& friendInfo); + // Packet management + void MakeFriendStatusPacket(FriendsResult result, uint64 friend_guid, WorldPacket* data); + void SendFriendStatus(Player* player, FriendsResult result, uint64 friend_guid, bool broadcast); + void BroadcastToFriendListers(Player* player, WorldPacket* packet); + // Loading + PlayerSocial* LoadFromDB(PreparedQueryResult result, uint64 guid); + private: + typedef std::map SocialMap; + SocialMap m_socialMap; }; #define sSocialMgr SocialMgr::instance() diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index c90c6e866..472ae3a50 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -566,148 +566,6 @@ void WorldSession::HandleStandStateChangeOpcode(WorldPacket& recv_data) _player->SetStandState(animstate); } -void WorldSession::HandleContactListOpcode(WorldPacket& recv_data) -{ - uint32 unk; - recv_data >> unk; -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_CONTACT_LIST - Unk: %d", unk); -#endif - _player->GetSocial()->SendSocialList(_player); -} - -void WorldSession::HandleAddFriendOpcode(WorldPacket& recv_data) -{ -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ADD_FRIEND"); -#endif - - std::string friendName = GetAcoreString(LANG_FRIEND_IGNORE_UNKNOWN); - std::string friendNote; - - recv_data >> friendName; - - recv_data >> friendNote; - - if (!normalizePlayerName(friendName)) - return; - -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s asked to add friend : '%s'", GetPlayer()->GetName().c_str(), friendName.c_str()); -#endif - - // xinef: Get Data From global storage - uint32 guidLow = sWorld->GetGlobalPlayerGUID(friendName); - if (!guidLow) - return; - - GlobalPlayerData const* playerData = sWorld->GetGlobalPlayerData(guidLow); - if (!playerData) - return; - - uint64 friendGuid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER); - uint32 friendAccountId = playerData->accountId; - 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 (friendGuid) - { - if (friendGuid == GetPlayer()->GetGUID()) - friendResult = FRIEND_SELF; - else if (GetPlayer()->GetTeamId() != teamId && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && AccountMgr::IsPlayerAccount(GetSecurity())) - friendResult = FRIEND_ENEMY; - else if (GetPlayer()->GetSocial()->HasFriend(guidLow)) - friendResult = FRIEND_ALREADY; - else - { - Player* pFriend = ObjectAccessor::FindPlayerInOrOutOfWorld(friendGuid); - if (pFriend && pFriend->IsVisibleGloballyFor(GetPlayer()) && !AccountMgr::IsGMAccount(pFriend->GetSession()->GetSecurity())) - friendResult = FRIEND_ADDED_ONLINE; - else - friendResult = FRIEND_ADDED_OFFLINE; - if (!GetPlayer()->GetSocial()->AddToSocialList(guidLow, false)) - { - friendResult = FRIEND_LIST_FULL; -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s's friend list is full.", GetPlayer()->GetName().c_str()); -#endif - } - } - GetPlayer()->GetSocial()->SetFriendNote(guidLow, friendNote); - } - } - - sSocialMgr->SendFriendStatus(GetPlayer(), friendResult, guidLow, false); - -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent (SMSG_FRIEND_STATUS)"); -#endif -} - -void WorldSession::HandleDelFriendOpcode(WorldPacket& recv_data) -{ - uint64 FriendGUID; - -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_DEL_FRIEND"); -#endif - - recv_data >> FriendGUID; - - _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(FriendGUID), false); - - sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_REMOVED, GUID_LOPART(FriendGUID), false); - -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent motd (SMSG_FRIEND_STATUS)"); -#endif -} - -void WorldSession::HandleAddIgnoreOpcode(WorldPacket& recv_data) -{ -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ADD_IGNORE"); -#endif - - std::string ignoreName = GetAcoreString(LANG_FRIEND_IGNORE_UNKNOWN); - - recv_data >> ignoreName; - - if (!normalizePlayerName(ignoreName)) - return; - -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s asked to Ignore: '%s'", GetPlayer()->GetName().c_str(), ignoreName.c_str()); -#endif - uint32 lowGuid = sWorld->GetGlobalPlayerGUID(ignoreName); - if (!lowGuid) - return; - - uint64 IgnoreGuid = MAKE_NEW_GUID(lowGuid, 0, HIGHGUID_PLAYER); - FriendsResult ignoreResult = FRIEND_IGNORE_NOT_FOUND; - - if (IgnoreGuid == GetPlayer()->GetGUID()) //not add yourself - ignoreResult = FRIEND_IGNORE_SELF; - else if (GetPlayer()->GetSocial()->HasIgnore(lowGuid)) - ignoreResult = FRIEND_IGNORE_ALREADY; - else - { - ignoreResult = FRIEND_IGNORE_ADDED; - - // ignore list full - if (!GetPlayer()->GetSocial()->AddToSocialList(lowGuid, true)) - ignoreResult = FRIEND_IGNORE_FULL; - } - - sSocialMgr->SendFriendStatus(GetPlayer(), ignoreResult, lowGuid, false); - -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent (SMSG_FRIEND_STATUS)"); -#endif -} - void WorldSession::HandleLoadActionsSwitchSpec(PreparedQueryResult result) { if (!GetPlayer()) @@ -745,36 +603,6 @@ void WorldSession::HandleCharacterAuraFrozen(PreparedQueryResult result) } while (result->NextRow()); } -void WorldSession::HandleDelIgnoreOpcode(WorldPacket& recv_data) -{ - uint64 IgnoreGUID; - -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_DEL_IGNORE"); -#endif - - recv_data >> IgnoreGUID; - - _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(IgnoreGUID), true); - - sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_IGNORE_REMOVED, GUID_LOPART(IgnoreGUID), false); - -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent motd (SMSG_FRIEND_STATUS)"); -#endif -} - -void WorldSession::HandleSetContactNotesOpcode(WorldPacket& recv_data) -{ -#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SET_CONTACT_NOTES"); -#endif - uint64 guid; - std::string note; - recv_data >> guid >> note; - _player->GetSocial()->SetFriendNote(GUID_LOPART(guid), note); -} - void WorldSession::HandleBugOpcode(WorldPacket& recv_data) { uint32 suggestion, contentlen, typelen; diff --git a/src/server/game/Handlers/Socialhandler.cpp b/src/server/game/Handlers/Socialhandler.cpp new file mode 100644 index 000000000..9c81ec16f --- /dev/null +++ b/src/server/game/Handlers/Socialhandler.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-GPL2 + * Copyright (C) 2008-2016 TrinityCore + * Copyright (C) 2005-2009 MaNGOS + */ + + +#include "WorldSession.h" +#include "AccountMgr.h" +#include "Log.h" +#include "Language.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "SocialMgr.h" +#include "World.h" + +void WorldSession::HandleContactListOpcode(WorldPacket& recv_data) +{ + uint32 flags; + recv_data >> flags; + + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_CONTACT_LIST - Unk: %d", flags); + + _player->GetSocial()->SendSocialList(_player, flags); +} + +void WorldSession::HandleAddFriendOpcode(WorldPacket& recv_data) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ADD_FRIEND"); + + std::string friendName = GetAcoreString(LANG_FRIEND_IGNORE_UNKNOWN); + std::string friendNote; + + recv_data >> friendName; + recv_data >> friendNote; + + if (!normalizePlayerName(friendName)) + return; + + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s asked to add friend : '%s'", GetPlayer()->GetName().c_str(), friendName.c_str()); + + // xinef: Get Data From global storage + uint32 guidLow = sWorld->GetGlobalPlayerGUID(friendName); + if (!guidLow) + return; + + GlobalPlayerData const* playerData = sWorld->GetGlobalPlayerData(guidLow); + if (!playerData) + return; + + uint64 friendGuid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER); + uint32 friendAccountId = playerData->accountId; + 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 (friendGuid) + { + if (friendGuid == GetPlayer()->GetGUID()) + friendResult = FRIEND_SELF; + else if (GetPlayer()->GetTeamId() != teamId && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && AccountMgr::IsPlayerAccount(GetSecurity())) + friendResult = FRIEND_ENEMY; + else if (GetPlayer()->GetSocial()->HasFriend(guidLow)) + friendResult = FRIEND_ALREADY; + else + { + Player* pFriend = ObjectAccessor::FindPlayerInOrOutOfWorld(friendGuid); + if (pFriend && pFriend->IsVisibleGloballyFor(GetPlayer()) && !AccountMgr::IsGMAccount(pFriend->GetSession()->GetSecurity())) + 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; + } + GetPlayer()->GetSocial()->SetFriendNote(guidLow, friendNote); + } + } + + sSocialMgr->SendFriendStatus(GetPlayer(), friendResult, guidLow, false); + + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent (SMSG_FRIEND_STATUS)"); +} + +void WorldSession::HandleDelFriendOpcode(WorldPacket& recv_data) +{ + uint64 FriendGUID; + recv_data >> FriendGUID; + + _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(FriendGUID), SOCIAL_FLAG_FRIEND); + + sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_REMOVED, GUID_LOPART(FriendGUID), false); + + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent motd (SMSG_FRIEND_STATUS)"); +} + +void WorldSession::HandleAddIgnoreOpcode(WorldPacket& recv_data) +{ + std::string ignoreName = GetAcoreString(LANG_FRIEND_IGNORE_UNKNOWN); + + recv_data >> ignoreName; + + if (!normalizePlayerName(ignoreName)) + return; + + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s asked to Ignore: '%s'", GetPlayer()->GetName().c_str(), ignoreName.c_str()); + + uint32 lowGuid = sWorld->GetGlobalPlayerGUID(ignoreName); + if (!lowGuid) + return; + + uint64 IgnoreGuid = MAKE_NEW_GUID(lowGuid, 0, HIGHGUID_PLAYER); + FriendsResult ignoreResult = FRIEND_IGNORE_NOT_FOUND; + + if (IgnoreGuid == GetPlayer()->GetGUID()) //not add yourself + ignoreResult = FRIEND_IGNORE_SELF; + else if (GetPlayer()->GetSocial()->HasIgnore(lowGuid)) + ignoreResult = FRIEND_IGNORE_ALREADY; + else + { + ignoreResult = FRIEND_IGNORE_ADDED; + + // ignore list full + if (!GetPlayer()->GetSocial()->AddToSocialList(lowGuid, SOCIAL_FLAG_IGNORED)) + ignoreResult = FRIEND_IGNORE_FULL; + } + + sSocialMgr->SendFriendStatus(GetPlayer(), ignoreResult, lowGuid, false); + + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent (SMSG_FRIEND_STATUS)"); +} + +void WorldSession::HandleDelIgnoreOpcode(WorldPacket& recv_data) +{ + uint64 IgnoreGUID; + recv_data >> IgnoreGUID; + + _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(IgnoreGUID), SOCIAL_FLAG_IGNORED); + sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_IGNORE_REMOVED, GUID_LOPART(IgnoreGUID), false); +} + +void WorldSession::HandleSetContactNotesOpcode(WorldPacket& recv_data) +{ + uint64 guid; + std::string note; + recv_data >> guid >> note; + _player->GetSocial()->SetFriendNote(GUID_LOPART(guid), note); +}