root/trunk/src/game/SocialMgr.cpp @ 102

Revision 102, 10.1 kB (checked in by yumileroy, 17 years ago)

[svn] Fixed copyright notices to comply with GPL.

Original author: w12x
Date: 2008-10-23 03:29:52-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "SocialMgr.h"
22#include "Policies/SingletonImp.h"
23#include "Database/DatabaseEnv.h"
24#include "Opcodes.h"
25#include "WorldPacket.h"
26#include "WorldSession.h"
27#include "Player.h"
28#include "ObjectMgr.h"
29#include "World.h"
30#include "Util.h"
31
32INSTANTIATE_SINGLETON_1( SocialMgr );
33
34PlayerSocial::PlayerSocial()
35{
36    m_playerGUID = 0;
37}
38
39PlayerSocial::~PlayerSocial()
40{
41    m_playerSocialMap.clear();
42}
43
44bool PlayerSocial::AddToSocialList(uint32 friend_guid, bool ignore)
45{
46    // client limit
47    if(m_playerSocialMap.size() >= 50)
48        return false;
49
50    uint32 flag = SOCIAL_FLAG_FRIEND;
51    if(ignore)
52        flag = SOCIAL_FLAG_IGNORED;
53
54    PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
55    if(itr != m_playerSocialMap.end())
56    {
57        CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags | %u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid);
58        m_playerSocialMap[friend_guid].Flags |= flag;
59    }
60    else
61    {
62        CharacterDatabase.PExecute("INSERT INTO character_social (guid, friend, flags) VALUES ('%u', '%u', '%u')", GetPlayerGUID(), friend_guid, flag);
63        FriendInfo fi;
64        fi.Flags |= flag;
65        m_playerSocialMap[friend_guid] = fi;
66    }
67    return true;
68}
69
70void PlayerSocial::RemoveFromSocialList(uint32 friend_guid, bool ignore)
71{
72    PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
73    if(itr == m_playerSocialMap.end())                      // not exist
74        return;
75
76    uint32 flag = SOCIAL_FLAG_FRIEND;
77    if(ignore)
78        flag = SOCIAL_FLAG_IGNORED;
79
80    itr->second.Flags &= ~flag;
81    if(itr->second.Flags == 0)
82    {
83        CharacterDatabase.PExecute("DELETE FROM character_social WHERE guid = '%u' AND friend = '%u'", GetPlayerGUID(), friend_guid);
84        m_playerSocialMap.erase(itr);
85    }
86    else
87    {
88        CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags & ~%u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid);
89    }
90}
91
92void PlayerSocial::SetFriendNote(uint32 friend_guid, std::string note)
93{
94    PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
95    if(itr == m_playerSocialMap.end())                      // not exist
96        return;
97
98    utf8truncate(note,48);                                  // DB and client size limitation
99
100    CharacterDatabase.escape_string(note);
101    CharacterDatabase.PExecute("UPDATE character_social SET note = '%s' WHERE guid = '%u' AND friend = '%u'", note.c_str(), GetPlayerGUID(), friend_guid);
102    m_playerSocialMap[friend_guid].Note = note;
103}
104
105void PlayerSocial::SendSocialList()
106{
107    Player *plr = objmgr.GetPlayer(GetPlayerGUID());
108    if(!plr)
109        return;
110
111    uint32 size = m_playerSocialMap.size();
112
113    WorldPacket data(SMSG_CONTACT_LIST, (4+4+size*25));     // just can guess size
114    data << uint32(7);                                      // unk flag (0x1, 0x2, 0x4), 0x7 if it include ignore list
115    data << uint32(size);                                   // friends count
116
117    for(PlayerSocialMap::iterator itr = m_playerSocialMap.begin(); itr != m_playerSocialMap.end(); ++itr)
118    {
119        sSocialMgr.GetFriendInfo(plr, itr->first, itr->second);
120
121        data << uint64(itr->first);                         // player guid
122        data << uint32(itr->second.Flags);                  // player flag (0x1-friend?, 0x2-ignored?, 0x4-muted?)
123        data << itr->second.Note;                           // string note
124        if(itr->second.Flags & SOCIAL_FLAG_FRIEND)          // if IsFriend()
125        {
126            data << uint8(itr->second.Status);              // online/offline/etc?
127            if(itr->second.Status)                          // if online
128            {
129                data << uint32(itr->second.Area);           // player area
130                data << uint32(itr->second.Level);          // player level
131                data << uint32(itr->second.Class);          // player class
132            }
133        }
134    }
135
136    plr->GetSession()->SendPacket(&data);
137    sLog.outDebug("WORLD: Sent SMSG_CONTACT_LIST");
138}
139
140bool PlayerSocial::HasFriend(uint32 friend_guid)
141{
142    PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
143    if(itr != m_playerSocialMap.end())
144        return itr->second.Flags & SOCIAL_FLAG_FRIEND;
145    return false;
146}
147
148bool PlayerSocial::HasIgnore(uint32 ignore_guid)
149{
150    PlayerSocialMap::iterator itr = m_playerSocialMap.find(ignore_guid);
151    if(itr != m_playerSocialMap.end())
152        return itr->second.Flags & SOCIAL_FLAG_IGNORED;
153    return false;
154}
155
156SocialMgr::SocialMgr()
157{
158
159}
160
161SocialMgr::~SocialMgr()
162{
163
164}
165
166void SocialMgr::RemovePlayerSocial(uint32 guid)
167{
168    SocialMap::iterator itr = m_socialMap.find(guid);
169    if(itr != m_socialMap.end())
170        m_socialMap.erase(itr);
171}
172
173void SocialMgr::GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo)
174{
175    if(!player)
176        return;
177
178    Player *pFriend = ObjectAccessor::FindPlayer(friendGUID);
179
180    uint32 team = player->GetTeam();
181    uint32 security = player->GetSession()->GetSecurity();
182    bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
183    bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST) || security > SEC_PLAYER;
184
185    PlayerSocialMap::iterator itr = player->GetSocial()->m_playerSocialMap.find(friendGUID);
186    if(itr != player->GetSocial()->m_playerSocialMap.end())
187        friendInfo.Note = itr->second.Note;
188
189    // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
190    // MODERATOR, GAME MASTER, ADMINISTRATOR can see all
191    if( pFriend && pFriend->GetName() &&
192        ( security > SEC_PLAYER ||
193        ( pFriend->GetTeam() == team || allowTwoSideWhoList ) &&
194        ( pFriend->GetSession()->GetSecurity() == SEC_PLAYER || gmInWhoList && pFriend->IsVisibleGloballyFor(player) )))
195    {
196        friendInfo.Status = FRIEND_STATUS_ONLINE;
197        if(pFriend->isAFK())
198            friendInfo.Status = FRIEND_STATUS_AFK;
199        if(pFriend->isDND())
200            friendInfo.Status = FRIEND_STATUS_DND;
201        friendInfo.Area = pFriend->GetZoneId();
202        friendInfo.Level = pFriend->getLevel();
203        friendInfo.Class = pFriend->getClass();
204    }
205    else
206    {
207        friendInfo.Status = FRIEND_STATUS_OFFLINE;
208        friendInfo.Area = 0;
209        friendInfo.Level = 0;
210        friendInfo.Class = 0;
211    }
212}
213
214void SocialMgr::MakeFriendStatusPacket(FriendsResult result, uint32 guid, WorldPacket *data)
215{
216    data->Initialize(SMSG_FRIEND_STATUS, 5);
217    *data << uint8(result);
218    *data << uint64(guid);
219}
220
221void SocialMgr::SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, std::string name, bool broadcast)
222{
223    FriendInfo fi;
224
225    WorldPacket data;
226    MakeFriendStatusPacket(result, friend_guid, &data);
227    GetFriendInfo(player, friend_guid, fi);
228    switch(result)
229    {
230        case FRIEND_ADDED_OFFLINE:
231        case FRIEND_ADDED_ONLINE:
232            data << fi.Note;
233            break;
234    }
235
236    switch(result)
237    {
238        case FRIEND_ADDED_ONLINE:
239        case FRIEND_ONLINE:
240            data << uint8(fi.Status);
241            data << uint32(fi.Area);
242            data << uint32(fi.Level);
243            data << uint32(fi.Class);
244            break;
245    }
246
247    if(broadcast)
248        BroadcastToFriendListers(player, &data);
249    else
250        player->GetSession()->SendPacket(&data);
251}
252
253void SocialMgr::BroadcastToFriendListers(Player *player, WorldPacket *packet)
254{
255    if(!player)
256        return;
257
258    uint32 team     = player->GetTeam();
259    uint32 security = player->GetSession()->GetSecurity();
260    uint32 guid     = player->GetGUIDLow();
261    bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST);
262    bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
263
264    for(SocialMap::iterator itr = m_socialMap.begin(); itr != m_socialMap.end(); ++itr)
265    {
266        PlayerSocialMap::iterator itr2 = itr->second.m_playerSocialMap.find(guid);
267        if(itr2 != itr->second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND))
268        {
269            Player *pFriend = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
270
271            // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
272            // MODERATOR, GAME MASTER, ADMINISTRATOR can see all
273            if( pFriend && pFriend->IsInWorld() &&
274                ( pFriend->GetSession()->GetSecurity() > SEC_PLAYER ||
275                ( pFriend->GetTeam() == team || allowTwoSideWhoList ) &&
276                (security == SEC_PLAYER || gmInWhoList && player->IsVisibleGloballyFor(pFriend) )))
277            {
278                pFriend->GetSession()->SendPacket(packet);
279            }
280        }
281    }
282}
283
284PlayerSocial *SocialMgr::LoadFromDB(QueryResult *result, uint32 guid)
285{
286    PlayerSocial *social = &m_socialMap[guid];
287    social->SetPlayerGUID(guid);
288
289    if(!result)
290        return social;
291
292    uint32 friend_guid = 0;
293    uint32 flags = 0;
294    std::string note = "";
295
296    do
297    {
298        Field *fields  = result->Fetch();
299
300        friend_guid = fields[0].GetUInt32();
301        flags = fields[1].GetUInt32();
302        note = fields[2].GetCppString();
303
304        social->m_playerSocialMap[friend_guid] = FriendInfo(flags, note);
305
306        // client limit
307        if(social->m_playerSocialMap.size() >= 50)
308            break;
309    }
310    while( result->NextRow() );
311    delete result;
312    return social;
313}
Note: See TracBrowser for help on using the browser.