OregonCore  revision 3611e8a-git
Your Favourite TBC server
SocialMgr.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore 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 "Database/DatabaseEnv.h"
20 #include "Opcodes.h"
21 #include "WorldPacket.h"
22 #include "WorldSession.h"
23 #include "Player.h"
24 #include "ObjectMgr.h"
25 #include "MapManager.h"
26 #include "World.h"
27 #include "Util.h"
28 
30 
32 {
33  m_playerGUID = 0;
34 }
35 
37 {
38  m_playerSocialMap.clear();
39 }
40 
42 {
43  uint32 counter = 0;
44  for (PlayerSocialMap::iterator itr = m_playerSocialMap.begin(); itr != m_playerSocialMap.end(); ++itr)
45  {
46  if (itr->second.Flags & flag)
47  counter++;
48  }
49  return counter;
50 }
51 
52 bool PlayerSocial::AddToSocialList(uint32 friend_guid, bool ignore)
53 {
54  // check client limits
55  if (ignore)
56  {
58  return false;
59  }
60  else
61  {
63  return false;
64  }
65 
67  if (ignore)
68  flag = SOCIAL_FLAG_IGNORED;
69 
70  PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
71  if (itr != m_playerSocialMap.end())
72  {
73  CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags | %u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid);
74  m_playerSocialMap[friend_guid].Flags |= flag;
75  }
76  else
77  {
78  CharacterDatabase.PExecute("INSERT INTO character_social (guid, friend, flags) VALUES ('%u', '%u', '%u')", GetPlayerGUID(), friend_guid, flag);
79  FriendInfo fi;
80  fi.Flags |= flag;
81  m_playerSocialMap[friend_guid] = fi;
82  }
83  return true;
84 }
85 
86 void PlayerSocial::RemoveFromSocialList(uint32 friend_guid, bool ignore)
87 {
88  PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
89  if (itr == m_playerSocialMap.end()) // not exist
90  return;
91 
93  if (ignore)
94  flag = SOCIAL_FLAG_IGNORED;
95 
96  itr->second.Flags &= ~flag;
97  if (itr->second.Flags == 0)
98  {
99  CharacterDatabase.PExecute("DELETE FROM character_social WHERE guid = '%u' AND friend = '%u'", GetPlayerGUID(), friend_guid);
100  m_playerSocialMap.erase(itr);
101  }
102  else
103  CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags & ~%u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid);
104 }
105 
106 void PlayerSocial::SetFriendNote(uint32 friend_guid, std::string note)
107 {
108  PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
109  if (itr == m_playerSocialMap.end()) // not exist
110  return;
111 
112  utf8truncate(note, 48); // DB and client size limitation
113 
115  CharacterDatabase.PExecute("UPDATE character_social SET note = '%s' WHERE guid = '%u' AND friend = '%u'", note.c_str(), GetPlayerGUID(), friend_guid);
116  m_playerSocialMap[friend_guid].Note = note;
117 }
118 
120 {
121  Player* plr = sObjectMgr.GetPlayer(GetPlayerGUID());
122  if (!plr)
123  return;
124 
125  uint32 size = m_playerSocialMap.size();
126 
127  WorldPacket data(SMSG_CONTACT_LIST, (4 + 4 + size * 25)); // just can guess size
128  data << uint32(7); // unk flag (0x1, 0x2, 0x4), 0x7 if it include ignore list
129  data << uint32(size); // friends count
130 
131  for (PlayerSocialMap::iterator itr = m_playerSocialMap.begin(); itr != m_playerSocialMap.end(); ++itr)
132  {
133  sSocialMgr.GetFriendInfo(plr, itr->first, itr->second);
134 
135  data << uint64(itr->first); // player guid
136  data << uint32(itr->second.Flags); // player flag (0x1-friend?, 0x2-ignored?, 0x4-muted?)
137  data << itr->second.Note; // string note
138  if (itr->second.Flags & SOCIAL_FLAG_FRIEND) // if IsFriend()
139  {
140  data << uint8(itr->second.Status); // online/offline/etc?
141  if (itr->second.Status) // if online
142  {
143  data << uint32(itr->second.Area); // player area
144  data << uint32(itr->second.Level); // player level
145  data << uint32(itr->second.Class); // player class
146  }
147  }
148  }
149 
150  plr->GetSession()->SendPacket(&data);
151  sLog.outDebug("WORLD: Sent SMSG_CONTACT_LIST");
152 }
153 
155 {
156  PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
157  if (itr != m_playerSocialMap.end())
158  return itr->second.Flags & SOCIAL_FLAG_FRIEND;
159  return false;
160 }
161 
163 {
164  PlayerSocialMap::iterator itr = m_playerSocialMap.find(ignore_guid);
165  if (itr != m_playerSocialMap.end())
166  return itr->second.Flags & SOCIAL_FLAG_IGNORED;
167  return false;
168 }
169 
171 {
172 }
173 
175 {
176 }
177 
178 void SocialMgr::GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo& friendInfo)
179 {
180  if (!player)
181  return;
182 
183  friendInfo.Status = FRIEND_STATUS_OFFLINE;
184  friendInfo.Area = 0;
185  friendInfo.Level = 0;
186  friendInfo.Class = 0;
187 
188  Player* pFriend = ObjectAccessor::FindPlayer(friendGUID);
189  if (!pFriend)
190  return;
191 
192  uint32 team = player->GetTeam();
193  uint32 security = player->GetSession()->GetSecurity();
194 
195  bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
196  bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST) || security > SEC_PLAYER;
197  bool hideInArena = sWorld.getConfig(CONFIG_ARENA_HIDE_FROM_SOCIAL);
198 
199  PlayerSocialMap::iterator itr = player->GetSocial()->m_playerSocialMap.find(friendGUID);
200  if (itr != player->GetSocial()->m_playerSocialMap.end())
201  friendInfo.Note = itr->second.Note;
202 
203  // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
204  // MODERATOR, GAME MASTER, ADMINISTRATOR can see all
205  if (pFriend && pFriend->GetName() &&
206  (security > SEC_PLAYER ||
207  ((pFriend->GetTeam() == team || allowTwoSideWhoList) &&
208  (pFriend->GetSession()->GetSecurity() == SEC_PLAYER || (gmInWhoList && pFriend->IsVisibleGloballyFor(player))))))
209  {
210  friendInfo.Status = FriendStatus(friendInfo.Status | FRIEND_STATUS_ONLINE);
211 
212  // AFK Status
213  pFriend->isAFK() ? friendInfo.Status = FriendStatus(friendInfo.Status | FRIEND_STATUS_AFK) : friendInfo.Status = FriendStatus(friendInfo.Status & ~FRIEND_STATUS_AFK);
214 
215  // DND Status
216  pFriend->isDND() ? friendInfo.Status = FriendStatus(friendInfo.Status | FRIEND_STATUS_DND) : friendInfo.Status = FriendStatus(friendInfo.Status & ~FRIEND_STATUS_DND);
217 
218  // RAF Status
219  sObjectMgr.GetRAFLinkStatus(player, pFriend) ? friendInfo.Status = FriendStatus(friendInfo.Status | FRIEND_STATUS_RAF) : friendInfo.Status = FriendStatus(friendInfo.Status & ~FRIEND_STATUS_RAF);
220 
221 
222  if (hideInArena && pFriend->InBattleground())
223  {
225  friendInfo.Area = 0; // unknown
226  else
230  }
231  else
232  friendInfo.Area = pFriend->GetZoneId();
233 
234  friendInfo.Level = pFriend->getLevel();
235  friendInfo.Class = pFriend->getClass();
236  }
237 }
238 
240 {
241  data->Initialize(SMSG_FRIEND_STATUS, 5);
242  *data << uint8(result);
243  *data << uint64(guid);
244 }
245 
246 void SocialMgr::SendFriendStatus(Player* player, FriendsResult result, uint32 friend_guid, bool broadcast)
247 {
248  FriendInfo fi;
249 
250  WorldPacket data;
251  MakeFriendStatusPacket(result, friend_guid, &data);
252  GetFriendInfo(player, friend_guid, fi);
253  switch (result)
254  {
256  case FRIEND_ADDED_ONLINE:
257  data << fi.Note;
258  default:
259  break;
260  }
261 
262  switch (result)
263  {
264  case FRIEND_ADDED_ONLINE:
265  case FRIEND_ONLINE:
266  data << uint8(fi.Status);
267  data << uint32(fi.Area);
268  data << uint32(fi.Level);
269  data << uint32(fi.Class);
270  default:
271  break;
272  }
273 
274  if (broadcast)
275  BroadcastToFriendListers(player, &data);
276  else
277  player->GetSession()->SendPacket(&data);
278 }
279 
281 {
282  if (!player)
283  return;
284 
285  uint32 team = player->GetTeam();
286  uint32 security = player->GetSession()->GetSecurity();
287  uint32 guid = player->GetGUIDLow();
288  bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST);
289  bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
290 
291  for (SocialMap::iterator itr = m_socialMap.begin(); itr != m_socialMap.end(); ++itr)
292  {
293  PlayerSocialMap::iterator itr2 = itr->second.m_playerSocialMap.find(guid);
294  if (itr2 != itr->second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND))
295  {
297 
298  // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
299  // MODERATOR, GAME MASTER, ADMINISTRATOR can see all
300  if (pFriend && pFriend->IsInWorld() &&
301  (pFriend->GetSession()->GetSecurity() > SEC_PLAYER ||
302  ((pFriend->GetTeam() == team || allowTwoSideWhoList) &&
303  (security == SEC_PLAYER || (gmInWhoList && player->IsVisibleGloballyFor(pFriend))))))
304  pFriend->GetSession()->SendPacket(packet);
305  }
306  }
307 }
308 
310 {
311  PlayerSocial* social = &m_socialMap[guid];
312  social->SetPlayerGUID(guid);
313 
314  if (!result)
315  return social;
316 
317  uint32 friend_guid = 0;
318  uint32 flags = 0;
319  std::string note = "";
320 
321  do
322  {
323  Field* fields = result->Fetch();
324 
325  friend_guid = fields[0].GetUInt32();
326  flags = fields[1].GetUInt32();
327  note = fields[2].GetCppString();
328 
329  social->m_playerSocialMap[friend_guid] = FriendInfo(flags, note);
330 
331  // client limit
333  break;
334  }
335  while (result->NextRow());
336  return social;
337 }
338 
#define SOCIALMGR_FRIEND_LIMIT
Definition: SocialMgr.h:112
uint32 Level
Definition: SocialMgr.h:52
bool isDND() const
Definition: Player.h:981
#define MAPID_INVALID
Definition: Object.h:565
uint32 GetZoneId(uint32 mapid, float x, float y, float z)
Definition: MapManager.h:56
void SendSocialList()
Definition: SocialMgr.cpp:119
SocialFlag
Definition: SocialMgr.h:40
std::string Note
Definition: SocialMgr.h:54
PlayerSocial * LoadFromDB(QueryResult_AutoPtr result, uint32 guid)
Definition: SocialMgr.cpp:309
Definition: Field.h:24
void utf8truncate(std::string &utf8str, size_t len)
Definition: Util.cpp:273
bool HasIgnore(uint32 ignore_guid)
Definition: SocialMgr.cpp:162
uint32 GetZoneId() const
Definition: Object.cpp:1176
bool AddToSocialList(uint32 friend_guid, bool ignore)
Definition: SocialMgr.cpp:52
#define sLog
Log class singleton.
Definition: Log.h:187
uint32 Class
Definition: SocialMgr.h:53
unsigned long escape_string(char *to, const char *from, unsigned long length)
Definition: Database.cpp:212
void Initialize(uint16 opcode, size_t newres=200)
Definition: WorldPacket.h:37
uint32 GetGUIDLow() const
Definition: Object.h:160
FriendStatus Status
Definition: SocialMgr.h:49
#define sObjectMgr
Definition: ObjectMgr.h:1285
void SendPacket(WorldPacket const *packet)
bool HasFriend(uint32 friend_guid)
Definition: SocialMgr.cpp:154
ACE_UINT8 uint8
Definition: Define.h:73
PlayerSocial * GetSocial()
Definition: Player.h:985
std::string GetCppString() const
Definition: Field.h:52
const bool & IsInWorld() const
Definition: Object.h:129
bool IsVisibleGloballyFor(Player *pl) const
Definition: Player.cpp:18711
FriendsResult
Definition: SocialMgr.h:81
float GetPositionY() const
Definition: Position.h:98
#define MAKE_NEW_GUID(l, e, h)
Definition: ObjectGuid.h:80
void BroadcastToFriendListers(Player *player, WorldPacket *packet)
Definition: SocialMgr.cpp:280
void SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, bool broadcast)
Definition: SocialMgr.cpp:246
static Player * FindPlayer(uint64, bool force=false)
float GetPositionZ() const
Definition: Position.h:99
WorldLocation const & GetBattlegroundEntryPoint() const
Definition: Player.h:2302
uint32 GetMapId() const
Definition: Object.h:585
bool PExecute(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:441
uint32 m_playerGUID
Definition: SocialMgr.h:141
#define sSocialMgr
Definition: SocialMgr.h:166
uint32 Flags
Definition: SocialMgr.h:50
PlayerSocialMap m_playerSocialMap
Definition: SocialMgr.h:140
const char * GetName() const
Definition: Object.h:692
ACE_UINT64 uint64
Definition: Define.h:70
bool InBattleground() const
Definition: Player.h:2207
void SetPlayerGUID(uint32 guid)
Definition: SocialMgr.h:134
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
uint32 GetPlayerGUID()
Definition: SocialMgr.h:130
uint32 Area
Definition: SocialMgr.h:51
uint8 getClass() const
Definition: Unit.h:1039
uint32 GetTeam() const
Definition: Player.h:2075
#define SOCIALMGR_IGNORE_LIMIT
Definition: SocialMgr.h:113
void GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo)
Definition: SocialMgr.cpp:178
bool isAFK() const
Definition: Player.h:980
WorldSession * GetSession() const
Definition: Player.h:1959
#define sWorld
Definition: World.h:860
void SetFriendNote(uint32 friend_guid, std::string note)
Definition: SocialMgr.cpp:106
DatabaseType CharacterDatabase
Accessor to the character database.
Definition: Main.cpp:54
void uint32 GetSecurity() const
Definition: WorldSession.h:96
void RemoveFromSocialList(uint32 friend_guid, bool ignore)
Definition: SocialMgr.cpp:86
FriendStatus
Definition: SocialMgr.h:30
ACE_UINT32 uint32
Definition: Define.h:71
float GetPositionX() const
Definition: Position.h:97
INSTANTIATE_SINGLETON_1(SocialMgr)
uint32 getLevel() const
Definition: Unit.h:1029
Definition: Player.h:922
void MakeFriendStatusPacket(FriendsResult result, uint32 friend_guid, WorldPacket *data)
Definition: SocialMgr.cpp:239
uint32 GetNumberOfSocialsWithFlag(SocialFlag flag)
Definition: SocialMgr.cpp:41