TrinityCore
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
28{
29 uint32 counter = 0;
30 for (PlayerSocialMap::const_iterator itr = _playerSocialMap.begin(); itr != _playerSocialMap.end(); ++itr)
31 if ((itr->second.Flags & flag) != 0)
32 ++counter;
33
34 return counter;
35}
36
37bool PlayerSocial::AddToSocialList(ObjectGuid const& friendGuid, ObjectGuid const& accountGuid, SocialFlag flag)
38{
39 // check client limits
41 return false;
42
43 PlayerSocialMap::iterator itr = _playerSocialMap.find(friendGuid);
44 if (itr != _playerSocialMap.end())
45 {
46 itr->second.Flags |= flag;
47 itr->second.WowAccountGuid = accountGuid;
48
50
51 stmt->setUInt8(0, itr->second.Flags);
52 stmt->setUInt64(1, GetPlayerGUID().GetCounter());
53 stmt->setUInt64(2, friendGuid.GetCounter());
54
55 CharacterDatabase.Execute(stmt);
56 }
57 else
58 {
59 itr = _playerSocialMap.emplace(std::piecewise_construct, std::forward_as_tuple(friendGuid), std::forward_as_tuple()).first;
60
61 itr->second.Flags |= flag;
62 itr->second.WowAccountGuid = accountGuid;
63
65
66 stmt->setUInt64(0, GetPlayerGUID().GetCounter());
67 stmt->setUInt64(1, friendGuid.GetCounter());
68 stmt->setUInt8(2, flag);
69
70 CharacterDatabase.Execute(stmt);
71 }
72
73 if (flag & SOCIAL_FLAG_IGNORED)
74 _ignoredAccounts.insert(accountGuid);
75
76 return true;
77}
78
80{
81 PlayerSocialMap::iterator itr = _playerSocialMap.find(friendGuid);
82 if (itr == _playerSocialMap.end())
83 return;
84
85 itr->second.Flags &= ~flag;
86
87 if (!itr->second.Flags)
88 {
90
91 stmt->setUInt64(0, GetPlayerGUID().GetCounter());
92 stmt->setUInt64(1, friendGuid.GetCounter());
93
94 CharacterDatabase.Execute(stmt);
95
96 ObjectGuid accountGuid = itr->second.WowAccountGuid;
97
98 _playerSocialMap.erase(itr);
99
100 if (flag & SOCIAL_FLAG_IGNORED)
101 {
102 auto otherIgnoreForAccount = std::find_if(_playerSocialMap.begin(), _playerSocialMap.end(), [&](PlayerSocialMap::value_type const& social)
103 {
104 return social.second.Flags & SOCIAL_FLAG_IGNORED && social.second.WowAccountGuid == accountGuid;
105 });
106
107 if (otherIgnoreForAccount == _playerSocialMap.end())
108 _ignoredAccounts.erase(accountGuid);
109 }
110 }
111 else
112 {
114
115 stmt->setUInt8(0, itr->second.Flags);
116 stmt->setUInt64(1, GetPlayerGUID().GetCounter());
117 stmt->setUInt64(2, friendGuid.GetCounter());
118
119 CharacterDatabase.Execute(stmt);
120 }
121}
122
123void PlayerSocial::SetFriendNote(ObjectGuid const& friendGuid, std::string const& note)
124{
125 PlayerSocialMap::iterator itr = _playerSocialMap.find(friendGuid);
126 if (itr == _playerSocialMap.end()) // not exist
127 return;
128
129 itr->second.Note = note;
130 utf8truncate(itr->second.Note, 48); // DB and client size limitation
131
133
134 stmt->setString(0, itr->second.Note);
135 stmt->setUInt64(1, GetPlayerGUID().GetCounter());
136 stmt->setUInt64(2, friendGuid.GetCounter());
137
138 CharacterDatabase.Execute(stmt);
139}
140
142{
143 ASSERT(player);
144
145 uint32 friendsCount = 0;
146 uint32 ignoredCount = 0;
147
149 contactList.Flags = flags; // 0x1 = Friendlist update. 0x2 = Ignorelist update. 0x4 = Mutelist update.
150
151 for (PlayerSocialMap::value_type& v : _playerSocialMap)
152 {
153 uint8 contactFlags = v.second.Flags;
154 if (!(contactFlags & flags))
155 continue;
156
157 // Check client limit for friends list
158 if (contactFlags & SOCIAL_FLAG_FRIEND)
159 if (++friendsCount > SOCIALMGR_FRIEND_LIMIT)
160 continue;
161
162 // Check client limit for ignore list
163 if (contactFlags & SOCIAL_FLAG_IGNORED)
164 if (++ignoredCount > SOCIALMGR_IGNORE_LIMIT)
165 continue;
166
167 SocialMgr::GetFriendInfo(player, v.first, v.second);
168
169 contactList.Contacts.emplace_back(v.first, v.second);
170 }
171
172 player->SendDirectMessage(contactList.Write());
173}
174
176{
177 PlayerSocialMap::const_iterator itr = _playerSocialMap.find(guid);
178 if (itr != _playerSocialMap.end())
179 return (itr->second.Flags & flags) != 0;
180
181 return false;
182}
183
184bool PlayerSocial::HasFriend(ObjectGuid const& friendGuid)
185{
186 return _HasContact(friendGuid, SOCIAL_FLAG_FRIEND);
187}
188
189bool PlayerSocial::HasIgnore(ObjectGuid const& ignoreGuid, ObjectGuid const& ignoreAccountGuid)
190{
191 return _HasContact(ignoreGuid, SOCIAL_FLAG_IGNORED) || _ignoredAccounts.find(ignoreAccountGuid) != _ignoredAccounts.end();
192}
193
195{
196 static SocialMgr instance;
197 return &instance;
198}
199
200void SocialMgr::GetFriendInfo(Player* player, ObjectGuid const& friendGUID, FriendInfo& friendInfo)
201{
202 if (!player)
203 return;
204
205 friendInfo.Status = FRIEND_STATUS_OFFLINE;
206 friendInfo.Area = 0;
207 friendInfo.Level = 0;
208 friendInfo.Class = 0;
209
210 Player* target = ObjectAccessor::FindPlayer(friendGUID);
211 if (!target)
212 return;
213
214 PlayerSocial::PlayerSocialMap::iterator itr = player->GetSocial()->_playerSocialMap.find(friendGUID);
215 if (itr != player->GetSocial()->_playerSocialMap.end())
216 friendInfo.Note = itr->second.Note;
217
218 // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
219 // MODERATOR, GAME MASTER, ADMINISTRATOR can see all
220
223 return;
224
225 // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST
226 if (target->GetTeam() != player->GetTeam() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST))
227 return;
228
229 if (target->IsVisibleGloballyFor(player))
230 {
231 if (target->isDND())
232 friendInfo.Status = FRIEND_STATUS_DND;
233 else if (target->isAFK())
234 friendInfo.Status = FRIEND_STATUS_AFK;
235 else
236 {
237 friendInfo.Status = FRIEND_STATUS_ONLINE;
238
239 if (target->GetSession()->GetRecruiterId() == player->GetSession()->GetAccountId() || target->GetSession()->GetAccountId() == player->GetSession()->GetRecruiterId())
240 friendInfo.Status = FriendStatus(uint32(friendInfo.Status) | FRIEND_STATUS_RAF);
241 }
242
243 friendInfo.Area = target->GetZoneId();
244 friendInfo.Level = target->GetLevel();
245 friendInfo.Class = target->GetClass();
246 }
247}
248
249void SocialMgr::SendFriendStatus(Player* player, FriendsResult result, ObjectGuid const& friendGuid, bool broadcast /*= false*/)
250{
251 FriendInfo fi;
252 GetFriendInfo(player, friendGuid, fi);
253
255 friendStatus.Initialize(friendGuid, result, fi);
256
257 if (broadcast)
258 BroadcastToFriendListers(player, friendStatus.Write());
259 else
260 player->SendDirectMessage(friendStatus.Write());
261}
262
264{
265 ASSERT(player);
266
267 AccountTypes gmSecLevel = AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST));
268 for (SocialMap::const_iterator itr = _socialMap.begin(); itr != _socialMap.end(); ++itr)
269 {
270 PlayerSocial::PlayerSocialMap::const_iterator itr2 = itr->second._playerSocialMap.find(player->GetGUID());
271 if (itr2 != itr->second._playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND) != 0)
272 {
273 Player* target = ObjectAccessor::FindPlayer(itr->first);
274 if (!target)
275 continue;
276
277 WorldSession* session = target->GetSession();
278 if (!session->HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && player->GetSession()->GetSecurity() > gmSecLevel)
279 continue;
280
281 if (target->GetTeam() != player->GetTeam() && !session->HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST))
282 continue;
283
284 if (player->IsVisibleGloballyFor(target))
285 session->SendPacket(packet);
286 }
287 }
288}
289
291{
292 PlayerSocial* social = &_socialMap[guid];
293 social->SetPlayerGUID(guid);
294
295 if (result)
296 {
297 do
298 {
299 Field* fields = result->Fetch();
300
301 ObjectGuid friendGuid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
302 ObjectGuid friendAccountGuid = ObjectGuid::Create<HighGuid::WowAccount>(uint64(fields[1].GetUInt32()));
303
304 uint8 flag = fields[2].GetUInt8();
305 social->_playerSocialMap[friendGuid] = FriendInfo(friendAccountGuid, flag, fields[3].GetString());
306 if (flag & SOCIAL_FLAG_IGNORED)
307 social->_ignoredAccounts.insert(friendAccountGuid);
308 }
309 while (result->NextRow());
310 }
311
312 return social;
313}
@ CHAR_UPD_CHARACTER_SOCIAL_NOTE
@ CHAR_UPD_CHARACTER_SOCIAL_FLAGS
@ CHAR_DEL_CHARACTER_SOCIAL
@ CHAR_INS_CHARACTER_SOCIAL
AccountTypes
Definition: Common.h:39
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:144
uint64_t uint64
Definition: Define.h:141
uint32_t uint32
Definition: Define.h:142
uint16 flags
Definition: DisableMgr.cpp:49
#define ASSERT
Definition: Errors.h:68
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:362
Class used to access individual fields of database query result.
Definition: Field.h:90
uint8 GetUInt8() const
Definition: Field.cpp:30
LowType GetCounter() const
Definition: ObjectGuid.h:293
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
void SetPlayerGUID(ObjectGuid const &guid)
Definition: SocialMgr.h:121
ObjectGuid const & GetPlayerGUID() const
Definition: SocialMgr.h:120
GuidUnorderedSet _ignoredAccounts
Definition: SocialMgr.h:130
PlayerSocialMap _playerSocialMap
Definition: SocialMgr.h:129
bool AddToSocialList(ObjectGuid const &guid, ObjectGuid const &accountGuid, SocialFlag flag)
Definition: SocialMgr.cpp:37
uint32 GetNumberOfSocialsWithFlag(SocialFlag flag)
Definition: SocialMgr.cpp:27
bool _HasContact(ObjectGuid const &guid, SocialFlag flags)
Definition: SocialMgr.cpp:175
void SetFriendNote(ObjectGuid const &guid, std::string const &note)
Definition: SocialMgr.cpp:123
bool HasIgnore(ObjectGuid const &ignoreGuid, ObjectGuid const &ignoreAccountGuid)
Definition: SocialMgr.cpp:189
bool HasFriend(ObjectGuid const &friendGuid)
Definition: SocialMgr.cpp:184
void RemoveFromSocialList(ObjectGuid const &guid, SocialFlag flag)
Definition: SocialMgr.cpp:79
void SendSocialList(Player *player, uint32 flags)
Definition: SocialMgr.cpp:141
PlayerSocial * GetSocial() const
Definition: Player.h:1163
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6324
WorldSession * GetSession() const
Definition: Player.h:2101
bool IsVisibleGloballyFor(Player const *player) const
Definition: Player.cpp:23778
bool isDND() const
Definition: Player.h:1157
bool isAFK() const
Definition: Player.h:1156
Team GetTeam() const
Definition: Player.h:2235
void setUInt8(const uint8 index, const uint8 value)
void setString(const uint8 index, const std::string &value)
void setUInt64(const uint8 index, const uint64 value)
static SocialMgr * instance()
Definition: SocialMgr.cpp:194
SocialMap _socialMap
Definition: SocialMgr.h:158
static void GetFriendInfo(Player *player, ObjectGuid const &friendGUID, FriendInfo &friendInfo)
Definition: SocialMgr.cpp:200
PlayerSocial * LoadFromDB(PreparedQueryResult result, ObjectGuid const &guid)
Definition: SocialMgr.cpp:290
void SendFriendStatus(Player *player, FriendsResult result, ObjectGuid const &friendGuid, bool broadcast=false)
Definition: SocialMgr.cpp:249
void BroadcastToFriendListers(Player *player, WorldPacket const *packet)
Definition: SocialMgr.cpp:263
uint8 GetClass() const
Definition: Unit.h:752
uint8 GetLevel() const
Definition: Unit.h:746
uint32 GetZoneId() const
Definition: Object.h:545
WorldPacket const * Write() override
std::vector< ContactInfo > Contacts
Definition: SocialPackets.h:66
WorldPacket const * Write() override
void Initialize(ObjectGuid const &guid, FriendsResult result, FriendInfo const &friendInfo)
Player session in the World.
Definition: WorldSession.h:963
AccountTypes GetSecurity() const
Definition: WorldSession.h:999
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:931
@ CONFIG_GM_LEVEL_IN_WHO_LIST
Definition: World.h:292
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
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