diff options
author | joschiwald <joschiwald.trinity@gmail.com> | 2015-02-05 20:18:32 +0100 |
---|---|---|
committer | joschiwald <joschiwald.trinity@gmail.com> | 2015-02-05 20:18:32 +0100 |
commit | be6b1f52516be0feb2b64f3bdbe1899cf5576777 (patch) | |
tree | f3706f037ba8a0f9e0dcdfb2f56ccb08cc31bb65 | |
parent | 0ac3a21d3331e5a65873e0c76dad7e64213d0536 (diff) |
Core/Packets:
- updated who packets
- fixed typos from previous commits
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Handlers/InspectHandler.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Handlers/MiscHandler.cpp | 244 | ||||
-rw-r--r-- | src/server/game/Handlers/QueryHandler.cpp | 24 | ||||
-rw-r--r-- | src/server/game/Server/Packets/InspectPackets.h | 2 | ||||
-rw-r--r-- | src/server/game/Server/Packets/ItemPackets.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Server/Packets/QueryPackets.cpp | 91 | ||||
-rw-r--r-- | src/server/game/Server/Packets/QueryPackets.h | 16 | ||||
-rw-r--r-- | src/server/game/Server/Packets/TicketPackets.h | 11 | ||||
-rw-r--r-- | src/server/game/Server/Packets/WhoPackets.cpp | 126 | ||||
-rw-r--r-- | src/server/game/Server/Packets/WhoPackets.h | 116 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 9 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 10 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 2 | ||||
-rw-r--r-- | src/server/worldserver/worldserver.conf.dist | 4 |
15 files changed, 456 insertions, 204 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 67b1985c2dd..cfd45ebe553 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -25024,7 +25024,6 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot) // LootItem is being removed (looted) from the container, delete it from the DB. if (!loot->containerID.IsEmpty()) loot->DeleteLootItemFromContainerItemDB(item->itemid); - } else SendEquipError(msg, NULL, NULL, item->itemid); diff --git a/src/server/game/Handlers/InspectHandler.cpp b/src/server/game/Handlers/InspectHandler.cpp index 7a8749e0c8e..4057960bfc9 100644 --- a/src/server/game/Handlers/InspectHandler.cpp +++ b/src/server/game/Handlers/InspectHandler.cpp @@ -117,7 +117,7 @@ void WorldSession::HandleInspectPVP(WorldPackets::Inspect::InspectPVPRequest& re return; } - TC_LOG_DEBUG("network", "WorldSession::HandleInspectPVP: Target %s, InspectRealmAddress %u.", request.InspectTarget.ToString().c_str(), request.InspectTarget); + TC_LOG_DEBUG("network", "WorldSession::HandleInspectPVP: Target %s, InspectRealmAddress %u.", request.InspectTarget.ToString().c_str(), request.InspectRealmAddress); if (!GetPlayer()->IsWithinDistInMap(player, INSPECT_DISTANCE, false)) return; 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) diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index 49ac42f0abf..4afb2826889 100644 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -30,38 +30,18 @@ #include "NPCHandler.h" #include "Pet.h" #include "MapManager.h" -#include "BattlenetAccountMgr.h" #include "CharacterPackets.h" #include "QueryPackets.h" void WorldSession::SendNameQueryOpcode(ObjectGuid guid) { Player* player = ObjectAccessor::FindConnectedPlayer(guid); - CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid); WorldPackets::Query::QueryPlayerNameResponse response; response.Player = guid; - if (characterInfo) - { - uint32 accountId = player ? player->GetSession()->GetAccountId() : ObjectMgr::GetPlayerAccountIdByGUID(guid); - uint32 bnetAccountId = player ? player->GetSession()->GetBattlenetAccountId() : Battlenet::AccountMgr::GetIdByGameAccount(accountId); - - response.Result = RESPONSE_SUCCESS; // name known - response.Data.IsDeleted = characterInfo->IsDeleted; - response.Data.AccountID = ObjectGuid::Create<HighGuid::WowAccount>(accountId); - response.Data.BnetAccountID = ObjectGuid::Create<HighGuid::BNetAccount>(bnetAccountId); - response.Data.Name = characterInfo->Name; - response.Data.VirtualRealmAddress = GetVirtualRealmAddress(); - response.Data.Race = characterInfo->Race; - response.Data.Sex = characterInfo->Sex; - response.Data.ClassID = characterInfo->Class; - response.Data.Level = characterInfo->Level; - - if (DeclinedName const* names = (player ? player->GetDeclinedNames() : nullptr)) - for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - response.Data.DeclinedNames.name[i] = names->name[i]; - } + if (response.Data.Initialize(guid, player)) + response.Result = RESPONSE_SUCCESS; // name known else response.Result = RESPONSE_FAILURE; // name unknown diff --git a/src/server/game/Server/Packets/InspectPackets.h b/src/server/game/Server/Packets/InspectPackets.h index 5f0fa45bb24..87a75a5834f 100644 --- a/src/server/game/Server/Packets/InspectPackets.h +++ b/src/server/game/Server/Packets/InspectPackets.h @@ -39,7 +39,7 @@ namespace WorldPackets struct InspectEnchantData { - InspectEnchantData(uint32 id, uint8 index) : Id(id), Index(Index) { } + InspectEnchantData(uint32 id, uint8 index) : Id(id), Index(index) { } uint32 Id = 0; uint8 Index = 0; diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp index 494d53b25f7..8456c68ee67 100644 --- a/src/server/game/Server/Packets/ItemPackets.cpp +++ b/src/server/game/Server/Packets/ItemPackets.cpp @@ -102,7 +102,7 @@ ByteBuffer& WorldPackets::Item::operator>>(ByteBuffer& data, InvUpdate& invUpdat void WorldPackets::Item::ItemInstance::Initalize(::Item const* item) { ItemID = item->GetEntry(); - RandomPropertiesSeed = item->GetTemplate()->GetRandomSuffix(); /// @todo: confirm this + RandomPropertiesSeed = item->GetItemSuffixFactor(); RandomPropertiesID = item->GetItemRandomPropertyId(); std::vector<uint32> const& bonusListIds = item->GetDynamicValues(ITEM_DYNAMIC_FIELD_BONUSLIST_IDS); if (!bonusListIds.empty()) diff --git a/src/server/game/Server/Packets/QueryPackets.cpp b/src/server/game/Server/Packets/QueryPackets.cpp index 4d6a0a56463..4dfd01dfcaa 100644 --- a/src/server/game/Server/Packets/QueryPackets.cpp +++ b/src/server/game/Server/Packets/QueryPackets.cpp @@ -16,6 +16,9 @@ */ #include "QueryPackets.h" +#include "BattlenetAccountMgr.h" +#include "Player.h" +#include "World.h" void WorldPackets::Query::QueryCreature::Read() { @@ -103,31 +106,81 @@ void WorldPackets::Query::QueryPlayerName::Read() _worldPacket >> Hint.NativeRealmAddress.Value; } +bool WorldPackets::Query::PlayerGuidLookupData::Initialize(ObjectGuid const& guid, Player const* player /*= nullptr*/) +{ + CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid); + if (!characterInfo) + return false; + + if (player) + { + ASSERT(player->GetGUID() == guid); + + AccountID = player->GetSession()->GetAccountGUID(); + BnetAccountID = player->GetSession()->GetBattlenetAccountGUID(); + Name = player->GetName(); + Race = player->getRace(); + Sex = player->getGender(); + ClassID = player->getClass(); + Level = player->getLevel(); + + if (DeclinedName const* names = player->GetDeclinedNames()) + DeclinedNames = *names; + } + else + { + uint32 accountId = ObjectMgr::GetPlayerAccountIdByGUID(guid); + uint32 bnetAccountId = Battlenet::AccountMgr::GetIdByGameAccount(accountId); + + AccountID = ObjectGuid::Create<HighGuid::WowAccount>(accountId); + BnetAccountID = ObjectGuid::Create<HighGuid::BNetAccount>(bnetAccountId); + Name = characterInfo->Name; + Race = characterInfo->Race; + Sex = characterInfo->Sex; + ClassID = characterInfo->Class; + Level = characterInfo->Level; + } + + IsDeleted = characterInfo->IsDeleted; + GuidActual = guid; + VirtualRealmAddress = GetVirtualRealmAddress(); + + return true; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::PlayerGuidLookupData const& lookupData) +{ + data.WriteBit(lookupData.IsDeleted); + data.WriteBits(lookupData.Name.length(), 6); + + for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + data.WriteBits(lookupData.DeclinedNames.name[i].length(), 7); + + for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + data.WriteString(lookupData.DeclinedNames.name[i]); + + data << lookupData.AccountID; + data << lookupData.BnetAccountID; + data << lookupData.GuidActual; + data << uint32(lookupData.VirtualRealmAddress); + data << uint8(lookupData.Race); + data << uint8(lookupData.Sex); + data << uint8(lookupData.ClassID); + data << uint8(lookupData.Level); + data.WriteString(lookupData.Name); + + data.FlushBits(); + + return data; +} + WorldPacket const* WorldPackets::Query::QueryPlayerNameResponse::Write() { _worldPacket << Result; _worldPacket << Player; if (Result == RESPONSE_SUCCESS) - { - _worldPacket.WriteBits(Data.Name.length(), 7); - - for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - _worldPacket.WriteBits(Data.DeclinedNames.name[i].length(), 7); - - for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - _worldPacket.WriteString(Data.DeclinedNames.name[i]); - - _worldPacket << Data.AccountID; - _worldPacket << Data.BnetAccountID; - _worldPacket << Data.GuidActual; - _worldPacket << Data.VirtualRealmAddress; - _worldPacket << Data.Race; - _worldPacket << Data.Sex; - _worldPacket << Data.ClassID; - _worldPacket << Data.Level; - _worldPacket.WriteString(Data.Name); - } + _worldPacket << Data; return &_worldPacket; } diff --git a/src/server/game/Server/Packets/QueryPackets.h b/src/server/game/Server/Packets/QueryPackets.h index 5a48db610ca..3907476129c 100644 --- a/src/server/game/Server/Packets/QueryPackets.h +++ b/src/server/game/Server/Packets/QueryPackets.h @@ -24,6 +24,8 @@ #include "NPCHandler.h" #include "G3D/Vector3.h" +class Player; + namespace WorldPackets { namespace Query @@ -90,16 +92,18 @@ namespace WorldPackets struct PlayerGuidLookupData { - bool IsDeleted = false; + bool Initialize(ObjectGuid const& guid, Player const* player = nullptr); + + bool IsDeleted = false; ObjectGuid AccountID; ObjectGuid BnetAccountID; ObjectGuid GuidActual; std::string Name; uint32 VirtualRealmAddress = 0; - uint8 Race = RACE_NONE; - uint8 Sex = GENDER_NONE; - uint8 ClassID = CLASS_NONE; - uint8 Level = 0; + uint8 Race = RACE_NONE; + uint8 Sex = GENDER_NONE; + uint8 ClassID = CLASS_NONE; + uint8 Level = 0; DeclinedName DeclinedNames; }; @@ -319,4 +323,6 @@ namespace WorldPackets } } +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::PlayerGuidLookupData const& lookupData); + #endif // QueryPackets_h__ diff --git a/src/server/game/Server/Packets/TicketPackets.h b/src/server/game/Server/Packets/TicketPackets.h index 076db67fb96..8a5ae862f84 100644 --- a/src/server/game/Server/Packets/TicketPackets.h +++ b/src/server/game/Server/Packets/TicketPackets.h @@ -29,7 +29,7 @@ namespace WorldPackets public: GMTicketGetSystemStatus(WorldPacket&& packet) : ClientPacket(CMSG_GM_TICKET_GET_SYSTEM_STATUS, std::move(packet)) { } - void Read() override { }; + void Read() override { } }; class GMTicketSystemStatus final : public ServerPacket @@ -47,7 +47,7 @@ namespace WorldPackets public: GMTicketGetCaseStatus(WorldPacket&& packet) : ClientPacket(CMSG_GM_TICKET_GET_CASE_STATUS, std::move(packet)) { } - void Read() override { }; + void Read() override { } }; class GMTicketCaseStatus final : public ServerPacket @@ -63,11 +63,6 @@ namespace WorldPackets int32 WaitTimeOverrideMinutes = 0; std::string Url; std::string WaitTimeOverrideMessage; - - bool operator<(GMTicketCase const& right) const - { - return CaseID < right.CaseID; - } }; GMTicketCaseStatus() : ServerPacket(SMSG_GM_TICKET_CASE_STATUS, 12) { } @@ -76,7 +71,7 @@ namespace WorldPackets time_t OldestTicketTime = 0; time_t UpdateTime = 0; - std::set<GMTicketCase> Cases; + std::vector<GMTicketCase> Cases; }; class GMTicketGetTicket final : public ClientPacket diff --git a/src/server/game/Server/Packets/WhoPackets.cpp b/src/server/game/Server/Packets/WhoPackets.cpp new file mode 100644 index 00000000000..7a1704e2567 --- /dev/null +++ b/src/server/game/Server/Packets/WhoPackets.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "WhoPackets.h" + +void WorldPackets::Who::WhoIsRequest::Read() +{ + CharName = _worldPacket.ReadString(_worldPacket.ReadBits(6)); +} + +WorldPacket const* WorldPackets::Who::WhoIsResponse::Write() +{ + _worldPacket.WriteBits(AccountName.length(), 11); + _worldPacket.WriteString(AccountName); + _worldPacket.FlushBits(); + + return &_worldPacket; +} + +ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Who::WhoWord& word) +{ + data.ResetBitPos(); + word.Word = data.ReadString(data.ReadBits(7)); + + return data; +} + +ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Who::WhoRequestServerInfo& serverInfo) +{ + data >> serverInfo.FactionGroup; + data >> serverInfo.Locale; + data >> serverInfo.RequesterVirtualRealmAddress; + + return data; +} + +ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Who::WhoRequest& request) +{ + data >> request.MinLevel; + data >> request.MaxLevel; + data >> request.RaceFilter; + data >> request.ClassFilter; + + uint32 nameLength = data.ReadBits(6); + uint32 virtualRealmNameLength = data.ReadBits(9); + uint32 guildNameLength = data.ReadBits(7); + uint32 guildVirtualRealmNameLength = data.ReadBits(9); + request.Words.resize(data.ReadBits(3)); + + request.ShowEnemies = data.ReadBit(); + request.ShowArenaPlayers = data.ReadBit(); + request.ExactName = data.ReadBit(); + request.ServerInfo.HasValue = data.ReadBit(); + + request.Name = data.ReadString(nameLength); + request.VirtualRealmName = data.ReadString(virtualRealmNameLength); + request.Guild = data.ReadString(guildNameLength); + request.GuildVirtualRealmName = data.ReadString(guildVirtualRealmNameLength); + + for (size_t i = 0; i < request.Words.size(); ++i) + data >> request.Words[i]; + + if (request.ServerInfo.HasValue) + data >> request.ServerInfo.Value; + + return data; +} + +void WorldPackets::Who::WhoRequestPkt::Read() +{ + Areas.resize(_worldPacket.ReadBits(4)); + + _worldPacket >> Request; + + for (size_t i = 0; i < Areas.size(); ++i) + _worldPacket >> Areas[i]; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Who::WhoEntry const& entry) +{ + data << entry.PlayerData; + + data << entry.GuildGUID; + data << uint32(entry.GuildVirtualRealmAddress); + data << int32(entry.AreaID); + + data.WriteBits(entry.GuildName.length(), 7); + data.WriteBit(entry.IsGM); + data.WriteString(entry.GuildName); + + data.FlushBits(); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Who::WhoResponse const& response) +{ + data.WriteBits(response.Entries.size(), 6); + data.FlushBits(); + + for (size_t i = 0; i < response.Entries.size(); ++i) + data << response.Entries[i]; + + return data; +} + +WorldPacket const* WorldPackets::Who::WhoResponsePkt::Write() +{ + _worldPacket << Response; + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/WhoPackets.h b/src/server/game/Server/Packets/WhoPackets.h new file mode 100644 index 00000000000..3a3618c9756 --- /dev/null +++ b/src/server/game/Server/Packets/WhoPackets.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WhoPackets_h__ +#define WhoPackets_h__ + +#include "Packet.h" +#include "ObjectGuid.h" +#include "QueryPackets.h" + +namespace WorldPackets +{ + namespace Who + { + class WhoIsRequest final : public ClientPacket + { + public: + WhoIsRequest(WorldPacket&& packet) : ClientPacket(CMSG_WHOIS, std::move(packet)) { } + + void Read() override; + + std::string CharName; + }; + + class WhoIsResponse final : public ServerPacket + { + public: + WhoIsResponse() : ServerPacket(SMSG_WHOIS, 2) { } + + WorldPacket const* Write() override; + + std::string AccountName; + }; + + struct WhoWord + { + std::string Word; + }; + + struct WhoRequestServerInfo + { + int32 FactionGroup = 0; + int32 Locale = 0; + uint32 RequesterVirtualRealmAddress = 0; + }; + + struct WhoRequest + { + int32 MinLevel = 0; + int32 MaxLevel = 0; + std::string Name; + std::string VirtualRealmName; + std::string Guild; + std::string GuildVirtualRealmName; + int32 RaceFilter = -1; + int32 ClassFilter = -1; + std::vector<WhoWord> Words; + bool ShowEnemies = false; + bool ShowArenaPlayers = false; + bool ExactName = false; + Optional<WhoRequestServerInfo> ServerInfo; + }; + + class WhoRequestPkt final : public ClientPacket + { + public: + WhoRequestPkt(WorldPacket&& packet) : ClientPacket(CMSG_WHO, std::move(packet)) { } + + void Read() override; + + WhoRequest Request; + std::vector<int32> Areas; + }; + + struct WhoEntry + { + Query::PlayerGuidLookupData PlayerData; + ObjectGuid GuildGUID; + uint32 GuildVirtualRealmAddress = 0; + std::string GuildName; + int32 AreaID = 0; + bool IsGM = false; + }; + + struct WhoResponse + { + std::vector<WhoEntry> Entries; + }; + + class WhoResponsePkt final : public ServerPacket + { + public: + WhoResponsePkt() : ServerPacket(SMSG_WHO, 1) { } + + WorldPacket const* Write() override; + + WhoResponse Response; + }; + } +} + +#endif // WhoPackets_h__ diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 0dfb5b9d016..9b9bb079729 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -41,6 +41,7 @@ #include "Packets/TalentPackets.h" #include "Packets/TradePackets.h" #include "Packets/TicketPackets.h" +#include "Packets/WhoPackets.h" template<class PacketClass, void(WorldSession::*HandlerFunction)(PacketClass&)> class PacketHandler : public ClientOpcodeHandler @@ -898,8 +899,8 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_WARDEN_DATA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWardenDataOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_WARGAME_ACCEPT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_WARGAME_START, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_WHO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_WHOIS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoisOpcode ); + DEFINE_HANDLER(CMSG_WHO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Who::WhoRequestPkt, &WorldSession::HandleWhoOpcode); + DEFINE_HANDLER(CMSG_WHOIS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Who::WhoIsRequest, &WorldSession::HandleWhoisOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_WORLD_TELEPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWorldTeleportOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_WRAP_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWrapItemOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_ZONEUPDATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleZoneUpdateOpcode ); @@ -1950,8 +1951,8 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_WEEKLY_RESET_CURRENCY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_WEEKLY_SPELL_USAGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_WEEKLY_SPELL_USAGE_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_WHO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_WHOIS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_WHO, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_WHOIS, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_WORLD_SERVER_INFO, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_XP_GAIN_ABORTED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_XP_GAIN_ENABLED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 2b54b5d794d..029d97ce9bd 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -279,6 +279,12 @@ namespace WorldPackets { class CancelTrade; } + + namespace Who + { + class WhoIsRequest; + class WhoRequestPkt; + } } enum AccountDataType @@ -737,7 +743,7 @@ class WorldSession void HandleLootOpcode(WorldPackets::Loot::LootUnit& packet); void HandleLootReleaseOpcode(WorldPackets::Loot::LootRelease& packet); void HandleLootMasterGiveOpcode(WorldPacket& recvPacket); - void HandleWhoOpcode(WorldPacket& recvPacket); + void HandleWhoOpcode(WorldPackets::Who::WhoRequestPkt& whoRequest); void HandleLogoutRequestOpcode(WorldPackets::Character::LogoutRequest& logoutRequest); void HandleLogoutCancelOpcode(WorldPackets::Character::LogoutCancel& logoutCancel); @@ -1094,7 +1100,7 @@ class WorldSession void HandleSetTitleOpcode(WorldPacket& recvData); void HandleRealmSplitOpcode(WorldPacket& recvData); void HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse& packet); - void HandleWhoisOpcode(WorldPacket& recvData); + void HandleWhoisOpcode(WorldPackets::Who::WhoIsRequest& packet); void HandleResetInstancesOpcode(WorldPacket& recvData); void HandleHearthAndResurrect(WorldPacket& recvData); void HandleInstanceLockResponse(WorldPacket& recvPacket); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 7885819af9f..c2f482570a1 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -278,7 +278,6 @@ void World::AddSession_(WorldSession* s) s->SendAuthResponse(AUTH_OK, false); s->SendSetTimeZoneInformation(); - s->SendFeatureSystemStatus(); s->SendFeatureSystemStatusGlueScreen(); s->SendAddonsInfo(); @@ -378,7 +377,6 @@ bool World::RemoveQueuedPlayer(WorldSession* sess) pop_sess->SendAuthWaitQue(0); pop_sess->SendSetTimeZoneInformation(); - pop_sess->SendFeatureSystemStatus(); pop_sess->SendFeatureSystemStatusGlueScreen(); pop_sess->SendAddonsInfo(); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 0327d0f8884..cadf86d6618 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -615,9 +615,9 @@ ArenaTeam.CharterCost.5v5 = 2000000 # # MaxWhoListReturns # Description: Set the max number of players returned in the /who list and interface. -# Default: 49 - (stable) +# Default: 50 - (stable) -MaxWhoListReturns = 49 +MaxWhoListReturns = 50 # # CharacterCreating.Disabled |