Core/PacketIO: Updated AH and mail packets
This commit is contained in:
@@ -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 (filters->Classes[proto->GetClass()].SubclassMask != AuctionSearchFilters::FILTER_SKIP_SUBCLASS)
|
||||
{
|
||||
if (!(filters->Classes[proto->GetClass()].SubclassMask & (1 << proto->GetSubClass())))
|
||||
continue;
|
||||
|
||||
if (itemSubClass != 0xffffffff && proto->GetSubClass() != itemSubClass)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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& enchant : auctionItem.Enchantments)
|
||||
for (auto const& gem : auctionItem.Gems)
|
||||
data << gem;
|
||||
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user