diff options
author | Shauren <shauren.trinity@gmail.com> | 2016-06-14 21:28:48 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-06-14 21:28:48 +0200 |
commit | 27e08e48e117a3c31e3d45d8bfe5d307d93ebc81 (patch) | |
tree | 5674e82092b08796214e6ce7f8cf48f90a4629b5 | |
parent | d2733eb6f1f9a550ec6511b5fa696b67b11044b3 (diff) |
Core/PacketIO: Updated AH and mail packets
-rw-r--r-- | src/server/game/AuctionHouse/AuctionHouseMgr.cpp | 48 | ||||
-rw-r--r-- | src/server/game/AuctionHouse/AuctionHouseMgr.h | 21 | ||||
-rw-r--r-- | src/server/game/Entities/Item/ItemTemplate.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Handlers/AuctionHouseHandler.cpp | 32 | ||||
-rw-r--r-- | src/server/game/Server/Packets/AuctionHousePackets.cpp | 75 | ||||
-rw-r--r-- | src/server/game/Server/Packets/AuctionHousePackets.h | 31 | ||||
-rw-r--r-- | src/server/game/Server/Packets/ItemPackets.cpp | 34 | ||||
-rw-r--r-- | src/server/game/Server/Packets/ItemPackets.h | 8 | ||||
-rw-r--r-- | src/server/game/Server/Packets/MailPackets.cpp | 56 | ||||
-rw-r--r-- | src/server/game/Server/Packets/MailPackets.h | 8 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 26 |
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); |