TrinityCore
Loading...
Searching...
No Matches
SocialMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "SocialMgr.h"
19#include "DatabaseEnv.h"
20#include "ObjectAccessor.h"
21#include "Player.h"
22#include "RBAC.h"
23#include "SocialPackets.h"
24#include "World.h"
25#include "WorldSession.h"
26
29PlayerSocial::PlayerSocial(PlayerSocial&&) noexcept = default;
30PlayerSocial& PlayerSocial::operator=(PlayerSocial const&) = default;
31PlayerSocial& PlayerSocial::operator=(PlayerSocial&&) noexcept = default;
32PlayerSocial::~PlayerSocial() = default;
33
34uint32 PlayerSocial::GetNumberOfSocialsWithFlag(SocialFlag flag)
35{
36 uint32 counter = 0;
37 for (PlayerSocialMap::const_iterator itr = _playerSocialMap.begin(); itr != _playerSocialMap.end(); ++itr)
38 if ((itr->second.Flags & flag) != 0)
39 ++counter;
40
41 return counter;
42}
43
44bool PlayerSocial::AddToSocialList(ObjectGuid const& friendGuid, ObjectGuid const& accountGuid, SocialFlag flag)
45{
46 // check client limits
48 return false;
49
50 PlayerSocialMap::iterator itr = _playerSocialMap.find(friendGuid);
51 if (itr != _playerSocialMap.end())
52 {
53 itr->second.Flags |= flag;
54 itr->second.WowAccountGuid = accountGuid;
55
57
58 stmt->setUInt8(0, itr->second.Flags);
60 stmt->setUInt64(2, friendGuid.GetCounter());
61
62 CharacterDatabase.Execute(stmt);
63 }
64 else
65 {
66 itr = _playerSocialMap.emplace(std::piecewise_construct, std::forward_as_tuple(friendGuid), std::forward_as_tuple()).first;
67
68 itr->second.Flags |= flag;
69 itr->second.WowAccountGuid = accountGuid;
70
72
74 stmt->setUInt64(1, friendGuid.GetCounter());
75 stmt->setUInt8(2, flag);
76
77 CharacterDatabase.Execute(stmt);
78 }
79
80 if (flag & SOCIAL_FLAG_IGNORED)
81 _ignoredAccounts.insert(accountGuid);
82
83 return true;
84}
85
87{
88 PlayerSocialMap::iterator itr = _playerSocialMap.find(friendGuid);
89 if (itr == _playerSocialMap.end())
90 return;
91
92 itr->second.Flags &= ~flag;
93
94 if (!itr->second.Flags)
95 {
97
98 stmt->setUInt64(0, GetPlayerGUID().GetCounter());
99 stmt->setUInt64(1, friendGuid.GetCounter());
100
101 CharacterDatabase.Execute(stmt);
102
103 ObjectGuid accountGuid = itr->second.WowAccountGuid;
104
105 _playerSocialMap.erase(itr);
106
107 if (flag & SOCIAL_FLAG_IGNORED)
108 {
109 auto otherIgnoreForAccount = std::find_if(_playerSocialMap.begin(), _playerSocialMap.end(), [&](PlayerSocialMap::value_type const& social)
110 {
111 return social.second.Flags & SOCIAL_FLAG_IGNORED && social.second.WowAccountGuid == accountGuid;
112 });
113
114 if (otherIgnoreForAccount == _playerSocialMap.end())
115 _ignoredAccounts.erase(accountGuid);
116 }
117 }
118 else
119 {
121
122 stmt->setUInt8(0, itr->second.Flags);
123 stmt->setUInt64(1, GetPlayerGUID().GetCounter());
124 stmt->setUInt64(2, friendGuid.GetCounter());
125
126 CharacterDatabase.Execute(stmt);
127 }
128}
129
130void PlayerSocial::SetFriendNote(ObjectGuid const& friendGuid, std::string const& note)
131{
132 PlayerSocialMap::iterator itr = _playerSocialMap.find(friendGuid);
133 if (itr == _playerSocialMap.end()) // not exist
134 return;
135
136 itr->second.Note = note;
137 utf8truncate(itr->second.Note, 48); // DB and client size limitation
138
140
141 stmt->setString(0, itr->second.Note);
142 stmt->setUInt64(1, GetPlayerGUID().GetCounter());
143 stmt->setUInt64(2, friendGuid.GetCounter());
144
145 CharacterDatabase.Execute(stmt);
146}
147
149{
150 ASSERT(player);
151
152 uint32 friendsCount = 0;
153 uint32 ignoredCount = 0;
154
156 contactList.Flags = flags; // 0x1 = Friendlist update. 0x2 = Ignorelist update. 0x4 = Mutelist update.
157
158 for (PlayerSocialMap::value_type& v : _playerSocialMap)
159 {
160 uint8 contactFlags = v.second.Flags;
161 if (!(contactFlags & flags))
162 continue;
163
164 // Check client limit for friends list
165 if (contactFlags & SOCIAL_FLAG_FRIEND)
166 if (++friendsCount > SOCIALMGR_FRIEND_LIMIT)
167 continue;
168
169 // Check client limit for ignore list
170 if (contactFlags & SOCIAL_FLAG_IGNORED)
171 if (++ignoredCount > SOCIALMGR_IGNORE_LIMIT)
172 continue;
173
174 SocialMgr::GetFriendInfo(player, v.first, v.second);
175
176 WorldPackets::Social::ContactInfo& contact = contactList.Contacts.emplace_back();
177 contact.Guid = v.first;
178 contact.WowAccountGuid = v.second.WowAccountGuid;
181 contact.TypeFlags = v.second.Flags;
182 contact.Notes = v.second.Note;
183 contact.Status = v.second.Status;
184 contact.AreaID = v.second.Area;
185 contact.Level = v.second.Level;
186 contact.ClassID = v.second.Class;
187 }
188
189 player->SendDirectMessage(contactList.Write());
190}
191
193{
194 PlayerSocialMap::const_iterator itr = _playerSocialMap.find(guid);
195 if (itr != _playerSocialMap.end())
196 return (itr->second.Flags & flags) != 0;
197
198 return false;
199}
200
201bool PlayerSocial::HasFriend(ObjectGuid const& friendGuid)
202{
203 return _HasContact(friendGuid, SOCIAL_FLAG_FRIEND);
204}
205
206bool PlayerSocial::HasIgnore(ObjectGuid const& ignoreGuid, ObjectGuid const& ignoreAccountGuid)
207{
208 return _HasContact(ignoreGuid, SOCIAL_FLAG_IGNORED) || _ignoredAccounts.find(ignoreAccountGuid) != _ignoredAccounts.end();
209}
210
211SocialMgr::SocialMgr() = default;
212SocialMgr::~SocialMgr() = default;
213
215{
216 static SocialMgr instance;
217 return &instance;
218}
219
220void SocialMgr::GetFriendInfo(Player* player, ObjectGuid const& friendGUID, FriendInfo& friendInfo)
221{
222 if (!player)
223 return;
224
225 friendInfo.Status = FRIEND_STATUS_OFFLINE;
226 friendInfo.Area = 0;
227 friendInfo.Level = 0;
228 friendInfo.Class = 0;
229
230 Player* target = ObjectAccessor::FindPlayer(friendGUID);
231 if (!target)
232 return;
233
234 PlayerSocial::PlayerSocialMap::iterator itr = player->GetSocial()->_playerSocialMap.find(friendGUID);
235 if (itr != player->GetSocial()->_playerSocialMap.end())
236 friendInfo.Note = itr->second.Note;
237
238 // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
239 // MODERATOR, GAME MASTER, ADMINISTRATOR can see all
240
243 return;
244
245 // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST
246 if (target->GetTeam() != player->GetTeam() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST))
247 return;
248
249 if (target->IsVisibleGloballyFor(player))
250 {
251 if (target->isDND())
252 friendInfo.Status = FRIEND_STATUS_DND;
253 else if (target->isAFK())
254 friendInfo.Status = FRIEND_STATUS_AFK;
255 else
256 {
257 friendInfo.Status = FRIEND_STATUS_ONLINE;
258
259 if (target->GetSession()->GetRecruiterId() == player->GetSession()->GetAccountId() || target->GetSession()->GetAccountId() == player->GetSession()->GetRecruiterId())
260 friendInfo.Status = FriendStatus(uint32(friendInfo.Status) | FRIEND_STATUS_RAF);
261 }
262
263 friendInfo.Area = target->GetZoneId();
264 friendInfo.Level = target->GetLevel();
265 friendInfo.Class = target->GetClass();
266 }
267}
268
269void SocialMgr::SendFriendStatus(Player* player, FriendsResult result, ObjectGuid const& friendGuid, bool broadcast /*= false*/)
270{
271 FriendInfo fi;
272 GetFriendInfo(player, friendGuid, fi);
273
276 friendStatus.Notes = fi.Note;
277 friendStatus.ClassID = fi.Class;
278 friendStatus.Status = fi.Status;
279 friendStatus.Guid = friendGuid;
280 friendStatus.WowAccountGuid = fi.WowAccountGuid;
281 friendStatus.Level = fi.Level;
282 friendStatus.AreaID = fi.Area;
283 friendStatus.FriendResult = result;
284
285 if (broadcast)
286 BroadcastToFriendListers(player, friendStatus.Write());
287 else
288 player->SendDirectMessage(friendStatus.Write());
289}
290
292{
293 ASSERT(player);
294
295 AccountTypes gmSecLevel = AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST));
296 for (SocialMap::const_iterator itr = _socialMap.begin(); itr != _socialMap.end(); ++itr)
297 {
298 PlayerSocial::PlayerSocialMap::const_iterator itr2 = itr->second._playerSocialMap.find(player->GetGUID());
299 if (itr2 != itr->second._playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND) != 0)
300 {
301 Player* target = ObjectAccessor::FindPlayer(itr->first);
302 if (!target)
303 continue;
304
305 WorldSession* session = target->GetSession();
306 if (!session->HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && player->GetSession()->GetSecurity() > gmSecLevel)
307 continue;
308
309 if (target->GetTeam() != player->GetTeam() && !session->HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST))
310 continue;
311
312 if (player->IsVisibleGloballyFor(target))
313 session->SendPacket(packet);
314 }
315 }
316}
317
319{
320 PlayerSocial* social = &_socialMap[guid];
321 social->SetPlayerGUID(guid);
322
323 if (result)
324 {
325 do
326 {
327 Field* fields = result->Fetch();
328
329 ObjectGuid friendGuid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
330 ObjectGuid friendAccountGuid = ObjectGuid::Create<HighGuid::WowAccount>(uint64(fields[1].GetUInt32()));
331
332 uint8 flag = fields[2].GetUInt8();
333 social->_playerSocialMap[friendGuid] = FriendInfo(friendAccountGuid, flag, fields[3].GetString());
334 if (flag & SOCIAL_FLAG_IGNORED)
335 social->_ignoredAccounts.insert(friendAccountGuid);
336 }
337 while (result->NextRow());
338 }
339
340 return social;
341}
@ CHAR_UPD_CHARACTER_SOCIAL_NOTE
@ CHAR_UPD_CHARACTER_SOCIAL_FLAGS
@ CHAR_DEL_CHARACTER_SOCIAL
@ CHAR_INS_CHARACTER_SOCIAL
AccountTypes
Definition Common.h:42
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint8_t uint8
Definition Define.h:156
uint64_t uint64
Definition Define.h:153
uint32_t uint32
Definition Define.h:154
uint16 flags
#define ASSERT
Definition Errors.h:80
Role Based Access Control related classes definition.
FriendsResult
Results of friend related commands.
Definition SocialMgr.h:68
FriendStatus
Definition SocialMgr.h:30
@ FRIEND_STATUS_RAF
Definition SocialMgr.h:35
@ FRIEND_STATUS_AFK
Definition SocialMgr.h:33
@ FRIEND_STATUS_DND
Definition SocialMgr.h:34
@ FRIEND_STATUS_OFFLINE
Definition SocialMgr.h:31
@ FRIEND_STATUS_ONLINE
Definition SocialMgr.h:32
SocialFlag
Definition SocialMgr.h:39
@ SOCIAL_FLAG_FRIEND
Definition SocialMgr.h:40
@ SOCIAL_FLAG_IGNORED
Definition SocialMgr.h:41
#define SOCIALMGR_IGNORE_LIMIT
Definition SocialMgr.h:101
#define SOCIALMGR_FRIEND_LIMIT
Definition SocialMgr.h:100
void utf8truncate(std::string &utf8str, size_t len)
Definition Util.cpp:315
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
Class used to access individual fields of database query result.
Definition Field.h:94
uint8 GetUInt8() const noexcept
Definition Field.cpp:29
LowType GetCounter() const
Definition ObjectGuid.h:336
void SetPlayerGUID(ObjectGuid const &guid)
Definition SocialMgr.h:128
ObjectGuid const & GetPlayerGUID() const
Definition SocialMgr.h:127
GuidUnorderedSet _ignoredAccounts
Definition SocialMgr.h:137
PlayerSocialMap _playerSocialMap
Definition SocialMgr.h:136
bool AddToSocialList(ObjectGuid const &guid, ObjectGuid const &accountGuid, SocialFlag flag)
Definition SocialMgr.cpp:44
uint32 GetNumberOfSocialsWithFlag(SocialFlag flag)
Definition SocialMgr.cpp:34
bool _HasContact(ObjectGuid const &guid, SocialFlag flags)
void SetFriendNote(ObjectGuid const &guid, std::string const &note)
bool HasIgnore(ObjectGuid const &ignoreGuid, ObjectGuid const &ignoreAccountGuid)
bool HasFriend(ObjectGuid const &friendGuid)
void RemoveFromSocialList(ObjectGuid const &guid, SocialFlag flag)
Definition SocialMgr.cpp:86
void SendSocialList(Player *player, uint32 flags)
PlayerSocial * GetSocial() const
Definition Player.h:1290
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6283
WorldSession * GetSession() const
Definition Player.h:2272
bool IsVisibleGloballyFor(Player const *player) const
Definition Player.cpp:24528
bool isDND() const
Definition Player.h:1284
bool isAFK() const
Definition Player.h:1283
Team GetTeam() const
Definition Player.h:2423
void setString(uint8 index, std::string &&value)
void setUInt64(uint8 index, uint64 value)
void setUInt8(uint8 index, uint8 value)
static SocialMgr * instance()
SocialMap _socialMap
Definition SocialMgr.h:170
static void GetFriendInfo(Player *player, ObjectGuid const &friendGUID, FriendInfo &friendInfo)
PlayerSocial * LoadFromDB(PreparedQueryResult result, ObjectGuid const &guid)
void SendFriendStatus(Player *player, FriendsResult result, ObjectGuid const &friendGuid, bool broadcast=false)
void BroadcastToFriendListers(Player *player, WorldPacket const *packet)
uint8 GetClass() const
Definition Unit.h:764
uint8 GetLevel() const
Definition Unit.h:757
uint32 GetZoneId() const
Definition Object.h:332
WorldPacket const * Write() override
std::vector< ContactInfo > Contacts
WorldPacket const * Write() override
Player session in the World.
AccountTypes GetSecurity() const
uint32 GetRecruiterId() const
bool HasPermission(uint32 permissionId)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
uint32 GetAccountId() const
#define sWorld
Definition World.h:916
uint32 GetVirtualRealmAddress()
Definition World.cpp:3526
@ CONFIG_GM_LEVEL_IN_WHO_LIST
Definition World.h:290
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
@ RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS
Definition RBAC.h:88
@ RBAC_PERM_TWO_SIDE_WHO_LIST
Definition RBAC.h:81
ObjectGuid WowAccountGuid
Definition SocialMgr.h:50
FriendStatus Status
Definition SocialMgr.h:51
uint8 Level
Definition SocialMgr.h:54
uint8 Class
Definition SocialMgr.h:55
std::string Note
Definition SocialMgr.h:56
uint32 Area
Definition SocialMgr.h:53