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 "World.h"
24#include "WorldPacket.h"
25#include "WorldSession.h"
26
28{ }
29
31{
32 uint32 counter = 0;
33 for (PlayerSocialMap::const_iterator itr = _playerSocialMap.begin(); itr != _playerSocialMap.end(); ++itr)
34 if ((itr->second.Flags & flag) != 0)
35 ++counter;
36
37 return counter;
38}
39
41{
42 // check client limits
44 return false;
45
46 PlayerSocialMap::iterator itr = _playerSocialMap.find(friendGuid);
47 if (itr != _playerSocialMap.end())
48 {
49 itr->second.Flags |= flag;
50
52
53 stmt->setUInt8(0, itr->second.Flags);
55 stmt->setUInt32(2, friendGuid.GetCounter());
56
57 CharacterDatabase.Execute(stmt);
58 }
59 else
60 {
61 _playerSocialMap[friendGuid].Flags |= flag;
62
64
66 stmt->setUInt32(1, friendGuid.GetCounter());
67 stmt->setUInt8(2, flag);
68
69 CharacterDatabase.Execute(stmt);
70 }
71
72 return true;
73}
74
76{
77 PlayerSocialMap::iterator itr = _playerSocialMap.find(friendGuid);
78 if (itr == _playerSocialMap.end())
79 return;
80
81 itr->second.Flags &= ~flag;
82
83 if (!itr->second.Flags)
84 {
86
87 stmt->setUInt32(0, GetPlayerGUID().GetCounter());
88 stmt->setUInt32(1, friendGuid.GetCounter());
89
90 CharacterDatabase.Execute(stmt);
91
92 _playerSocialMap.erase(itr);
93 }
94 else
95 {
97
98 stmt->setUInt8(0, itr->second.Flags);
99 stmt->setUInt32(1, GetPlayerGUID().GetCounter());
100 stmt->setUInt32(2, friendGuid.GetCounter());
101
102 CharacterDatabase.Execute(stmt);
103 }
104}
105
106void PlayerSocial::SetFriendNote(ObjectGuid const& friendGuid, std::string const& note)
107{
108 PlayerSocialMap::iterator itr = _playerSocialMap.find(friendGuid);
109 if (itr == _playerSocialMap.end()) // not exist
110 return;
111
112 itr->second.Note = note;
113 utf8truncate(itr->second.Note, 48); // DB and client size limitation
114
116
117 stmt->setString(0, itr->second.Note);
118 stmt->setUInt32(1, GetPlayerGUID().GetCounter());
119 stmt->setUInt32(2, friendGuid.GetCounter());
120
121 CharacterDatabase.Execute(stmt);
122}
123
125{
126 ASSERT(player);
127
128 uint32 friendsCount = 0;
129 uint32 ignoredCount = 0;
130 uint32 totalCount = 0;
131
132 WorldPacket data(SMSG_CONTACT_LIST, (4 + 4 + _playerSocialMap.size() * 25)); // just can guess size
133 data << uint32(flags); // 0x1 = Friendlist update. 0x2 = Ignorelist update. 0x4 = Mutelist update.
134 size_t countPos = data.wpos();
135 data << uint32(0); // contacts count placeholder
136
137 for (auto& v : _playerSocialMap)
138 {
139 uint8 contactFlags = v.second.Flags;
140 if (!(contactFlags & flags))
141 continue;
142
143 // Check client limit for friends list
144 if (contactFlags & SOCIAL_FLAG_FRIEND)
145 if (++friendsCount > SOCIALMGR_FRIEND_LIMIT)
146 continue;
147
148 // Check client limit for ignore list
149 if (contactFlags & SOCIAL_FLAG_IGNORED)
150 if (++ignoredCount > SOCIALMGR_IGNORE_LIMIT)
151 continue;
152
153 ++totalCount;
154 SocialMgr::GetFriendInfo(player, v.first, v.second);
155
156 data << v.first; // player guid
157 data << uint32(contactFlags); // player flag (0x1 = Friend, 0x2 = Ignored, 0x4 = Muted)
158 data << v.second.Note; // string note
159 if (contactFlags & SOCIAL_FLAG_FRIEND) // if IsFriend()
160 {
161 data << uint8(v.second.Status); // online/offline/etc?
162 if (v.second.Status) // if online
163 {
164 data << uint32(v.second.Area); // player area
165 data << uint32(v.second.Level); // player level
166 data << uint32(v.second.Class); // player class
167 }
168 }
169 }
170
171 data.put<uint32>(countPos, totalCount);
172
173 player->SendDirectMessage(&data);
174}
175
177{
178 PlayerSocialMap::const_iterator itr = _playerSocialMap.find(guid);
179 if (itr != _playerSocialMap.end())
180 return (itr->second.Flags & flags) != 0;
181
182 return false;
183}
184
185bool PlayerSocial::HasFriend(ObjectGuid const& friendGuid)
186{
187 return _HasContact(friendGuid, SOCIAL_FLAG_FRIEND);
188}
189
190bool PlayerSocial::HasIgnore(ObjectGuid const& ignoreGuid)
191{
192 return _HasContact(ignoreGuid, SOCIAL_FLAG_IGNORED);
193}
194
196{
197 static SocialMgr instance;
198 return &instance;
199}
200
201void SocialMgr::GetFriendInfo(Player* player, ObjectGuid const& friendGUID, FriendInfo& friendInfo)
202{
203 if (!player)
204 return;
205
206 friendInfo.Status = FRIEND_STATUS_OFFLINE;
207 friendInfo.Area = 0;
208 friendInfo.Level = 0;
209 friendInfo.Class = 0;
210
211 Player* target = ObjectAccessor::FindPlayer(friendGUID);
212 if (!target)
213 return;
214
215 PlayerSocial::PlayerSocialMap::iterator itr = player->GetSocial()->_playerSocialMap.find(friendGUID);
216 if (itr != player->GetSocial()->_playerSocialMap.end())
217 friendInfo.Note = itr->second.Note;
218
219 // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
220 // MODERATOR, GAME MASTER, ADMINISTRATOR can see all
221
224 return;
225
226 // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST
227 if (target->GetTeam() != player->GetTeam() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST))
228 return;
229
230 if (target->IsVisibleGloballyFor(player))
231 {
232 if (target->isDND())
233 friendInfo.Status = FRIEND_STATUS_DND;
234 else if (target->isAFK())
235 friendInfo.Status = FRIEND_STATUS_AFK;
236 else
237 {
238 friendInfo.Status = FRIEND_STATUS_ONLINE;
239
240 if (target->GetSession()->GetRecruiterId() == player->GetSession()->GetAccountId() || target->GetSession()->GetAccountId() == player->GetSession()->GetRecruiterId())
241 friendInfo.Status = FriendStatus(uint32(friendInfo.Status) | FRIEND_STATUS_RAF);
242 }
243
244 friendInfo.Area = target->GetZoneId();
245 friendInfo.Level = target->GetLevel();
246 friendInfo.Class = target->GetClass();
247 }
248}
249
250void SocialMgr::SendFriendStatus(Player* player, FriendsResult result, ObjectGuid const& friendGuid, bool broadcast /*= false*/)
251{
252 FriendInfo fi;
253 GetFriendInfo(player, friendGuid, fi);
254
256 data << uint8(result);
257 data << friendGuid;
258 switch (result)
259 {
262 data << fi.Note;
263 break;
264 default:
265 break;
266 }
267
268 switch (result)
269 {
271 case FRIEND_ONLINE:
272 data << uint8(fi.Status);
273 data << uint32(fi.Area);
274 data << uint32(fi.Level);
275 data << uint32(fi.Class);
276 break;
277 default:
278 break;
279 }
280
281 if (broadcast)
282 BroadcastToFriendListers(player, &data);
283 else
284 player->SendDirectMessage(&data);
285}
286
288{
289 ASSERT(player);
290
291 AccountTypes gmSecLevel = AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST));
292 for (SocialMap::const_iterator itr = _socialMap.begin(); itr != _socialMap.end(); ++itr)
293 {
294 PlayerSocial::PlayerSocialMap::const_iterator itr2 = itr->second._playerSocialMap.find(player->GetGUID());
295 if (itr2 != itr->second._playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND) != 0)
296 {
297 Player* target = ObjectAccessor::FindPlayer(itr->first);
298 if (!target)
299 continue;
300
301 WorldSession* session = target->GetSession();
302 if (!session->HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && player->GetSession()->GetSecurity() > gmSecLevel)
303 continue;
304
305 if (target->GetTeam() != player->GetTeam() && !session->HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST))
306 continue;
307
308 if (player->IsVisibleGloballyFor(target))
309 session->SendPacket(packet);
310 }
311 }
312}
313
315{
316 PlayerSocial* social = &_socialMap[guid];
317 social->SetPlayerGUID(guid);
318
319 if (result)
320 {
321 do
322 {
323 Field* fields = result->Fetch();
324
325 ObjectGuid friendGuid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt32());
326
327 uint8 flag = fields[1].GetUInt8();
328 social->_playerSocialMap[friendGuid] = FriendInfo(flag, fields[2].GetString());
329 }
330 while (result->NextRow());
331 }
332
333 return social;
334}
@ 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.
uint8_t uint8
Definition Define.h:135
uint32_t uint32
Definition Define.h:133
uint16 flags
#define ASSERT
Definition Errors.h:68
Role Based Access Control related classes definition.
FriendsResult
Results of friend related commands.
Definition SocialMgr.h:66
@ FRIEND_ONLINE
Definition SocialMgr.h:69
@ FRIEND_ADDED_OFFLINE
Definition SocialMgr.h:74
@ FRIEND_ADDED_ONLINE
Definition SocialMgr.h:73
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:99
#define SOCIALMGR_FRIEND_LIMIT
Definition SocialMgr.h:98
void utf8truncate(std::string &utf8str, size_t len)
Definition Util.cpp:362
size_t wpos() const
Definition ByteBuffer.h:321
void put(std::size_t pos, T value)
Definition ByteBuffer.h:137
Class used to access individual fields of database query result.
Definition Field.h:92
uint8 GetUInt8() const
Definition Field.cpp:29
LowType GetCounter() const
Definition ObjectGuid.h:156
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
void SetPlayerGUID(ObjectGuid const &guid)
Definition SocialMgr.h:120
ObjectGuid const & GetPlayerGUID() const
Definition SocialMgr.h:119
bool HasIgnore(ObjectGuid const &ignoreGuid)
PlayerSocialMap _playerSocialMap
Definition SocialMgr.h:128
uint32 GetNumberOfSocialsWithFlag(SocialFlag flag)
Definition SocialMgr.cpp:30
bool _HasContact(ObjectGuid const &guid, SocialFlag flags)
bool AddToSocialList(ObjectGuid const &guid, SocialFlag flag)
Definition SocialMgr.cpp:40
void SetFriendNote(ObjectGuid const &guid, std::string const &note)
bool HasFriend(ObjectGuid const &friendGuid)
void RemoveFromSocialList(ObjectGuid const &guid, SocialFlag flag)
Definition SocialMgr.cpp:75
void SendSocialList(Player *player, uint32 flags)
uint32 GetTeam() const
Definition Player.h:1832
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6161
WorldSession * GetSession() const
Definition Player.h:1719
bool IsVisibleGloballyFor(Player const *player) const
Definition Player.cpp:22113
bool isDND() const
Definition Player.h:976
PlayerSocial * GetSocial()
Definition Player.h:982
bool isAFK() const
Definition Player.h:975
void setUInt32(uint8 index, uint32 value)
void setUInt8(uint8 index, uint8 value)
void setString(uint8 index, std::string const &value)
static SocialMgr * instance()
SocialMap _socialMap
Definition SocialMgr.h:156
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:895
uint8 GetLevel() const
Definition Unit.h:889
uint32 GetZoneId() const
Definition Object.h:373
Player session in the World.
void SendPacket(WorldPacket const *packet)
Send a packet to the client.
AccountTypes GetSecurity() const
uint32 GetRecruiterId() const
bool HasPermission(uint32 permissionId)
uint32 GetAccountId() const
@ SMSG_CONTACT_LIST
Definition Opcodes.h:132
@ SMSG_FRIEND_STATUS
Definition Opcodes.h:133
#define sWorld
Definition World.h:900
@ CONFIG_GM_LEVEL_IN_WHO_LIST
Definition World.h:264
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:50
uint8 Level
Definition SocialMgr.h:53
uint8 Class
Definition SocialMgr.h:54
std::string Note
Definition SocialMgr.h:55
uint32 Area
Definition SocialMgr.h:52