void Channel::List(Player* player) { uint64 p = player->GetGUID(); if (!IsOn(p)) { WorldPacket data; MakeNotMember(&data); SendToOne(&data, p); } else { WorldPacket data(SMSG_CHANNEL_LIST, 1+(GetName().size()+1)+1+4+players.size()*(8+1)); data << uint8(1); // channel type? data << GetName(); // channel name data << uint8(GetFlags()); // channel flags? size_t pos = data.wpos(); data << uint32(0); // size of list, placeholder uint32 gmLevelInWhoList = sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); uint32 count = 0; for (PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) { Player* member = ObjectAccessor::FindPlayer(i->first); // PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters // MODERATOR, GAME MASTER, ADMINISTRATOR can see all if (member && (!AccountMgr::IsPlayerAccount(player->GetSession()->GetSecurity()) || member->GetSession()->GetSecurity() <= AccountTypes(gmLevelInWhoList)) && member->IsVisibleGloballyFor(player)) { data << uint64(i->first); data << uint8(i->second.flags); // flags seems to be changed... ++count; } } data.put<uint32>(pos, count); SendToOne(&data, p); } }
void Channel::List(Player* player) { ObjectGuid p = player->GetObjectGuid(); if (!IsOn(p)) { WorldPacket data; MakeNotMember(&data); SendToOne(&data, p); } else { WorldPacket data(SMSG_CHANNEL_LIST, 1 + (GetName().size() + 1) + 1 + 4 + m_players.size()*(8 + 1)); data << uint8(1); // channel type? data << GetName(); // channel name data << uint8(GetFlags()); // channel flags? size_t pos = data.wpos(); data << uint32(0); // size of list, placeholder AccountTypes gmLevelInWhoList = (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_WHO_LIST); uint32 count = 0; for (PlayerList::const_iterator i = m_players.begin(); i != m_players.end(); ++i) { Player* plr = sObjectMgr.GetPlayer(i->first); // PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters // MODERATOR, GAME MASTER, ADMINISTRATOR can see all if (plr && (player->GetSession()->GetSecurity() > SEC_PLAYER || plr->GetSession()->GetSecurity() <= gmLevelInWhoList) && plr->IsVisibleGloballyFor(player)) { data << ObjectGuid(i->first); data << uint8(i->second.flags); // flags seems to be changed... ++count; } } data.put<uint32>(pos, count); SendToOne(&data, p); } }
void SocialMgr::GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo &friendInfo) { if (!player) return; friendInfo.Status = FRIEND_STATUS_OFFLINE; friendInfo.Area = 0; friendInfo.Level = 0; friendInfo.Class = 0; Player* target = ObjectAccessor::FindPlayer(friendGUID); if (!target) return; PlayerSocialMap::iterator itr = player->GetSocial()->m_playerSocialMap.find(friendGUID); if (itr != player->GetSocial()->m_playerSocialMap.end()) friendInfo.Note = itr->second.Note; // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters // MODERATOR, GAME MASTER, ADMINISTRATOR can see all if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && target->GetSession()->GetSecurity() > AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST))) return; // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST if (target->GetTeam() != player->GetTeam() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST)) return; if (target->IsVisibleGloballyFor(player)) { if (target->isDND()) friendInfo.Status = FRIEND_STATUS_DND; else if (target->isAFK()) friendInfo.Status = FRIEND_STATUS_AFK; else friendInfo.Status = FRIEND_STATUS_ONLINE; friendInfo.Area = target->GetZoneId(); friendInfo.Level = target->getLevel(); friendInfo.Class = target->getClass(); } }
void SocialMgr::GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo &friendInfo) { if (!player) return; friendInfo.Status = FRIEND_STATUS_OFFLINE; friendInfo.Area = 0; friendInfo.Level = 0; friendInfo.Class = 0; Player *pFriend = ObjectAccessor::FindPlayer(friendGUID); if (!pFriend) return; uint32 team = player->GetTeam(); AccountTypes security = player->GetSession()->GetSecurity(); bool allowTwoSideWhoList = sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); AccountTypes gmLevelInWhoList = AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST)); PlayerSocialMap::iterator itr = player->GetSocial()->m_playerSocialMap.find(friendGUID); if (itr != player->GetSocial()->m_playerSocialMap.end()) friendInfo.Note = itr->second.Note; // 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->GetName() && (security > SEC_PLAYER || ((pFriend->GetTeam() == team || allowTwoSideWhoList) && (pFriend->GetSession()->GetSecurity() <= gmLevelInWhoList))) && pFriend->IsVisibleGloballyFor(player)) { friendInfo.Status = FRIEND_STATUS_ONLINE; if (pFriend->isAFK()) friendInfo.Status = FRIEND_STATUS_AFK; if (pFriend->isDND()) friendInfo.Status = FRIEND_STATUS_DND; if (pFriend->IsReferAFriendLinked(player)) friendInfo.Status = FRIEND_STATUS_RAF; friendInfo.Area = pFriend->GetZoneId(); friendInfo.Level = pFriend->getLevel(); friendInfo.Class = pFriend->getClass(); } }
void Channel::List(Player const* player) { uint64 guid = player->GetGUID(); if (!IsOn(guid)) { WorldPacket data; MakeNotMember(&data); SendToOne(&data, guid); return; } TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "SMSG_CHANNEL_LIST %s Channel: %s", player->GetSession()->GetPlayerInfo().c_str(), GetName().c_str()); WorldPacket data(SMSG_CHANNEL_LIST, 1+(GetName().size()+1)+1+4+playersStore.size()*(8+1)); data << uint8(1); // channel type? data << GetName(); // channel name data << uint8(GetFlags()); // channel flags? size_t pos = data.wpos(); data << uint32(0); // size of list, placeholder uint32 count = 0; for (PlayerContainer::const_iterator i = playersStore.begin(); i != playersStore.end(); ++i) { Player* member = ObjectAccessor::FindPlayer(i->first); if (member && (member->GetSession()->GetSecurity() < SEC_ADMINISTRATOR || member->IsVisibleGloballyFor(player))) { data << uint64(i->first); data << uint8(i->second.flags); // flags seems to be changed... ++count; } } data.put<uint32>(pos, count); SendToOne(&data, guid); }
void SocialMgr::GetFriendInfo(Player* player, uint32 friend_lowguid, FriendInfo& friendInfo) const { if (!player) return; Player* pFriend = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, friend_lowguid)); Team team = player->GetTeam(); AccountTypes security = player->GetSession()->GetSecurity(); bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_WHO_LIST); AccountTypes gmLevelInWhoList = AccountTypes(sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_WHO_LIST)); PlayerSocialMap::iterator itr = player->GetSocial()->m_playerSocialMap.find(friend_lowguid); if (itr != player->GetSocial()->m_playerSocialMap.end()) { // 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->GetName() && (security > SEC_PLAYER || ((pFriend->GetTeam() == team || allowTwoSideWhoList) && (pFriend->GetSession()->GetSecurity() <= gmLevelInWhoList))) && pFriend->IsVisibleGloballyFor(player)) { friendInfo.Status = FRIEND_STATUS_ONLINE; if (pFriend->isAFK()) friendInfo.Status = FRIEND_STATUS_AFK; if (pFriend->isDND()) friendInfo.Status = FRIEND_STATUS_DND; friendInfo.Area = pFriend->GetZoneId(); friendInfo.Level = pFriend->getLevel(); friendInfo.Class = pFriend->getClass(); } else { friendInfo.Status = FRIEND_STATUS_OFFLINE; friendInfo.Area = 0; friendInfo.Level = 0; friendInfo.Class = 0; } } }
void Channel::List(Player const* player) { ObjectGuid const& guid = player->GetGUID(); if (!IsOn(guid)) { NotMemberAppend appender; ChannelNameBuilder<NotMemberAppend> builder(this, appender); SendToOne(builder, guid); return; } std::string channelName = GetName(player->GetSession()->GetSessionDbcLocale()); TC_LOG_DEBUG("chat.system", "SMSG_CHANNEL_LIST %s Channel: %s", player->GetSession()->GetPlayerInfo().c_str(), channelName.c_str()); WorldPackets::Channel::ChannelListResponse list; list._Display = true; /// always true? list._Channel = channelName; list._ChannelFlags = GetFlags(); uint32 gmLevelInWhoList = sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); list._Members.reserve(_playersStore.size()); for (PlayerContainer::value_type const& i : _playersStore) { Player* member = ObjectAccessor::FindConnectedPlayer(i.first); // PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters // MODERATOR, GAME MASTER, ADMINISTRATOR can see all if (member && (player->GetSession()->HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) || member->GetSession()->GetSecurity() <= AccountTypes(gmLevelInWhoList)) && member->IsVisibleGloballyFor(player)) { list._Members.emplace_back(i.first, GetVirtualRealmAddress(), i.second.GetFlags()); } } player->SendDirectMessage(list.Write()); }
bool ChatHandler::needReportToTarget(Player* chr) const { Player* pl = m_session->GetPlayer(); return pl != chr && pl->IsVisibleGloballyFor(chr); }
void WorldSession::HandleWhoOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received opcode CMSG_WHO"); // recv_data.hexlike(); uint32 level_min, level_max, racemask, classmask, zones_count, str_count; uint32 zoneids[10]; // 10 is client limit std::string player_name, guild_name; recv_data >> level_min; // maximal player level, default 0 recv_data >> level_max; // minimal player level, default 100 (MAX_LEVEL) recv_data >> player_name; // player name, case sensitive... recv_data >> guild_name; // guild name, case sensitive... recv_data >> racemask; // race mask recv_data >> classmask; // class mask recv_data >> zones_count; // zones count, client limit=10 (2.0.10) if (zones_count > 10) return; // can't be received from real client or broken packet for (uint32 i = 0; i < zones_count; ++i) { uint32 temp; recv_data >> temp; // zone id, 0 if zone is unknown... zoneids[i] = temp; DEBUG_LOG("Zone %u: %u", i, zoneids[i]); } recv_data >> str_count; // user entered strings count, client limit=4 (checked on 2.0.10) if (str_count > 4) return; // can't be received from real client or broken packet DEBUG_LOG("Minlvl %u, maxlvl %u, name %s, guild %s, racemask %u, classmask %u, zones %u, strings %u", level_min, level_max, player_name.c_str(), guild_name.c_str(), racemask, classmask, zones_count, str_count); std::wstring str[4]; // 4 is client limit for (uint32 i = 0; i < str_count; ++i) { std::string temp; recv_data >> temp; // user entered string, it used as universal search pattern(guild+player name)? if (!Utf8toWStr(temp, str[i])) continue; wstrToLower(str[i]); DEBUG_LOG("String %u: %s", i, temp.c_str()); } std::wstring wplayer_name; std::wstring wguild_name; if (!(Utf8toWStr(player_name, wplayer_name) && Utf8toWStr(guild_name, wguild_name))) return; wstrToLower(wplayer_name); wstrToLower(wguild_name); // client send in case not set max level value 100 but mangos support 255 max level, // update it to show GMs with characters after 100 level if (level_max >= MAX_LEVEL) level_max = STRONG_MAX_LEVEL; Team team = _player->GetTeam(); AccountTypes security = GetSecurity(); bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_WHO_LIST); AccountTypes gmLevelInWhoList = (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_WHO_LIST); uint32 matchcount = 0; uint32 displaycount = 0; WorldPacket data(SMSG_WHO, 50); // guess size data << uint32(matchcount); // placeholder, count of players matching criteria data << uint32(displaycount); // placeholder, count of players displayed // TODO: Guard Player map HashMapHolder<Player>::MapType& m = sObjectAccessor.GetPlayers(); for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) { Player* pl = itr->second; if (security == SEC_PLAYER) { // player can see member of other team only if CONFIG_BOOL_ALLOW_TWO_SIDE_WHO_LIST if (pl->GetTeam() != team && !allowTwoSideWhoList) continue; // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST if (pl->GetSession()->GetSecurity() > gmLevelInWhoList) continue; } // do not process players which are not in world if (!pl->IsInWorld()) continue; // check if target is globally visible for player if (!pl->IsVisibleGloballyFor(_player)) continue; // check if target's level is in level range uint32 lvl = pl->getLevel(); if (lvl < level_min || lvl > level_max) continue; // check if class matches classmask uint32 class_ = pl->getClass(); if (!(classmask & (1 << class_))) continue; // check if race matches racemask uint32 race = pl->getRace(); if (!(racemask & (1 << race))) continue; uint32 pzoneid = pl->GetZoneId(); uint8 gender = pl->getGender(); bool z_show = true; for (uint32 i = 0; i < zones_count; ++i) { if (zoneids[i] == pzoneid) { z_show = true; break; } z_show = false; } if (!z_show) continue; std::string pname = pl->GetName(); std::wstring wpname; if (!Utf8toWStr(pname, wpname)) continue; wstrToLower(wpname); if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos)) continue; std::string gname = sGuildMgr.GetGuildNameById(pl->GetGuildId()); std::wstring wgname; if (!Utf8toWStr(gname, wgname)) continue; wstrToLower(wgname); if (!(wguild_name.empty() || wgname.find(wguild_name) != std::wstring::npos)) continue; std::string aname; if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(pzoneid)) aname = areaEntry->area_name[GetSessionDbcLocale()]; bool s_show = true; for (uint32 i = 0; i < str_count; ++i) { if (!str[i].empty()) { if (wgname.find(str[i]) != std::wstring::npos || wpname.find(str[i]) != std::wstring::npos || Utf8FitTo(aname, str[i])) { s_show = true; break; } s_show = false; } } if (!s_show) continue; // 49 is maximum player count sent to client ++matchcount; if (matchcount > 49) continue; ++displaycount; data << pname; // player name data << gname; // guild name data << uint32(lvl); // player level data << uint32(class_); // player class data << uint32(race); // player race data << uint8(gender); // player gender data << uint32(pzoneid); // player zone id } data.put(0, displaycount); // insert right count, count displayed data.put(4, matchcount); // insert right count, count of matches SendPacket(&data); DEBUG_LOG("WORLD: Send SMSG_WHO Message"); }
void Channel::List(Player* player) { uint64 p = player->GetGUID(); if(!IsOn(p)) { WorldPacket data; MakeNotMember(&data); SendToOne(&data, p); } else { WorldPacket data(SMSG_CHANNEL_LIST, 1+(GetName().size()+1)+1+4+players.size()*(8+1)); data << uint8(1); // channel type? data << GetName(); // channel name data << uint8(GetFlags()); // channel flags? size_t pos = data.wpos(); data << uint32(0); // size of list, placeholder bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST); uint32 count = 0; for(PlayerList::iterator i = players.begin(); i != players.end(); ++i) { Player *plr = objmgr.GetPlayer(i->first); // PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters // MODERATOR, GAME MASTER, ADMINISTRATOR can see all if( plr && ( plr->GetSession()->GetSecurity() == SEC_PLAYER || gmInWhoList && plr->IsVisibleGloballyFor(player) ) ) { data << uint64(i->first); data << uint8(i->second.flags); // flags seems to be changed... ++count; } } data.put<uint32>(pos,count); SendToOne(&data, p); } }
void WorldSession::HandleWhoOpcode(WorldPackets::Who::WhoRequestPkt& whoRequest) { WorldPackets::Who::WhoRequest& request = whoRequest.Request; TC_LOG_DEBUG("network", "WorldSession::HandleWhoOpcode: MinLevel: %u, MaxLevel: %u, Name: %s (VirtualRealmName: %s), Guild: %s (GuildVirtualRealmName: %s), RaceFilter: %d, ClassFilter: %d, Areas: " SZFMTD ", Words: " SZFMTD ".", request.MinLevel, request.MaxLevel, request.Name.c_str(), request.VirtualRealmName.c_str(), request.Guild.c_str(), request.GuildVirtualRealmName.c_str(), request.RaceFilter, request.ClassFilter, whoRequest.Areas.size(), request.Words.size()); // zones count, client limit = 10 (2.0.10) // can't be received from real client or broken packet if (whoRequest.Areas.size() > 10) return; // user entered strings count, client limit=4 (checked on 2.0.10) // can't be received from real client or broken packet if (request.Words.size() > 4) return; /// @todo: handle following packet values /// VirtualRealmNames /// ShowEnemies /// ShowArenaPlayers /// ExactName /// ServerInfo std::vector<std::wstring> wWords; wWords.resize(request.Words.size()); for (size_t i = 0; i < request.Words.size(); ++i) { TC_LOG_DEBUG("network", "WorldSession::HandleWhoOpcode: Word: %s", request.Words[i].Word.c_str()); // user entered string, it used as universal search pattern(guild+player name)? if (!Utf8toWStr(request.Words[i].Word, wWords[i])) continue; wstrToLower(wWords[i]); } std::wstring wPlayerName; std::wstring wGuildName; if (!(Utf8toWStr(request.Name, wPlayerName) && Utf8toWStr(request.Guild, wGuildName))) return; wstrToLower(wPlayerName); wstrToLower(wGuildName); // client send in case not set max level value 100 but Trinity supports 255 max level, // update it to show GMs with characters after 100 level if (whoRequest.Request.MaxLevel >= MAX_LEVEL) whoRequest.Request.MaxLevel = STRONG_MAX_LEVEL; uint32 team = _player->GetTeam(); uint32 gmLevelInWhoList = sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); WorldPackets::Who::WhoResponsePkt response; boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock()); HashMapHolder<Player>::MapType const& m = ObjectAccessor::GetPlayers(); for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) { Player* target = itr->second; // player can see member of other team only if has RBAC_PERM_TWO_SIDE_WHO_LIST if (target->GetTeam() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST)) continue; // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if has RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS if (target->GetSession()->GetSecurity() > AccountTypes(gmLevelInWhoList) && !HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS)) continue; // do not process players which are not in world if (!target->IsInWorld()) continue; // check if target is globally visible for player if (!target->IsVisibleGloballyFor(_player)) continue; // check if target's level is in level range uint8 lvl = target->getLevel(); if (lvl < request.MinLevel || lvl > request.MaxLevel) continue; // check if class matches classmask if (request.ClassFilter >= 0 && !(request.ClassFilter & (1 << target->getClass()))) continue; // check if race matches racemask if (request.RaceFilter >= 0 && !(request.RaceFilter & (1 << target->getRace()))) continue; if (!whoRequest.Areas.empty()) { if (std::find(whoRequest.Areas.begin(), whoRequest.Areas.end(), target->GetZoneId()) == whoRequest.Areas.end()) continue; } std::wstring wTargetName; if (!Utf8toWStr(target->GetName(), wTargetName)) continue; wstrToLower(wTargetName); if (!wPlayerName.empty() && wTargetName.find(wPlayerName) == std::wstring::npos) continue; Guild* targetGuild = target->GetGuild(); std::wstring wTargetGuildName; if (!Utf8toWStr(targetGuild ? targetGuild->GetName() : "", wTargetGuildName)) continue; wstrToLower(wTargetGuildName); if (!wGuildName.empty() && wTargetGuildName.find(wGuildName) == std::wstring::npos) continue; if (!wWords.empty()) { std::string aName; if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(target->GetZoneId())) aName = areaEntry->AreaName_lang; bool show = false; for (size_t i = 0; i < wWords.size(); ++i) { if (!wWords[i].empty()) { if (wTargetName.find(wWords[i]) != std::wstring::npos || wTargetGuildName.find(wWords[i]) != std::wstring::npos || Utf8FitTo(aName, wWords[i])) { show = true; break; } } } if (!show) continue; } WorldPackets::Who::WhoEntry whoEntry; if (!whoEntry.PlayerData.Initialize(target->GetGUID(), target)) continue; if (targetGuild) { whoEntry.GuildGUID = targetGuild->GetGUID(); whoEntry.GuildVirtualRealmAddress = GetVirtualRealmAddress(); whoEntry.GuildName = targetGuild->GetName(); } whoEntry.AreaID = target->GetZoneId(); whoEntry.IsGM = target->IsGameMaster(); response.Response.Entries.push_back(whoEntry); // 50 is maximum player count sent to client - can be overridden // through config, but is unstable if (response.Response.Entries.size() >= sWorld->getIntConfig(CONFIG_MAX_WHO)) break; } SendPacket(response.Write()); }