玩家登录数据库 HandlePlayerLogin 函数回调的时候 也会从数据库 表 character_social 返回查询到的社交关系
这时候需要 先给玩家发送玩家的好友关系
pCurrChar->GetSocial()->SendSocialList();
void PlayerSocial::SendSocialList()
{
Player* plr = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, m_playerLowGuid));
if (!plr)
return;
uint32 size = m_playerSocialMap.size();
WorldPacket data(SMSG_CONTACT_LIST, (4 + 4 + size * 25)); // just can guess size
data << uint32(7); // unk flag (0x1, 0x2, 0x4), 0x7 if it include ignore list
data << uint32(size); // friends count
for (auto& itr : m_playerSocialMap)
{
FriendInfo& friendInfo = itr.second;
sSocialMgr.GetFriendInfo(plr, itr.first, friendInfo);
data << ObjectGuid(HIGHGUID_PLAYER, itr.first); // player guid
data << uint32(friendInfo.Flags); // player flag (0x1-friend?, 0x2-ignored?, 0x4-muted?)
data << friendInfo.Note; // string note
if (friendInfo.Flags & SOCIAL_FLAG_FRIEND) // if IsFriend()
{
data << uint8(friendInfo.Status); // online/offline/etc?
if (friendInfo.Status) // if online
{
data << uint32(friendInfo.Area); // player area
data << uint32(friendInfo.Level); // player level
data << uint32(friendInfo.Class); // player class
}
}
}
plr->GetSession()->SendPacket(data);
DEBUG_LOG("WORLD: Sent SMSG_CONTACT_LIST");
}
然后需要通知 添加了该玩家好友的 在线玩家 玩家上线了 需要广播 所以最后一个参数为true
sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetObjectGuid(), true);
void SocialMgr::SendFriendStatus(Player* player, FriendsResult result, ObjectGuid friend_guid, bool broadcast)
{
uint32 friend_lowguid = friend_guid.GetCounter();
FriendInfo fi;
WorldPacket data;
MakeFriendStatusPacket(result, friend_lowguid, data);
GetFriendInfo(player, friend_lowguid, fi);
switch (result)
{
case FRIEND_ADDED_OFFLINE:
case FRIEND_ADDED_ONLINE:
data << fi.Note;
break;
default:
break;
}
switch (result)
{
case FRIEND_ADDED_ONLINE:
case FRIEND_ONLINE:
data << uint8(fi.Status);
data << uint32(fi.Area);
data << uint32(fi.Level);
data << uint32(fi.Class);
break;
default:
break;
}
if (broadcast)
BroadcastToFriendListers(player, data);
else
player->GetSession()->SendPacket(data);
}
最后就需要 遍历好友关系map数据 找到在线的玩家 并且添加了该玩家为好友的玩家 广播玩家上线的消息
void SocialMgr::BroadcastToFriendListers(Player* player, WorldPacket const& packet) const
{
if (!player)
return;
Team team = player->GetTeam();
AccountTypes security = player->GetSession()->GetSecurity();
uint32 guid = player->GetGUIDLow();
AccountTypes gmLevelInWhoList = AccountTypes(sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_WHO_LIST));
bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_WHO_LIST);
for (SocialMap::const_iterator itr = m_socialMap.begin(); itr != m_socialMap.end(); ++itr)
{
PlayerSocialMap::const_iterator itr2 = itr->second.m_playerSocialMap.find(guid);
if (itr2 != itr->second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND))
{
Player* pFriend = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first));
// PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
// MODERATOR, GAME MASTER, ADMINISTRATOR can see all
if (pFriend && pFriend->IsInWorld() &&
(pFriend->GetSession()->GetSecurity() > SEC_PLAYER ||
((pFriend->GetTeam() == team || allowTwoSideWhoList) && security <= gmLevelInWhoList)) &&
player->IsVisibleGloballyFor(pFriend))
{
pFriend->GetSession()->SendPacket(packet);
}
}
}
}