diff options
-rw-r--r-- | src/server/game/Entities/Item/ItemTemplate.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 24 | ||||
-rw-r--r-- | src/server/game/Handlers/ItemHandler.cpp | 49 | ||||
-rw-r--r-- | src/server/game/Server/Packets/ItemPackets.cpp | 76 | ||||
-rw-r--r-- | src/server/game/Server/Packets/ItemPackets.h | 79 | ||||
-rw-r--r-- | src/server/game/Server/Packets/PacketUtilities.h | 19 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 6 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.h | 2 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 3 |
9 files changed, 196 insertions, 63 deletions
diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h index 73536d3e5e2..0a089a09b15 100644 --- a/src/server/game/Entities/Item/ItemTemplate.h +++ b/src/server/game/Entities/Item/ItemTemplate.h @@ -230,6 +230,7 @@ enum CurrencyCategory enum ItemVendorType { + ITEM_VENDOR_TYPE_NONE = 0, ITEM_VENDOR_TYPE_ITEM = 1, ITEM_VENDOR_TYPE_CURRENCY = 2, }; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 361c651e882..ee6a407fbbe 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -12997,12 +12997,11 @@ void Player::SendEquipError(InventoryResult msg, Item* item1 /*= nullptr*/, Item void Player::SendBuyError(BuyResult msg, Creature* creature, uint32 item, uint32 /*param*/) { - TC_LOG_DEBUG("network", "WORLD: Sent SMSG_BUY_FAILED"); - WorldPacket data(SMSG_BUY_FAILED, (8+4+4+1)); - data << (creature ? creature->GetGUID() : ObjectGuid::Empty); - data << uint32(item); - data << uint8(msg); - GetSession()->SendPacket(&data); + WorldPackets::Item::BuyFailed packet; + packet.VendorGUID = creature ? creature->GetGUID() : ObjectGuid::Empty; + packet.Muid = item; + packet.Reason = msg; + GetSession()->SendPacket(packet.Write()); } void Player::SendSellError(SellResult msg, Creature* creature, ObjectGuid guid) @@ -21358,12 +21357,13 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c { uint32 new_count = pVendor->UpdateVendorItemCurrentCount(crItem, count); - WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4)); - data << pVendor->GetGUID(); - data << uint32(vendorslot + 1); // numbered from 1 at client - data << int32(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF); - data << uint32(count); - GetSession()->SendPacket(&data); + WorldPackets::Item::BuySucceeded packet; + packet.VendorGUID = pVendor->GetGUID(); + packet.Muid = vendorslot + 1; + packet.NewQuantity = crItem->maxcount > 0 ? new_count : 0xFFFFFFFF; + packet.QuantityBought = count; + GetSession()->SendPacket(packet.Write()); + SendNewItem(it, count, true, false, false); if (!bStore) diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index 87f98e232bb..c1d29f46fba 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -529,38 +529,41 @@ void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket& recvData) GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, bag, bagslot); } -void WorldSession::HandleBuyItemOpcode(WorldPacket& recvData) +void WorldSession::HandleBuyItemOpcode(WorldPackets::Item::BuyItem& packet) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_BUY_ITEM"); - ObjectGuid vendorguid, bagGuid; - uint32 item, slot, count; - uint8 itemType; // 1 = item, 2 = currency - uint8 bagSlot; - - recvData >> vendorguid >> itemType >> item >> slot >> count >> bagGuid >> bagSlot; - // client expects count starting at 1, and we send vendorslot+1 to client already - if (slot > 0) - --slot; + if (packet.Muid > 0) + --packet.Muid; else return; // cheating - if (itemType == ITEM_VENDOR_TYPE_ITEM) + switch (packet.ItemType) { - Item* bagItem = _player->GetItemByGuid(bagGuid); + case ITEM_VENDOR_TYPE_ITEM: + { + Item* bagItem = _player->GetItemByGuid(packet.ContainerGUID); - uint8 bag = NULL_BAG; - if (bagItem && bagItem->IsBag()) - bag = bagItem->GetSlot(); - else if (bagGuid == GetPlayer()->GetGUID()) // The client sends the player guid when trying to store an item in the default backpack - bag = INVENTORY_SLOT_BAG_0; + uint8 bag = NULL_BAG; + if (bagItem && bagItem->IsBag()) + bag = bagItem->GetSlot(); + else if (packet.ContainerGUID == GetPlayer()->GetGUID()) // The client sends the player guid when trying to store an item in the default backpack + bag = INVENTORY_SLOT_BAG_0; - GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, bag, bagSlot); + GetPlayer()->BuyItemFromVendorSlot(packet.VendorGUID, packet.Muid, packet.Item.ItemID, + packet.Quantity, bag, packet.Slot); + break; + } + case ITEM_VENDOR_TYPE_CURRENCY: + { + GetPlayer()->BuyCurrencyFromVendorSlot(packet.VendorGUID, packet.Muid, packet.Item.ItemID, packet.Quantity); + break; + } + default: + { + TC_LOG_DEBUG("network", "WORLD: received wrong itemType (%u) in HandleBuyItemOpcode", packet.ItemType); + break; + } } - else if (itemType == ITEM_VENDOR_TYPE_CURRENCY) - GetPlayer()->BuyCurrencyFromVendorSlot(vendorguid, slot, item, count); - else - TC_LOG_DEBUG("network", "WORLD: received wrong itemType (%u) in HandleBuyItemOpcode", itemType); } void WorldSession::HandleListInventoryOpcode(WorldPackets::NPC::Hello& packet) diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp index 8456c68ee67..dbc7ba2615a 100644 --- a/src/server/game/Server/Packets/ItemPackets.cpp +++ b/src/server/game/Server/Packets/ItemPackets.cpp @@ -19,8 +19,39 @@ void WorldPackets::Item::BuyBackItem::Read() { - _worldPacket >> VendorGUID; - _worldPacket >> Slot; + _worldPacket >> VendorGUID + >> Slot; +} + +void WorldPackets::Item::BuyItem::Read() +{ + _worldPacket >> VendorGUID + >> ContainerGUID + >> Item + >> Quantity + >> Muid + >> Slot; + + ItemType = static_cast<ItemVendorType>(_worldPacket.ReadBits(2)); +} + +WorldPacket const* WorldPackets::Item::BuySucceeded::Write() +{ + _worldPacket << VendorGUID + << uint32(Muid) + << int32(NewQuantity) + << uint32(QuantityBought); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Item::BuyFailed::Write() +{ + _worldPacket << VendorGUID + << uint32(Muid) + << uint8(Reason); + + return &_worldPacket; } void WorldPackets::Item::GetItemPurchaseData::Read() @@ -68,11 +99,28 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemBonusInstanceDa return data; } +ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Item::ItemBonusInstanceData& itemBonusInstanceData) +{ + uint32 bonusListIdSize; + + data >> itemBonusInstanceData.Context; + data >> bonusListIdSize; + + for (uint32 i = 0u; i < bonusListIdSize; ++i) + { + uint32 bonusId; + data >> bonusId; + itemBonusInstanceData.BonusListIDs.push_back(bonusId); + } + + return data; +} + ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemInstance const& itemInstance) { - data << itemInstance.ItemID; - data << itemInstance.RandomPropertiesSeed; - data << itemInstance.RandomPropertiesID; + data << int32(itemInstance.ItemID); + data << int32(itemInstance.RandomPropertiesSeed); + data << int32(itemInstance.RandomPropertiesID); data.WriteBit(itemInstance.ItemBonus.HasValue); data.WriteBit(itemInstance.Modifications.HasValue); @@ -87,6 +135,24 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemInstance const& return data; } +ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Item::ItemInstance& itemInstance) +{ + data >> itemInstance.ItemID; + data >> itemInstance.RandomPropertiesSeed; + data >> itemInstance.RandomPropertiesID; + + itemInstance.ItemBonus.HasValue = data.ReadBit(); + itemInstance.Modifications.HasValue = data.ReadBit(); + + if (itemInstance.ItemBonus.HasValue) + data >> itemInstance.ItemBonus.Value; + + if (itemInstance.Modifications.HasValue) + data >> itemInstance.Modifications.Value; + + 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 65fdcdf3367..1645af8275a 100644 --- a/src/server/game/Server/Packets/ItemPackets.h +++ b/src/server/game/Server/Packets/ItemPackets.h @@ -26,6 +26,24 @@ namespace WorldPackets { namespace Item { + struct ItemBonusInstanceData + { + uint8 Context = 0; + std::vector<int32> BonusListIDs; + }; + + struct ItemInstance + { + void Initalize(::Item const* item); + void Initalize(::LootItem const& lootItem); + + uint32 ItemID = 0; + uint32 RandomPropertiesSeed = 0; + uint32 RandomPropertiesID = 0; + Optional<ItemBonusInstanceData> ItemBonus; + Optional<CompactArray<int32>> Modifications; + }; + class BuyBackItem final : public ClientPacket { public: @@ -37,6 +55,47 @@ namespace WorldPackets uint32 Slot = 0; }; + class BuyItem final : public ClientPacket + { + public: + BuyItem(WorldPacket&& packet) : ClientPacket(CMSG_BUY_ITEM, std::move(packet)) { } + + void Read() override; + + ObjectGuid VendorGUID; + ItemInstance Item; + uint32 Muid = 0u; + uint32 Slot = 0u; + ItemVendorType ItemType = ITEM_VENDOR_TYPE_NONE; + int32 Quantity = 0; + ObjectGuid ContainerGUID; + }; + + class BuySucceeded final : ServerPacket + { + public: + BuySucceeded() : ServerPacket(SMSG_BUY_SUCCEEDED, 16 + 4 + 4 + 4 + 4) { } + + WorldPacket const* Write() override; + + ObjectGuid VendorGUID; + uint32 Muid = 0u; + uint32 QuantityBought = 0u; + int32 NewQuantity = 0; + }; + + class BuyFailed final : ServerPacket + { + public: + BuyFailed() : ServerPacket(SMSG_BUY_FAILED, 16 + 4 + 1) { } + + WorldPacket const* Write() override; + + ObjectGuid VendorGUID; + uint32 Muid = 0u; + BuyResult Reason = BUY_ERR_CANT_FIND_ITEM; + }; + class GetItemPurchaseData final : public ClientPacket { public: @@ -93,24 +152,6 @@ namespace WorldPackets uint8 ProficiencyClass = 0; }; - struct ItemBonusInstanceData - { - uint8 Context = 0; - std::vector<int32> BonusListIDs; - }; - - struct ItemInstance - { - void Initalize(::Item const* item); - void Initalize(::LootItem const& lootItem); - - uint32 ItemID = 0; - uint32 RandomPropertiesSeed = 0; - uint32 RandomPropertiesID = 0; - Optional<ItemBonusInstanceData> ItemBonus; - Optional<CompactArray<int32>> Modifications; - }; - struct InvUpdate { struct InvItem @@ -222,6 +263,8 @@ namespace WorldPackets } ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemBonusInstanceData const& itemBonusInstanceData); +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); #endif // ItemPackets_h__ diff --git a/src/server/game/Server/Packets/PacketUtilities.h b/src/server/game/Server/Packets/PacketUtilities.h index 25e6f27d1d4..6246b637a71 100644 --- a/src/server/game/Server/Packets/PacketUtilities.h +++ b/src/server/game/Server/Packets/PacketUtilities.h @@ -73,4 +73,23 @@ namespace WorldPackets return data; } + + template <typename T> + ByteBuffer& operator>>(ByteBuffer& data, CompactArray<T>& v) + { + uint32 mask; + data >> mask; + + for (size_t index = 0; mask != 0; mask >>= 1, ++index) + { + if ((mask & 1) != 0) + { + T value; + data >> value; + v.Insert(index, value); + } + } + + return data; + } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 00d136d9c76..e29624e90e6 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -229,7 +229,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_BUSY_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBusyTradeOpcode ); DEFINE_HANDLER(CMSG_BUY_BACK_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::BuyBackItem, &WorldSession::HandleBuybackItem); DEFINE_OPCODE_HANDLER_OLD(CMSG_BUY_BANK_SLOT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyBankSlotOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_BUY_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyItemOpcode ); + DEFINE_HANDLER(CMSG_BUY_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::BuyItem, &WorldSession::HandleBuyItemOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_CAGE_BATTLE_PET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CALENDAR_ADD_EVENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarAddEvent ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CALENDAR_ARENA_TEAM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarArenaTeam ); @@ -1056,8 +1056,8 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_BONUS_ROLL_EMPTY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BREAK_TARGET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BUY_BANK_SLOT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_BUY_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_BUY_ITEM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BUY_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BUY_SUCCEEDED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CALENDAR_ACTION_PENDING, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CALENDAR_ARENA_TEAM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CALENDAR_CLEAR_PENDING_ACTION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index 6dfa72cf46b..6666b38bfc2 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -958,7 +958,7 @@ enum OpcodeServer : uint32 SMSG_BREAK_TARGET = 0x11A2, SMSG_BUY_BANK_SLOT_RESULT = 0xBADD, SMSG_BUY_FAILED = 0x013A, - SMSG_BUY_ITEM = 0x0BD1, + SMSG_BUY_SUCCEEDED = 0x0BD1, SMSG_CALENDAR_ACTION_PENDING = 0xBADD, SMSG_CALENDAR_ARENA_TEAM = 0xBADD, SMSG_CALENDAR_CLEAR_PENDING_ACTION = 0x1E8A, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index d6bdc0f11fb..fe221d38a9e 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -180,6 +180,7 @@ namespace WorldPackets { class AutoEquipItem; class AutoStoreBagItem; + class BuyItem; class BuyBackItem; class DestroyItem; class GetItemPurchaseData; @@ -984,7 +985,7 @@ class WorldSession void HandleAutoEquipItemOpcode(WorldPackets::Item::AutoEquipItem& autoEquipItem); void HandleSellItemOpcode(WorldPackets::Item::SellItem& packet); void HandleBuyItemInSlotOpcode(WorldPacket& recvPacket); - void HandleBuyItemOpcode(WorldPacket& recvPacket); + void HandleBuyItemOpcode(WorldPackets::Item::BuyItem& packet); void HandleListInventoryOpcode(WorldPackets::NPC::Hello& packet); void HandleAutoStoreBagItemOpcode(WorldPackets::Item::AutoStoreBagItem& packet); void HandleReadItem(WorldPacket& recvPacket); |