diff options
Diffstat (limited to 'src/server/game/Handlers/MiscHandler.cpp')
-rw-r--r-- | src/server/game/Handlers/MiscHandler.cpp | 244 |
1 files changed, 108 insertions, 136 deletions
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 6af14d53d50..c1045e63364 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -61,6 +61,7 @@ #include "ClientConfigPackets.h" #include "MiscPackets.h" #include "AchievementPackets.h" +#include "WhoPackets.h" void WorldSession::HandleRepopRequest(WorldPackets::Misc::RepopRequest& packet) { @@ -186,78 +187,63 @@ void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket& recvData) } } -void WorldSession::HandleWhoOpcode(WorldPacket& recvData) +void WorldSession::HandleWhoOpcode(WorldPackets::Who::WhoRequestPkt& whoRequest) { - TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_WHO Message"); + WorldPackets::Who::WhoRequest& request = whoRequest.Request; - uint32 matchcount = 0; + 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()); - uint32 level_min, level_max, racemask, classmask, zones_count, str_count; - uint32 zoneids[10]; // 10 is client limit - std::string player_name, guild_name; - - recvData >> level_min; // maximal player level, default 0 - recvData >> level_max; // minimal player level, default 100 (MAX_LEVEL) - recvData >> player_name; // player name, case sensitive... - - recvData >> guild_name; // guild name, case sensitive... - - recvData >> racemask; // race mask - recvData >> classmask; // class mask - recvData >> 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; - recvData >> temp; // zone id, 0 if zone is unknown... - zoneids[i] = temp; - TC_LOG_DEBUG("network", "Zone %u: %u", i, zoneids[i]); - } - - recvData >> str_count; // user entered strings count, client limit=4 (checked on 2.0.10) + // zones count, client limit = 10 (2.0.10) + // can't be received from real client or broken packet + if (whoRequest.Areas.size() > 10) + return; - if (str_count > 4) - return; // can't be received from real client or broken packet + // 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; - TC_LOG_DEBUG("network", "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); + /// @todo: handle following packet values + /// VirtualRealmNames + /// ShowEnemies + /// ShowArenaPlayers + /// ExactName + /// ServerInfo - std::wstring str[4]; // 4 is client limit - for (uint32 i = 0; i < str_count; ++i) + std::vector<std::wstring> wWords; + wWords.resize(request.Words.size()); + for (size_t i = 0; i < request.Words.size(); ++i) { - std::string temp; - recvData >> temp; // user entered string, it used as universal search pattern(guild+player name)? + TC_LOG_DEBUG("network", "WorldSession::HandleWhoOpcode: Word: %s", request.Words[i].Word); - if (!Utf8toWStr(temp, str[i])) + // user entered string, it used as universal search pattern(guild+player name)? + if (!Utf8toWStr(request.Words[i].Word, wWords[i])) continue; - wstrToLower(str[i]); - - TC_LOG_DEBUG("network", "String %u: %s", i, temp.c_str()); + wstrToLower(wWords[i]); } - std::wstring wplayer_name; - std::wstring wguild_name; - if (!(Utf8toWStr(player_name, wplayer_name) && Utf8toWStr(guild_name, wguild_name))) + std::wstring wPlayerName; + std::wstring wGuildName; + + if (!(Utf8toWStr(request.Name, wPlayerName) && Utf8toWStr(request.Guild, wGuildName))) return; - wstrToLower(wplayer_name); - wstrToLower(wguild_name); + + 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 (level_max >= MAX_LEVEL) - level_max = STRONG_MAX_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); - 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 + WorldPackets::Who::WhoResponsePkt response; boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock()); @@ -265,12 +251,12 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData) 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 CONFIG_ALLOW_TWO_SIDE_WHO_LIST + // 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 CONFIG_GM_IN_WHO_LIST - if (!HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && target->GetSession()->GetSecurity() > AccountTypes(gmLevelInWhoList)) + // 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 @@ -283,97 +269,92 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData) // check if target's level is in level range uint8 lvl = target->getLevel(); - if (lvl < level_min || lvl > level_max) + if (lvl < request.MinLevel || lvl > request.MaxLevel) continue; // check if class matches classmask - uint8 class_ = target->getClass(); - if (!(classmask & (1 << class_))) + if (request.ClassFilter >= 0 && !(request.ClassFilter & (1 << target->getClass()))) continue; // check if race matches racemask - uint32 race = target->getRace(); - if (!(racemask & (1 << race))) + if (request.RaceFilter >= 0 && !(request.RaceFilter & (1 << target->getRace()))) continue; - uint32 pzoneid = target->GetZoneId(); - uint8 gender = target->getGender(); - - bool z_show = true; - for (uint32 i = 0; i < zones_count; ++i) + if (!whoRequest.Areas.empty()) { - if (zoneids[i] == pzoneid) - { - z_show = true; - break; - } - - z_show = false; + if (std::find(whoRequest.Areas.begin(), whoRequest.Areas.end(), target->GetZoneId()) == whoRequest.Areas.end()) + continue; } - if (!z_show) - continue; - std::string pname = target->GetName(); - std::wstring wpname; - if (!Utf8toWStr(pname, wpname)) - continue; - wstrToLower(wpname); + std::wstring wTargetName; - if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos)) + if (!Utf8toWStr(target->GetName(), wTargetName)) continue; - std::string gname = sGuildMgr->GetGuildNameById(target->GetGuildId()); - std::wstring wgname; - if (!Utf8toWStr(gname, wgname)) + wstrToLower(wTargetName); + + if (!wPlayerName.empty() && wTargetName.find(wPlayerName) == std::wstring::npos) continue; - wstrToLower(wgname); - if (!(wguild_name.empty() || wgname.find(wguild_name) != std::wstring::npos)) + Guild* targetGuild = target->GetGuild(); + std::wstring wTargetGuildName; + + if (!Utf8toWStr(targetGuild ? targetGuild->GetName() : "", wTargetGuildName)) continue; - std::string aname; - if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(pzoneid)) - aname = areaEntry->ZoneName; + wstrToLower(wTargetGuildName); + + if (!wGuildName.empty() && wTargetGuildName.find(wGuildName) == std::wstring::npos) + continue; - bool s_show = true; - for (uint32 i = 0; i < str_count; ++i) + if (!wWords.empty()) { - if (!str[i].empty()) + std::string aName; + if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(target->GetZoneId())) + aName = areaEntry->ZoneName; + + bool show = false; + for (size_t i = 0; i < wWords.size(); ++i) { - if (wgname.find(str[i]) != std::wstring::npos || - wpname.find(str[i]) != std::wstring::npos || - Utf8FitTo(aname, str[i])) + if (!wWords[i].empty()) { - s_show = true; - break; + if (wTargetName.find(wWords[i]) != std::wstring::npos || + wTargetGuildName.find(wWords[i]) != std::wstring::npos || + Utf8FitTo(aName, wWords[i])) + { + show = true; + break; + } } - s_show = false; } + + if (!show) + continue; } - if (!s_show) - continue; - // 49 is maximum player count sent to client - can be overridden - // through config, but is unstable - if ((matchcount++) >= sWorld->getIntConfig(CONFIG_MAX_WHO)) + WorldPackets::Who::WhoEntry whoEntry; + if (!whoEntry.PlayerData.Initialize(target->GetGUID(), target)) continue; - 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 + if (targetGuild) + { + whoEntry.GuildGUID = targetGuild->GetGUID(); + whoEntry.GuildVirtualRealmAddress = GetVirtualRealmAddress(); + whoEntry.GuildName = targetGuild->GetName(); + } - ++displaycount; - } + whoEntry.AreaID = target->GetZoneId(); + whoEntry.IsGM = target->IsGameMaster(); - data.put(0, displaycount); // insert right count, count displayed - data.put(4, matchcount); // insert right count, count of matches + response.Response.Entries.push_back(whoEntry); - SendPacket(&data); - TC_LOG_DEBUG("network", "WORLD: Send SMSG_WHO Message"); + // 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()); } void WorldSession::HandleLogoutRequestOpcode(WorldPackets::Character::LogoutRequest& /*logoutRequest*/) @@ -1217,11 +1198,10 @@ void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recvData) SendNotification(LANG_YOU_NOT_HAVE_PERMISSION); } -void WorldSession::HandleWhoisOpcode(WorldPacket& recvData) +void WorldSession::HandleWhoisOpcode(WorldPackets::Who::WhoIsRequest& packet) { - TC_LOG_DEBUG("network", "Received opcode CMSG_WHOIS"); - std::string charname; - recvData >> charname; + TC_LOG_DEBUG("network", "Received whois command from player %s for character %s", + GetPlayer()->GetName().c_str(), packet.CharName.c_str()); if (!HasPermission(rbac::RBAC_PERM_OPCODE_WHOIS)) { @@ -1229,31 +1209,26 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recvData) return; } - if (charname.empty() || !normalizePlayerName (charname)) + if (packet.CharName.empty() || !normalizePlayerName(packet.CharName)) { SendNotification(LANG_NEED_CHARACTER_NAME); return; } - Player* player = ObjectAccessor::FindConnectedPlayerByName(charname); - + Player* player = ObjectAccessor::FindConnectedPlayerByName(packet.CharName); if (!player) { - SendNotification(LANG_PLAYER_NOT_EXIST_OR_OFFLINE, charname.c_str()); + SendNotification(LANG_PLAYER_NOT_EXIST_OR_OFFLINE, packet.CharName.c_str()); return; } - uint32 accid = player->GetSession()->GetAccountId(); - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_WHOIS); - - stmt->setUInt32(0, accid); + stmt->setUInt32(0, player->GetSession()->GetAccountId()); PreparedQueryResult result = LoginDatabase.Query(stmt); - if (!result) { - SendNotification(LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND, charname.c_str()); + SendNotification(LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND, packet.CharName.c_str()); return; } @@ -1261,21 +1236,18 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recvData) std::string acc = fields[0].GetString(); if (acc.empty()) acc = "Unknown"; + std::string email = fields[1].GetString(); if (email.empty()) email = "Unknown"; + std::string lastip = fields[2].GetString(); if (lastip.empty()) lastip = "Unknown"; - std::string msg = charname + "'s " + "account is " + acc + ", e-mail: " + email + ", last ip: " + lastip; - - WorldPacket data(SMSG_WHOIS, msg.size()+1); - data << msg; - SendPacket(&data); - - TC_LOG_DEBUG("network", "Received whois command from player %s for character %s", - GetPlayer()->GetName().c_str(), charname.c_str()); + WorldPackets::Who::WhoIsResponse response; + response.AccountName = packet.CharName + "'s " + "account is " + acc + ", e-mail: " + email + ", last ip: " + lastip; + SendPacket(response.Write()); } void WorldSession::HandleComplainOpcode(WorldPacket& recvData) |