aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.h1
-rw-r--r--src/server/game/Entities/Player/Player.cpp24
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp49
-rw-r--r--src/server/game/Server/Packets/ItemPackets.cpp76
-rw-r--r--src/server/game/Server/Packets/ItemPackets.h79
-rw-r--r--src/server/game/Server/Packets/PacketUtilities.h19
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp6
-rw-r--r--src/server/game/Server/Protocol/Opcodes.h2
-rw-r--r--src/server/game/Server/WorldSession.h3
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);