Core/Packets: Fix and enable CMSG_BUY_ITEM, SMSG_BUY_FAILED and SMSG_BUY_SUCCEEDED
Closes #14127
This commit is contained in:
@@ -230,6 +230,7 @@ enum CurrencyCategory
|
||||
|
||||
enum ItemVendorType
|
||||
{
|
||||
ITEM_VENDOR_TYPE_NONE = 0,
|
||||
ITEM_VENDOR_TYPE_ITEM = 1,
|
||||
ITEM_VENDOR_TYPE_CURRENCY = 2,
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user