aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoschiwald <joschiwald.trinity@gmail.com>2015-02-05 20:18:32 +0100
committerjoschiwald <joschiwald.trinity@gmail.com>2015-02-05 20:18:32 +0100
commitbe6b1f52516be0feb2b64f3bdbe1899cf5576777 (patch)
treef3706f037ba8a0f9e0dcdfb2f56ccb08cc31bb65
parent0ac3a21d3331e5a65873e0c76dad7e64213d0536 (diff)
Core/Packets:
- updated who packets - fixed typos from previous commits
-rw-r--r--src/server/game/Entities/Player/Player.cpp1
-rw-r--r--src/server/game/Handlers/InspectHandler.cpp2
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp244
-rw-r--r--src/server/game/Handlers/QueryHandler.cpp24
-rw-r--r--src/server/game/Server/Packets/InspectPackets.h2
-rw-r--r--src/server/game/Server/Packets/ItemPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/QueryPackets.cpp91
-rw-r--r--src/server/game/Server/Packets/QueryPackets.h16
-rw-r--r--src/server/game/Server/Packets/TicketPackets.h11
-rw-r--r--src/server/game/Server/Packets/WhoPackets.cpp126
-rw-r--r--src/server/game/Server/Packets/WhoPackets.h116
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp9
-rw-r--r--src/server/game/Server/WorldSession.h10
-rw-r--r--src/server/game/World/World.cpp2
-rw-r--r--src/server/worldserver/worldserver.conf.dist4
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