mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-19 17:05:44 +01:00
Core/Packets: converted CMSG_WHO and SMSG_WHO to packet class
This commit is contained in:
@@ -48,10 +48,12 @@
|
||||
#include "Opcodes.h"
|
||||
#include "OutdoorPvP.h"
|
||||
#include "Player.h"
|
||||
#include "QueryPackets.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "WhoListStorage.h"
|
||||
#include "WhoPackets.h"
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
#include <zlib.h>
|
||||
@@ -178,89 +180,62 @@ 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;
|
||||
|
||||
uint32 levelMin, levelMax, racemask, classmask, zonesCount, strCount;
|
||||
uint32 zoneids[10]; // 10 is client limit
|
||||
std::string packetPlayerName, packetGuildName;
|
||||
|
||||
recvData >> levelMin; // maximal player level, default 0
|
||||
recvData >> levelMax; // minimal player level, default 100 (MAX_LEVEL)
|
||||
recvData >> packetPlayerName; // player name, case sensitive...
|
||||
|
||||
recvData >> packetGuildName; // guild name, case sensitive...
|
||||
|
||||
recvData >> racemask; // race mask
|
||||
recvData >> classmask; // class mask
|
||||
recvData >> zonesCount; // zones count, client limit = 10 (2.0.10)
|
||||
|
||||
if (zonesCount > 10)
|
||||
return; // can't be received from real client or broken packet
|
||||
|
||||
for (uint32 i = 0; i < zonesCount; ++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 >> strCount; // user entered strings count, client limit=4 (checked on 2.0.10)
|
||||
|
||||
if (strCount > 4)
|
||||
return; // can't be received from real client or broken packet
|
||||
|
||||
TC_LOG_DEBUG("network", "Minlvl %u, maxlvl %u, name %s, guild %s, racemask %u, classmask %u, zones %u, strings %u", levelMin, levelMax, packetPlayerName.c_str(), packetGuildName.c_str(), racemask, classmask, zonesCount, strCount);
|
||||
|
||||
std::wstring str[4]; // 4 is client limit
|
||||
for (uint32 i = 0; i < strCount; ++i)
|
||||
{
|
||||
std::string temp;
|
||||
recvData >> temp; // user entered string, it used as universal search pattern(guild+player name)?
|
||||
|
||||
if (!Utf8toWStr(temp, str[i]))
|
||||
continue;
|
||||
|
||||
wstrToLower(str[i]);
|
||||
|
||||
TC_LOG_DEBUG("network", "String %u: %s", i, temp.c_str());
|
||||
}
|
||||
|
||||
std::wstring wpacketPlayerName;
|
||||
std::wstring wpacketGuildName;
|
||||
if (!(Utf8toWStr(packetPlayerName, wpacketPlayerName) && Utf8toWStr(packetGuildName, wpacketGuildName)))
|
||||
// zones count, client limit = 10 (2.0.10)
|
||||
// can't be received from real client or broken packet
|
||||
if (whoRequest.Request.Areas.size() > 10)
|
||||
return;
|
||||
|
||||
wstrToLower(wpacketPlayerName);
|
||||
wstrToLower(wpacketGuildName);
|
||||
// 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;
|
||||
|
||||
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 (levelMax >= MAX_LEVEL)
|
||||
levelMax = 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;
|
||||
uint32 gmLevelInWhoList = sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST);
|
||||
|
||||
WorldPacket data(SMSG_WHO, 500); // guess size
|
||||
data << uint32(matchCount); // placeholder, count of players matching criteria
|
||||
data << uint32(displayCount); // placeholder, count of players displayed
|
||||
WorldPackets::Who::WhoResponsePkt response;
|
||||
|
||||
WhoListInfoVector const& whoList = sWhoListStorageMgr->GetWhoList();
|
||||
for (WhoListPlayerInfo const& target : whoList)
|
||||
{
|
||||
// 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.GetSecurity() > AccountTypes(gmLevelInWhoList))
|
||||
// player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if has RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS
|
||||
if (target.GetSecurity() > AccountTypes(gmLevelInWhoList) && !HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS))
|
||||
continue;
|
||||
|
||||
// check if target is globally visible for player
|
||||
@@ -270,87 +245,75 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
|
||||
|
||||
// check if target's level is in level range
|
||||
uint8 lvl = target.GetLevel();
|
||||
if (lvl < levelMin || lvl > levelMax)
|
||||
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 playerZoneId = target.GetZoneId();
|
||||
uint8 gender = target.GetGender();
|
||||
|
||||
bool showZones = true;
|
||||
for (uint32 i = 0; i < zonesCount; ++i)
|
||||
if (!whoRequest.Request.Areas.empty())
|
||||
{
|
||||
if (zoneids[i] == playerZoneId)
|
||||
{
|
||||
showZones = true;
|
||||
break;
|
||||
}
|
||||
|
||||
showZones = false;
|
||||
if (std::find(whoRequest.Request.Areas.begin(), whoRequest.Request.Areas.end(), target.GetZoneId()) == whoRequest.Request.Areas.end())
|
||||
continue;
|
||||
}
|
||||
if (!showZones)
|
||||
|
||||
std::wstring const& wTargetName = target.GetWidePlayerName();
|
||||
if (!(wPlayerName.empty() || wTargetName.find(wPlayerName) != std::wstring::npos))
|
||||
continue;
|
||||
|
||||
std::wstring const& wideplayername = target.GetWidePlayerName();
|
||||
if (!(wpacketPlayerName.empty() || wideplayername.find(wpacketPlayerName) != std::wstring::npos))
|
||||
std::wstring const& wTargetGuildName = target.GetWideGuildName();
|
||||
|
||||
if (!wGuildName.empty() && wTargetGuildName.find(wGuildName) == std::wstring::npos)
|
||||
continue;
|
||||
|
||||
std::wstring const& wideguildname = target.GetWideGuildName();
|
||||
if (!(wpacketGuildName.empty() || wideguildname.find(wpacketGuildName) != std::wstring::npos))
|
||||
continue;
|
||||
|
||||
std::string aname;
|
||||
if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(playerZoneId))
|
||||
aname = areaEntry->AreaName[GetSessionDbcLocale()];
|
||||
|
||||
bool s_show = true;
|
||||
for (uint32 i = 0; i < strCount; ++i)
|
||||
if (!wWords.empty())
|
||||
{
|
||||
if (!str[i].empty())
|
||||
std::string aName;
|
||||
if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(target.GetZoneId()))
|
||||
aName = areaEntry->AreaName[GetSessionDbcLocale()];
|
||||
|
||||
bool show = false;
|
||||
for (size_t i = 0; i < wWords.size(); ++i)
|
||||
{
|
||||
if (wideguildname.find(str[i]) != std::wstring::npos ||
|
||||
wideplayername.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)
|
||||
|
||||
WorldPackets::Who::WhoEntry whoEntry;
|
||||
if (!whoEntry.PlayerData.Initialize(target.GetGuid(), nullptr))
|
||||
continue;
|
||||
|
||||
// 49 is maximum player count sent to client - can be overridden
|
||||
if (!target.GetGuildName().empty())
|
||||
whoEntry.GuildName = target.GetGuildName();
|
||||
|
||||
whoEntry.AreaID = target.GetZoneId();
|
||||
|
||||
response.Response.Entries.push_back(whoEntry);
|
||||
|
||||
// 50 is maximum player count sent to client - can be overridden
|
||||
// through config, but is unstable
|
||||
if ((matchCount++) >= sWorld->getIntConfig(CONFIG_MAX_WHO))
|
||||
continue;
|
||||
|
||||
data << target.GetPlayerName(); // player name
|
||||
data << target.GetGuildName(); // guild name
|
||||
data << uint32(lvl); // player level
|
||||
data << uint32(class_); // player class
|
||||
data << uint32(race); // player race
|
||||
data << uint8(gender); // player gender
|
||||
data << uint32(playerZoneId); // player zone id
|
||||
|
||||
++displayCount;
|
||||
if (response.Response.Entries.size() >= sWorld->getIntConfig(CONFIG_MAX_WHO))
|
||||
break;
|
||||
}
|
||||
|
||||
data.put(0, displayCount); // insert right count, count displayed
|
||||
data.put(4, matchCount); // insert right count, count of matches
|
||||
|
||||
SendPacket(&data);
|
||||
TC_LOG_DEBUG("network", "WORLD: Send SMSG_WHO Message");
|
||||
SendPacket(response.Write());
|
||||
}
|
||||
|
||||
void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/)
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "QuestPackets.h"
|
||||
#include "QueryPackets.h"
|
||||
#include "SystemPackets.h"
|
||||
#include "WhoPackets.h"
|
||||
#include "WorldStatePackets.h"
|
||||
|
||||
#endif // AllPackets_h__
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "CharacterCache.h"
|
||||
#include "Player.h"
|
||||
#include "QueryPackets.h"
|
||||
|
||||
void WorldPackets::Query::DBQueryBulk::Read()
|
||||
@@ -75,3 +77,31 @@ WorldPacket const* WorldPackets::Query::HotfixNotifyBlob::Write()
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
bool WorldPackets::Query::PlayerGuidLookupData::Initialize(ObjectGuid const& guid, Player const* player /*= nullptr*/)
|
||||
{
|
||||
CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(guid);
|
||||
if (!characterInfo)
|
||||
return false;
|
||||
|
||||
if (player)
|
||||
{
|
||||
ASSERT(player->GetGUID() == guid);
|
||||
|
||||
Name = player->GetName();
|
||||
Race = player->getRace();
|
||||
Sex = player->getGender();
|
||||
ClassID = player->getClass();
|
||||
Level = player->getLevel();
|
||||
}
|
||||
else
|
||||
{
|
||||
Name = characterInfo->Name;
|
||||
Race = characterInfo->Race;
|
||||
Sex = characterInfo->Sex;
|
||||
ClassID = characterInfo->Class;
|
||||
Level = characterInfo->Level;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#include "Packet.h"
|
||||
#include "DB2Stores.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "SharedDefines.h"
|
||||
|
||||
class Player;
|
||||
|
||||
namespace WorldPackets
|
||||
{
|
||||
@@ -65,6 +68,17 @@ namespace WorldPackets
|
||||
|
||||
HotfixData const* Hotfixes = nullptr;
|
||||
};
|
||||
|
||||
struct PlayerGuidLookupData
|
||||
{
|
||||
bool Initialize(ObjectGuid const& guid, Player const* player = nullptr);
|
||||
|
||||
std::string Name;
|
||||
uint8 Race = RACE_NONE;
|
||||
uint8 Sex = GENDER_NONE;
|
||||
uint8 ClassID = CLASS_NONE;
|
||||
uint8 Level = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
87
src/server/game/Server/Packets/WhoPackets.cpp
Normal file
87
src/server/game/Server/Packets/WhoPackets.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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"
|
||||
|
||||
ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Who::WhoWord& word)
|
||||
{
|
||||
data >> word.Word;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Who::WhoRequest& request)
|
||||
{
|
||||
data >> request.MinLevel;
|
||||
data >> request.MaxLevel;
|
||||
data >> request.Guild;
|
||||
data >> request.Name;
|
||||
data >> request.RaceFilter;
|
||||
data >> request.ClassFilter;
|
||||
|
||||
uint32 areas = 0;
|
||||
data >> areas;
|
||||
|
||||
request.Areas.resize(areas);
|
||||
for (size_t i = 0; i < request.Areas.size(); ++i)
|
||||
data >> request.Areas[i];
|
||||
|
||||
uint32 words = 0;
|
||||
data >> words;
|
||||
|
||||
request.Words.resize(words);
|
||||
for (size_t i = 0; i < request.Words.size(); ++i)
|
||||
data >> request.Words[i];
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void WorldPackets::Who::WhoRequestPkt::Read()
|
||||
{
|
||||
_worldPacket >> Request;
|
||||
}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Who::WhoEntry const& entry)
|
||||
{
|
||||
data << entry.PlayerData.Name;
|
||||
data << entry.GuildName;
|
||||
data << uint32(entry.PlayerData.Level);
|
||||
data << uint32(entry.PlayerData.ClassID);
|
||||
data << uint32(entry.PlayerData.Race);
|
||||
data << uint8(entry.PlayerData.Sex);
|
||||
data << uint32(entry.AreaID);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Who::WhoResponse const& response)
|
||||
{
|
||||
data << uint32(response.Entries.size()); // Number of displayed characters
|
||||
data << uint32(response.Entries.size()); // Number of matching characters (when using filters) TODO
|
||||
|
||||
for (WorldPackets::Who::WhoEntry const& whoEntry : response.Entries)
|
||||
data << whoEntry;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
WorldPacket const* WorldPackets::Who::WhoResponsePkt::Write()
|
||||
{
|
||||
_worldPacket << Response;
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
79
src/server/game/Server/Packets/WhoPackets.h
Normal file
79
src/server/game/Server/Packets/WhoPackets.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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 "QueryPackets.h"
|
||||
|
||||
namespace WorldPackets
|
||||
{
|
||||
namespace Who
|
||||
{
|
||||
struct WhoWord
|
||||
{
|
||||
std::string Word;
|
||||
};
|
||||
|
||||
struct WhoRequest
|
||||
{
|
||||
int32 MinLevel = 0;
|
||||
int32 MaxLevel = 0;
|
||||
std::string Name;
|
||||
std::string Guild;
|
||||
int32 RaceFilter = -1;
|
||||
int32 ClassFilter = -1;
|
||||
std::vector<WhoWord> Words;
|
||||
std::vector<int32> Areas;
|
||||
};
|
||||
|
||||
class WhoRequestPkt final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
WhoRequestPkt(WorldPacket&& packet) : ClientPacket(CMSG_WHO, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
WhoRequest Request;
|
||||
};
|
||||
|
||||
struct WhoEntry
|
||||
{
|
||||
Query::PlayerGuidLookupData PlayerData;
|
||||
std::string GuildName;
|
||||
int32 AreaID = 0;
|
||||
};
|
||||
|
||||
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__
|
||||
@@ -171,6 +171,11 @@ namespace WorldPackets
|
||||
{
|
||||
class DBQueryBulk;
|
||||
}
|
||||
|
||||
namespace Who
|
||||
{
|
||||
class WhoRequestPkt;
|
||||
}
|
||||
}
|
||||
|
||||
enum AccountDataType
|
||||
@@ -656,7 +661,7 @@ class TC_GAME_API WorldSession
|
||||
void HandleLootOpcode(WorldPacket& recvPacket);
|
||||
void HandleLootReleaseOpcode(WorldPacket& recvPacket);
|
||||
void HandleLootMasterGiveOpcode(WorldPacket& recvPacket);
|
||||
void HandleWhoOpcode(WorldPacket& recvPacket);
|
||||
void HandleWhoOpcode(WorldPackets::Who::WhoRequestPkt& whoRequest);
|
||||
void HandleLogoutRequestOpcode(WorldPacket& recvPacket);
|
||||
void HandlePlayerLogoutOpcode(WorldPacket& recvPacket);
|
||||
void HandleLogoutCancelOpcode(WorldPacket& recvPacket);
|
||||
|
||||
Reference in New Issue
Block a user