aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-06-14 21:28:48 +0200
committerShauren <shauren.trinity@gmail.com>2016-06-14 21:28:48 +0200
commit27e08e48e117a3c31e3d45d8bfe5d307d93ebc81 (patch)
tree5674e82092b08796214e6ce7f8cf48f90a4629b5
parentd2733eb6f1f9a550ec6511b5fa696b67b11044b3 (diff)
Core/PacketIO: Updated AH and mail packets
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp48
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.h21
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp4
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp32
-rw-r--r--src/server/game/Server/Packets/AuctionHousePackets.cpp75
-rw-r--r--src/server/game/Server/Packets/AuctionHousePackets.h31
-rw-r--r--src/server/game/Server/Packets/ItemPackets.cpp34
-rw-r--r--src/server/game/Server/Packets/ItemPackets.h8
-rw-r--r--src/server/game/Server/Packets/MailPackets.cpp56
-rw-r--r--src/server/game/Server/Packets/MailPackets.h8
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp26
12 files changed, 234 insertions, 111 deletions
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index 3b3be37b0b3..190ee4d49d8 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -660,8 +660,7 @@ void AuctionHouseObject::BuildListOwnerItems(WorldPackets::AuctionHouse::Auction
}
void AuctionHouseObject::BuildListAuctionItems(WorldPackets::AuctionHouse::AuctionListItemsResult& packet, Player* player,
- std::wstring const& wsearchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
- uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32& totalcount)
+ std::wstring const& searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, bool usable, Optional<AuctionSearchFilters> const& filters, uint32 quality)
{
time_t curTime = sWorld->GetGameTime();
@@ -677,15 +676,24 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPackets::AuctionHouse::Aucti
continue;
ItemTemplate const* proto = item->GetTemplate();
+ if (filters)
+ {
+ // if we dont want any class filters, Optional is not initialized
+ // if we dont want this class included, SubclassMask is set to FILTER_SKIP_CLASS
+ // if we want this class and did not specify and subclasses, its set to FILTER_SKIP_SUBCLASS
+ // otherwise full restrictions apply
+ if (filters->Classes[proto->GetClass()].SubclassMask == AuctionSearchFilters::FILTER_SKIP_CLASS)
+ continue;
- if (itemClass != 0xffffffff && proto->GetClass() != itemClass)
- continue;
-
- if (itemSubClass != 0xffffffff && proto->GetSubClass() != itemSubClass)
- continue;
+ if (filters->Classes[proto->GetClass()].SubclassMask != AuctionSearchFilters::FILTER_SKIP_SUBCLASS)
+ {
+ if (!(filters->Classes[proto->GetClass()].SubclassMask & (1 << proto->GetSubClass())))
+ continue;
- if (inventoryType != 0xffffffff && proto->GetInventoryType() != InventoryType(inventoryType))
- continue;
+ if (!(filters->Classes[proto->GetClass()].InvTypes[proto->GetSubClass()] & (1 << proto->GetInventoryType())))
+ continue;
+ }
+ }
if (quality != 0xffffffff && proto->GetQuality() != quality)
continue;
@@ -693,12 +701,12 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPackets::AuctionHouse::Aucti
if (levelmin != 0 && (proto->GetBaseRequiredLevel() < levelmin || (levelmax != 0 && proto->GetBaseRequiredLevel() > levelmax)))
continue;
- if (usable != 0 && player->CanUseItem(item) != EQUIP_ERR_OK)
+ if (usable && player->CanUseItem(item) != EQUIP_ERR_OK)
continue;
// Allow search by suffix (ie: of the Monkey) or partial name (ie: Monkey)
// No need to do any of this if no search term was entered
- if (!wsearchedname.empty())
+ if (!searchedname.empty())
{
std::string name = proto->GetName(player->GetSession()->GetSessionDbcLocale());
if (name.empty())
@@ -741,15 +749,15 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPackets::AuctionHouse::Aucti
}
// Perform the search (with or without suffix)
- if (!Utf8FitTo(name, wsearchedname))
+ if (!Utf8FitTo(name, searchedname))
continue;
}
// Add the item if no search term or if entered search term was found
- if (packet.Items.size() < 50 && totalcount >= listfrom)
+ if (packet.Items.size() < 50 && packet.TotalCount >= listfrom)
Aentry->BuildAuctionInfo(packet.Items, true, item);
- ++totalcount;
+ ++packet.TotalCount;
}
}
@@ -837,6 +845,18 @@ void AuctionEntry::BuildAuctionInfo(std::vector<WorldPackets::AuctionHouse::Auct
auctionItem.Enchantments.emplace_back(item->GetEnchantmentId((EnchantmentSlot) i), item->GetEnchantmentDuration((EnchantmentSlot) i), item->GetEnchantmentCharges((EnchantmentSlot) i), i);
}
+ for (std::size_t i = 0; i < item->GetDynamicValues(ITEM_DYNAMIC_FIELD_GEMS).size(); ++i)
+ {
+ uint32 gemItemId = item->GetDynamicValue(ITEM_DYNAMIC_FIELD_GEMS, i);
+ if (!gemItemId)
+ continue;
+
+ WorldPackets::Item::ItemGemInstanceData gem;
+ gem.Slot = i;
+ gem.Item.ItemID = gemItemId;
+ auctionItem.Gems.push_back(gem);
+ }
+
items.emplace_back(auctionItem);
}
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h
index 233459de97b..3b8862b05c7 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.h
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h
@@ -96,6 +96,24 @@ struct TC_GAME_API AuctionEntry
};
+struct AuctionSearchFilters
+{
+ enum FilterType : uint32
+ {
+ FILTER_SKIP_CLASS = 0,
+ FILTER_SKIP_SUBCLASS = 0xFFFFFFFF,
+ FILTER_SKIP_INVTYPE = 0xFFFFFFFF
+ };
+
+ struct SubclassFilter
+ {
+ uint32 SubclassMask = FILTER_SKIP_CLASS;
+ std::array<uint32, MAX_ITEM_SUBCLASS_TOTAL> InvTypes;
+ };
+
+ std::array<SubclassFilter, MAX_ITEM_CLASS> Classes;
+};
+
//this class is used as auctionhouse instance
class TC_GAME_API AuctionHouseObject
{
@@ -140,8 +158,7 @@ class TC_GAME_API AuctionHouseObject
void BuildListBidderItems(WorldPackets::AuctionHouse::AuctionListBidderItemsResult& packet, Player* player, uint32& totalcount);
void BuildListOwnerItems(WorldPackets::AuctionHouse::AuctionListOwnerItemsResult& packet, Player* player, uint32& totalcount);
void BuildListAuctionItems(WorldPackets::AuctionHouse::AuctionListItemsResult& packet, Player* player,
- std::wstring const& searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
- uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32& totalcount);
+ std::wstring const& searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, bool usable, Optional<AuctionSearchFilters> const& filters, uint32 quality);
void BuildReplicate(WorldPackets::AuctionHouse::AuctionReplicateResponse& auctionReplicateResult, Player* player,
uint32 global, uint32 cursor, uint32 tombstone, uint32 count);
diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h
index 5fa6b5583af..fdc65af1cee 100644
--- a/src/server/game/Entities/Item/ItemTemplate.h
+++ b/src/server/game/Entities/Item/ItemTemplate.h
@@ -653,6 +653,8 @@ const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] =
MAX_ITEM_SUBCLASS_GLYPH
};
+#define MAX_ITEM_SUBCLASS_TOTAL 21
+
#define MIN_ITEM_LEVEL 1
#define MAX_ITEM_LEVEL 1000
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index c35e9bc99ca..b3f23d79221 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -17262,7 +17262,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
Field* fields = result->Fetch();
if (Item* item = _LoadItem(trans, zoneId, timeDiff, fields))
{
- ObjectGuid bagGuid = fields[21].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[24].GetUInt64()) : ObjectGuid::Empty;
+ ObjectGuid bagGuid = fields[24].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[24].GetUInt64()) : ObjectGuid::Empty;
uint8 slot = fields[25].GetUInt8();
GetSession()->GetCollectionMgr()->CheckHeirloomUpgrades(item);
@@ -17591,7 +17591,7 @@ void Player::_LoadMailedItems(Mail* mail)
Item* item = NewItemOrBag(proto);
- ObjectGuid ownerGuid = fields[21].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[21].GetUInt64()) : ObjectGuid::Empty;
+ ObjectGuid ownerGuid = fields[24].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[24].GetUInt64()) : ObjectGuid::Empty;
if (!item->LoadFromDB(itemGuid, ownerGuid, fields, itemEntry))
{
TC_LOG_ERROR("entities.player", "Player::_LoadMailedItems: Item (GUID: " UI64FMTD ") in mail (%u) doesn't exist, deleted from mail.", itemGuid, mail->messageID);
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index 1fa50f1493e..a4e9c995b4d 100644
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -616,10 +616,8 @@ void WorldSession::HandleAuctionListItems(WorldPackets::AuctionHouse::AuctionLis
AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction());
- TC_LOG_DEBUG("auctionHouse", "Auctionhouse search (%s), searchedname: %s, levelmin: %u, levelmax: %u, auctionSlotID: %u, auctionMainCategory: %u, auctionSubCategory: %u, quality: %u, usable: %u",
- packet.Auctioneer.ToString().c_str(), packet.Name.c_str(), packet.MinLevel, packet.MaxLevel , packet.InvType, packet.ItemClass, packet.ItemSubclass, packet.Quality, packet.OnlyUsable);
-
- WorldPackets::AuctionHouse::AuctionListItemsResult result;
+ TC_LOG_DEBUG("auctionHouse", "Auctionhouse search (%s), searchedname: %s, levelmin: %u, levelmax: %u, quality: %u, usable: %u",
+ packet.Auctioneer.ToString().c_str(), packet.Name.c_str(), packet.MinLevel, packet.MaxLevel , packet.Quality, packet.OnlyUsable);
// converting string that we try to find to lower case
std::wstring wsearchedname;
@@ -628,9 +626,29 @@ void WorldSession::HandleAuctionListItems(WorldPackets::AuctionHouse::AuctionLis
wstrToLower(wsearchedname);
- auctionHouse->BuildListAuctionItems(result, _player,
- wsearchedname, packet.Offset, packet.MinLevel, packet.MaxLevel, packet.OnlyUsable,
- packet.InvType, packet.ItemClass, packet.ItemSubclass, packet.Quality, result.TotalCount);
+ Optional<AuctionSearchFilters> filters;
+
+ WorldPackets::AuctionHouse::AuctionListItemsResult result;
+ if (packet.ClassFilters.empty())
+ {
+ filters = boost::in_place();
+
+ for (auto const& classFilter : packet.ClassFilters)
+ {
+ if (!classFilter.SubClassFilters.empty())
+ {
+ for (auto const& subClassFilter : classFilter.SubClassFilters)
+ {
+ filters->Classes[classFilter.ItemClass].SubclassMask |= 1 << subClassFilter.ItemSubclass;
+ filters->Classes[classFilter.ItemClass].InvTypes[subClassFilter.ItemSubclass] = subClassFilter.InvTypeMask;
+ }
+ }
+ else
+ filters->Classes[classFilter.ItemClass].SubclassMask = AuctionSearchFilters::FILTER_SKIP_SUBCLASS;
+ }
+ }
+
+ auctionHouse->BuildListAuctionItems(result, _player, wsearchedname, packet.Offset, packet.MinLevel, packet.MaxLevel, packet.OnlyUsable, filters, packet.Quality);
result.DesiredDelay = sWorld->getIntConfig(CONFIG_AUCTION_SEARCH_DELAY);
result.OnlyUsable = packet.OnlyUsable;
diff --git a/src/server/game/Server/Packets/AuctionHousePackets.cpp b/src/server/game/Server/Packets/AuctionHousePackets.cpp
index 143ba11ddca..6bff90b10ae 100644
--- a/src/server/game/Server/Packets/AuctionHousePackets.cpp
+++ b/src/server/game/Server/Packets/AuctionHousePackets.cpp
@@ -24,7 +24,6 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::AuctionHouse::AuctionItem
data << auctionItem.Item; // ItemInstance
data << int32(auctionItem.Count);
data << int32(auctionItem.Charges);
- data << int32(auctionItem.Enchantments.size());
data << int32(auctionItem.Flags);
data << int32(auctionItem.AuctionItemID);
data << auctionItem.Owner;
@@ -33,8 +32,16 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::AuctionHouse::AuctionItem
data << uint64(auctionItem.BuyoutPrice);
data << int32(auctionItem.DurationLeft);
data << uint8(auctionItem.DeleteReason);
+ data.WriteBits(auctionItem.Enchantments.size(), 4);
+ data.WriteBits(auctionItem.Gems.size(), 2);
+ data.WriteBit(auctionItem.CensorServerSideInfo);
+ data.WriteBit(auctionItem.CensorBidInfo);
+ data.FlushBits();
+
+ for (auto const& gem : auctionItem.Gems)
+ data << gem;
- for (auto const& enchant : auctionItem.Enchantments)
+ for (WorldPackets::AuctionHouse::AuctionItem::AuctionItemEnchant const& enchant : auctionItem.Enchantments)
{
data << int32(enchant.ID);
data << uint32(enchant.Expiration);
@@ -42,19 +49,14 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::AuctionHouse::AuctionItem
data << uint8(enchant.Slot);
}
- data.FlushBits();
-
- bool censorServerSideInfo = !data.WriteBit(auctionItem.CensorServerSideInfo);
- bool censorBidInfo = !data.WriteBit(auctionItem.CensorBidInfo);
-
- if (censorServerSideInfo)
+ if (!auctionItem.CensorServerSideInfo)
{
data << auctionItem.ItemGuid;
data << auctionItem.OwnerAccountID;
data << int32(auctionItem.EndTime);
}
- if (censorBidInfo)
+ if (!auctionItem.CensorBidInfo)
{
data << auctionItem.Bidder;
data << uint64(auctionItem.BidAmount);
@@ -195,14 +197,12 @@ WorldPacket const* WorldPackets::AuctionHouse::AuctionListItemsResult::Write()
_worldPacket << int32(Items.size());
_worldPacket << int32(TotalCount);
_worldPacket << int32(DesiredDelay);
-
- for (auto const& item : Items)
- _worldPacket << item;
-
- _worldPacket.FlushBits();
_worldPacket.WriteBit(OnlyUsable);
_worldPacket.FlushBits();
+ for (AuctionItem const& item : Items)
+ _worldPacket << item;
+
return &_worldPacket;
}
@@ -212,7 +212,7 @@ WorldPacket const* WorldPackets::AuctionHouse::AuctionListOwnerItemsResult::Writ
_worldPacket << uint32(TotalCount);
_worldPacket << uint32(DesiredDelay);
- for (auto const& item : Items)
+ for (AuctionItem const& item : Items)
_worldPacket << item;
return &_worldPacket;
@@ -224,7 +224,7 @@ WorldPacket const* WorldPackets::AuctionHouse::AuctionListBidderItemsResult::Wri
_worldPacket << uint32(TotalCount);
_worldPacket << uint32(DesiredDelay);
- for (auto const& item : Items)
+ for (AuctionItem const& item : Items)
_worldPacket << item;
return &_worldPacket;
@@ -236,25 +236,36 @@ void WorldPackets::AuctionHouse::AuctionListItems::Read()
_worldPacket >> Auctioneer;
_worldPacket >> MinLevel;
_worldPacket >> MaxLevel;
- _worldPacket >> InvType;
- _worldPacket >> ItemClass;
- _worldPacket >> ItemSubclass;
_worldPacket >> Quality;
_worldPacket >> SortCount;
+ KnownPets.resize(_worldPacket.read<uint32>());
+ _worldPacket >> MaxPetLevel;
+ for (std::size_t i = 0; i < KnownPets.size(); ++i)
+ _worldPacket >> KnownPets[i];
- _worldPacket.FlushBits();
- uint32 nameLength = _worldPacket.ReadBits(8);
- Name = _worldPacket.ReadString(nameLength);
+ Name = _worldPacket.ReadString(_worldPacket.ReadBits(8));
+ ClassFilters.resize(_worldPacket.ReadBits(3));
OnlyUsable = _worldPacket.ReadBit();
ExactMatch = _worldPacket.ReadBit();
+ for (ClassFilter& classFilter : ClassFilters)
+ {
+ _worldPacket >> classFilter.ItemClass;
+ classFilter.SubClassFilters.resize(_worldPacket.ReadBits(5));
+ for (ClassFilter::SubClassFilter& subclassFilter : classFilter.SubClassFilters)
+ {
+ _worldPacket >> subclassFilter.ItemSubclass;
+ _worldPacket >> subclassFilter.InvTypeMask;
+ }
+ }
+
_worldPacket.read_skip<uint32>(); // DataSize = (SortCount * 2)
for (int32 i = 0; i < SortCount; i++)
{
WorldPackets::AuctionHouse::AuctionListItems::Sort sort;
- _worldPacket >> sort.UnkByte1;
- _worldPacket >> sort.UnkByte2;
- DataSort.emplace_back(sort);
+ _worldPacket >> sort.Type;
+ _worldPacket >> sort.Direction;
+ DataSort.push_back(sort);
}
}
@@ -266,7 +277,7 @@ void WorldPackets::AuctionHouse::AuctionListOwnerItems::Read()
WorldPacket const* WorldPackets::AuctionHouse::AuctionListPendingSalesResult::Write()
{
- _worldPacket << int32(Mails.size());
+ _worldPacket << uint32(Mails.size());
_worldPacket << int32(TotalNumRecords);
for (auto const& mail : Mails)
@@ -312,12 +323,12 @@ WorldPacket const* WorldPackets::AuctionHouse::AuctionOutBidNotification::Write(
WorldPacket const* WorldPackets::AuctionHouse::AuctionReplicateResponse::Write()
{
- _worldPacket << int32(Result);
- _worldPacket << int32(DesiredDelay);
- _worldPacket << int32(ChangeNumberGlobal);
- _worldPacket << int32(ChangeNumberCursor);
- _worldPacket << int32(ChangeNumberTombstone);
- _worldPacket << int32(Items.size());
+ _worldPacket << uint32(Result);
+ _worldPacket << uint32(DesiredDelay);
+ _worldPacket << uint32(ChangeNumberGlobal);
+ _worldPacket << uint32(ChangeNumberCursor);
+ _worldPacket << uint32(ChangeNumberTombstone);
+ _worldPacket << uint32(Items.size());
for (auto const& item : Items)
_worldPacket << item;
diff --git a/src/server/game/Server/Packets/AuctionHousePackets.h b/src/server/game/Server/Packets/AuctionHousePackets.h
index e6aa6faac16..8ea9615e301 100644
--- a/src/server/game/Server/Packets/AuctionHousePackets.h
+++ b/src/server/game/Server/Packets/AuctionHousePackets.h
@@ -59,6 +59,7 @@ namespace WorldPackets
uint32 EndTime = 0;
ObjectGuid Bidder;
uint64 BidAmount = 0;
+ std::vector<Item::ItemGemInstanceData> Gems;
};
struct AuctionOwnerNotification
@@ -254,25 +255,37 @@ namespace WorldPackets
public:
struct Sort
{
- uint8 UnkByte1 = 0;
- uint8 UnkByte2 = 0;
+ uint8 Type = 0;
+ uint8 Direction = 0;
+ };
+
+ struct ClassFilter
+ {
+ struct SubClassFilter
+ {
+ int32 ItemSubclass;
+ uint32 InvTypeMask;
+ };
+
+ int32 ItemClass;
+ Array<SubClassFilter, 31> SubClassFilters;
};
AuctionListItems(WorldPacket&& packet) : ClientPacket(CMSG_AUCTION_LIST_ITEMS, std::move(packet)) { }
void Read() override;
- ObjectGuid Auctioneer;
- uint8 SortCount = 0;
- uint8 MaxLevel = 100;
uint32 Offset = 0;
- int32 ItemClass = 0;
+ ObjectGuid Auctioneer;
uint8 MinLevel = 1;
- int32 InvType = 0;
+ uint8 MaxLevel = 100;
int32 Quality = 0;
- int32 ItemSubclass = 0;
- bool ExactMatch = true;
+ uint8 SortCount = 0;
+ Array<uint8> KnownPets;
+ int8 MaxPetLevel;
std::string Name;
+ Array<ClassFilter, 7> ClassFilters;
+ bool ExactMatch = true;
bool OnlyUsable = false;
std::vector<Sort> DataSort;
};
diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp
index e627d80fdea..08648353635 100644
--- a/src/server/game/Server/Packets/ItemPackets.cpp
+++ b/src/server/game/Server/Packets/ItemPackets.cpp
@@ -165,7 +165,7 @@ WorldPacket const* WorldPackets::Item::SetProficiency::Write()
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemBonusInstanceData const& itemBonusInstanceData)
{
- data << itemBonusInstanceData.Context;
+ data << uint8(itemBonusInstanceData.Context);
data << uint32(itemBonusInstanceData.BonusListIDs.size());
for (uint32 bonusID : itemBonusInstanceData.BonusListIDs)
data << bonusID;
@@ -173,20 +173,18 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemBonusInstanceDa
return data;
}
-ByteBuffer& operator>>(ByteBuffer& data, Optional<WorldPackets::Item::ItemBonusInstanceData>& itemBonusInstanceData)
+ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Item::ItemBonusInstanceData& itemBonusInstanceData)
{
uint32 bonusListIdSize;
- itemBonusInstanceData = boost::in_place();
-
- data >> itemBonusInstanceData->Context;
+ data >> itemBonusInstanceData.Context;
data >> bonusListIdSize;
for (uint32 i = 0u; i < bonusListIdSize; ++i)
{
uint32 bonusId;
data >> bonusId;
- itemBonusInstanceData->BonusListIDs.push_back(bonusId);
+ itemBonusInstanceData.BonusListIDs.push_back(bonusId);
}
return data;
@@ -221,18 +219,34 @@ ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Item::ItemInstance& itemI
bool const hasModifications = data.ReadBit();
if (hasItemBonus)
- data >> itemInstance.ItemBonus;
+ {
+ itemInstance.ItemBonus = boost::in_place();
+ data >> *itemInstance.ItemBonus;
+ }
if (hasModifications)
{
- WorldPackets::CompactArray<int32> modifications;
- data >> modifications;
- itemInstance.Modifications = std::move(modifications);
+ itemInstance.Modifications = boost::in_place();
+ data >> *itemInstance.Modifications;
}
return data;
}
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemGemInstanceData const& itemGemInstanceData)
+{
+ data << uint8(itemGemInstanceData.Slot);
+ data << itemGemInstanceData.Item;
+ return data;
+}
+
+ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Item::ItemGemInstanceData& itemGemInstanceData)
+{
+ data >> itemGemInstanceData.Slot;
+ data >> itemGemInstanceData.Item;
+ return data;
+}
+
ByteBuffer& WorldPackets::Item::operator>>(ByteBuffer& data, InvUpdate& invUpdate)
{
invUpdate.Items.resize(data.ReadBits(2));
diff --git a/src/server/game/Server/Packets/ItemPackets.h b/src/server/game/Server/Packets/ItemPackets.h
index 833d1bd9261..7228efc5676 100644
--- a/src/server/game/Server/Packets/ItemPackets.h
+++ b/src/server/game/Server/Packets/ItemPackets.h
@@ -53,6 +53,12 @@ namespace WorldPackets
bool operator!=(ItemInstance const& r) const { return !(*this == r); }
};
+ struct ItemGemInstanceData
+ {
+ uint8 Slot;
+ ItemInstance Item;
+ };
+
class BuyBackItem final : public ClientPacket
{
public:
@@ -533,5 +539,7 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemBonusInstanceDa
ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Item::ItemBonusInstanceData& itemBonusInstanceData);
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemInstance const& itemInstance);
ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Item::ItemInstance& itemInstance);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemGemInstanceData const& itemGemInstanceData);
+ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Item::ItemGemInstanceData& itemGemInstanceData);
#endif // ItemPackets_h__
diff --git a/src/server/game/Server/Packets/MailPackets.cpp b/src/server/game/Server/Packets/MailPackets.cpp
index fc1c75dd2e1..12f48debe3d 100644
--- a/src/server/game/Server/Packets/MailPackets.cpp
+++ b/src/server/game/Server/Packets/MailPackets.cpp
@@ -33,32 +33,54 @@ WorldPackets::Mail::MailAttachedItem::MailAttachedItem(::Item const* item, uint8
for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; j++)
{
- Enchants[j].Enchant = item->GetEnchantmentId((EnchantmentSlot)j);
- Enchants[j].Duration = item->GetEnchantmentDuration((EnchantmentSlot)j);
- Enchants[j].Charges = item->GetEnchantmentCharges((EnchantmentSlot)j);
+ if (!item->GetEnchantmentId((EnchantmentSlot)j))
+ continue;
+
+ MailAttachedItemEnchant enchant;
+ enchant.Enchant = item->GetEnchantmentId((EnchantmentSlot)j);
+ enchant.Duration = item->GetEnchantmentDuration((EnchantmentSlot)j);
+ enchant.Charges = item->GetEnchantmentCharges((EnchantmentSlot)j);
+ enchant.Slot = j;
+ Enchants.push_back(enchant);
+ }
+
+ for (std::size_t i = 0; i < item->GetDynamicValues(ITEM_DYNAMIC_FIELD_GEMS).size(); ++i)
+ {
+ uint32 gemItemId = item->GetDynamicValue(ITEM_DYNAMIC_FIELD_GEMS, i);
+ if (!gemItemId)
+ continue;
+
+ Item::ItemGemInstanceData gem;
+ gem.Slot = i;
+ gem.Item.ItemID = gemItemId;
+ Gems.push_back(gem);
}
}
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Mail::MailAttachedItem const& att)
{
data << uint8(att.Position);
- data << uint32(att.AttachID);
+ data << int32(att.AttachID);
+ data << int32(att.Count);
+ data << int32(att.Charges);
+ data << uint32(att.MaxDurability);
+ data << int32(att.Durability);
data << att.Item;
+ data.WriteBits(att.Enchants.size(), 4);
+ data.WriteBits(att.Gems.size(), 2);
+ data.WriteBit(att.Unlocked);
+ data.FlushBits();
+
+ for (auto const& gem : att.Gems)
+ data << gem;
for (auto const& en : att.Enchants)
{
data << int32(en.Enchant);
- data << int32(en.Duration);
+ data << uint32(en.Duration);
data << int32(en.Charges);
}
- data << int32(att.Count);
- data << int32(att.Charges);
- data << int32(att.MaxDurability);
- data << int32(att.Durability);
- data.WriteBit(att.Unlocked);
- data.FlushBits();
-
return data;
}
@@ -100,26 +122,22 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Mail::MailListEntry const
{
data << int32(entry.MailID);
data << int8(entry.SenderType);
-
data << int64(entry.Cod);
data << int32(entry.StationeryID);
data << int64(entry.SentMoney);
data << int32(entry.Flags);
data << float(entry.DaysLeft);
data << int32(entry.MailTemplateID);
-
data << int32(entry.Attachments.size());
-
- for (auto const& att : entry.Attachments)
- data << att;
-
data.WriteBit(entry.SenderCharacter.is_initialized());
data.WriteBit(entry.AltSenderID.is_initialized());
-
data.WriteBits(entry.Subject.size(), 8);
data.WriteBits(entry.Body.size(), 13);
data.FlushBits();
+ for (auto const& att : entry.Attachments)
+ data << att;
+
if (entry.SenderCharacter)
data << *entry.SenderCharacter;
diff --git a/src/server/game/Server/Packets/MailPackets.h b/src/server/game/Server/Packets/MailPackets.h
index 927d8022c73..6a2928bb9a5 100644
--- a/src/server/game/Server/Packets/MailPackets.h
+++ b/src/server/game/Server/Packets/MailPackets.h
@@ -32,8 +32,9 @@ namespace WorldPackets
struct MailAttachedItemEnchant
{
int32 Enchant = 0;
- int32 Duration = 0;
+ uint32 Duration = 0;
int32 Charges = 0;
+ uint8 Slot = 0;
};
struct MailAttachedItem
@@ -45,10 +46,11 @@ namespace WorldPackets
Item::ItemInstance Item;
int32 Count = 0;
int32 Charges = 0;
- int32 MaxDurability = 0;
+ uint32 MaxDurability = 0;
int32 Durability = 0;
bool Unlocked = false;
- MailAttachedItemEnchant Enchants[8];
+ std::vector<MailAttachedItemEnchant> Enchants;
+ std::vector<Item::ItemGemInstanceData> Gems;
};
struct MailListEntry
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 1f9badfbdef..d03b3e6044b 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -138,7 +138,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_ATTACK_SWING, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Combat::AttackSwing, &WorldSession::HandleAttackSwingOpcode);
DEFINE_HANDLER(CMSG_AUCTION_HELLO_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::AuctionHouse::AuctionHelloRequest, &WorldSession::HandleAuctionHelloOpcode);
DEFINE_HANDLER(CMSG_AUCTION_LIST_BIDDER_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::AuctionHouse::AuctionListBidderItems, &WorldSession::HandleAuctionListBidderItems);
- DEFINE_HANDLER(CMSG_AUCTION_LIST_ITEMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::AuctionHouse::AuctionListItems, &WorldSession::HandleAuctionListItems);
+ DEFINE_HANDLER(CMSG_AUCTION_LIST_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::AuctionHouse::AuctionListItems, &WorldSession::HandleAuctionListItems);
DEFINE_HANDLER(CMSG_AUCTION_LIST_OWNER_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::AuctionHouse::AuctionListOwnerItems, &WorldSession::HandleAuctionListOwnerItems);
DEFINE_HANDLER(CMSG_AUCTION_LIST_PENDING_SALES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::AuctionHouse::AuctionListPendingSales, &WorldSession::HandleAuctionListPendingSales);
DEFINE_HANDLER(CMSG_AUCTION_PLACE_BID, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::AuctionHouse::AuctionPlaceBid, &WorldSession::HandleAuctionPlaceBid);
@@ -686,7 +686,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_SELL_WOW_TOKEN_CONFIRM, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SELL_WOW_TOKEN_START, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SEND_CONTACT_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Social::SendContactList, &WorldSession::HandleContactListOpcode);
- DEFINE_HANDLER(CMSG_SEND_MAIL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Mail::SendMail, &WorldSession::HandleSendMail);
+ DEFINE_HANDLER(CMSG_SEND_MAIL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::SendMail, &WorldSession::HandleSendMail);
DEFINE_HANDLER(CMSG_SEND_SOR_REQUEST_VIA_ADDRESS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SEND_TEXT_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::CTextEmote, &WorldSession::HandleTextEmoteOpcode);
DEFINE_HANDLER(CMSG_SET_ACHIEVEMENTS_HIDDEN, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -857,17 +857,17 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ATTACK_STOP, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ATTACK_SWING_ERROR, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ATTACK_SWING_LANDED_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_CLOSED_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_CLOSED_NOTIFICATION, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_COMMAND_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_HELLO_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_BIDDER_ITEMS_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_ITEMS_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_OWNER_ITEMS_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_PENDING_SALES_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_OUTBID_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_OWNER_BID_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_REPLICATE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_WON_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_BIDDER_ITEMS_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_ITEMS_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_OWNER_ITEMS_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_PENDING_SALES_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_OUTBID_NOTIFICATION, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_OWNER_BID_NOTIFICATION, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_REPLICATE_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_WON_NOTIFICATION, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AURA_POINTS_DEPLETED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AURA_UPDATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUTH_CHALLENGE, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -1318,7 +1318,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOOT_ROLL_WON, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOSS_OF_CONTROL_AURA_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAIL_COMMAND_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAIL_LIST_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAIL_LIST_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAIL_QUERY_NEXT_TIME_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAP_OBJECTIVES_INIT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAP_OBJ_EVENTS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1573,7 +1573,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_RANGED_COMBAT_TIMER, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_WEEKLY_CURRENCY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESPEC_WIPE_CONFIRM, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_CAST_BAR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_COMMS, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_TOKEN, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);