diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index b9e1181655..434ba79bcf 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -22,6 +22,7 @@ #include "DB2Stores.h" #include "DBCStores.h" #include "Item.h" +#include "ItemPackets.h" #include "Log.h" #include "NPCPackets.h" #include "ObjectMgr.h" @@ -1334,143 +1335,77 @@ void WorldSession::HandleItemTextQuery(WorldPacket& recvData ) SendPacket(&data); } -void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData) +void WorldSession::HandleTransmogrifyItems(WorldPackets::Item::TransmogrifyItems& transmogrifyItems) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_TRANSMOGRIFY_ITEMS"); Player* player = GetPlayer(); - // Read data - uint32 count = recvData.ReadBits(22); - - if (count >= EQUIPMENT_SLOT_END) + if (transmogrifyItems.Items.size() >= EQUIPMENT_SLOT_END) { - TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) sent a wrong count (%u) when transmogrifying items.", player->GetGUID().GetCounter(), player->GetName().c_str(), count); - recvData.rfinish(); + TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify more items than possible. Amount: (%u)", player->GetGUID().GetCounter(), player->GetName().c_str(), uint32(transmogrifyItems.Items.size())); return; } - std::vector itemGuids(count, ObjectGuid()); - std::vector newEntries(count, 0); - std::vector slots(count, 0); - - for (uint8 i = 0; i < count; ++i) - { - itemGuids[i][0] = recvData.ReadBit(); - itemGuids[i][5] = recvData.ReadBit(); - itemGuids[i][6] = recvData.ReadBit(); - itemGuids[i][2] = recvData.ReadBit(); - itemGuids[i][3] = recvData.ReadBit(); - itemGuids[i][7] = recvData.ReadBit(); - itemGuids[i][4] = recvData.ReadBit(); - itemGuids[i][1] = recvData.ReadBit(); - } - - ObjectGuid npcGuid; - npcGuid[7] = recvData.ReadBit(); - npcGuid[3] = recvData.ReadBit(); - npcGuid[5] = recvData.ReadBit(); - npcGuid[6] = recvData.ReadBit(); - npcGuid[1] = recvData.ReadBit(); - npcGuid[4] = recvData.ReadBit(); - npcGuid[0] = recvData.ReadBit(); - npcGuid[2] = recvData.ReadBit(); - - recvData.FlushBits(); - - for (uint32 i = 0; i < count; ++i) - { - recvData >> newEntries[i]; - - recvData.ReadByteSeq(itemGuids[i][1]); - recvData.ReadByteSeq(itemGuids[i][5]); - recvData.ReadByteSeq(itemGuids[i][0]); - recvData.ReadByteSeq(itemGuids[i][4]); - recvData.ReadByteSeq(itemGuids[i][6]); - recvData.ReadByteSeq(itemGuids[i][7]); - recvData.ReadByteSeq(itemGuids[i][3]); - recvData.ReadByteSeq(itemGuids[i][2]); - - recvData >> slots[i]; - } - - recvData.ReadByteSeq(npcGuid[7]); - recvData.ReadByteSeq(npcGuid[2]); - recvData.ReadByteSeq(npcGuid[5]); - recvData.ReadByteSeq(npcGuid[4]); - recvData.ReadByteSeq(npcGuid[3]); - recvData.ReadByteSeq(npcGuid[1]); - recvData.ReadByteSeq(npcGuid[6]); - recvData.ReadByteSeq(npcGuid[0]); - // Validate - - if (!player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_TRANSMOGRIFIER)) + if (!player->GetNPCIfCanInteractWith(transmogrifyItems.Npc, UNIT_NPC_FLAG_TRANSMOGRIFIER)) { - TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - %s not found or player can't interact with it.", npcGuid.ToString().c_str()); + TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - %s not found or player can't interact with it.", transmogrifyItems.Npc.ToString().c_str()); return; } int64 cost = 0; - std::vector transmogrifier(count, nullptr); - std::vector transmogrified(count, nullptr); - - for (uint8 i = 0; i < count; ++i) + for (WorldPackets::Item::TransmogrifyItem& item : transmogrifyItems.Items) { // slot of the transmogrified item - if (slots[i] >= EQUIPMENT_SLOT_END) + if (item.Slot >= EQUIPMENT_SLOT_END) { - TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify %s with a wrong slot (%u) when transmogrifying items.", player->GetGUID().GetCounter(), player->GetName().c_str(), itemGuids[i].ToString().c_str(), slots[i]); + TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify %s with a wrong slot (%u) when transmogrifying items.", player->GetGUID().GetCounter(), player->GetName().c_str(), item.SrcItemGUID.ToString().c_str(), item.Slot); return; } // transmogrified item - Item* itemTransmogrified = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slots[i]); - if (!itemTransmogrified) + Item* targetItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, item.Slot); + if (!targetItem) { - TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify an invalid item in a valid slot (slot: %u).", player->GetGUID().GetCounter(), player->GetName().c_str(), slots[i]); + TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify an invalid item in a valid slot (slot: %u).", player->GetGUID().GetCounter(), player->GetName().c_str(), item.Slot); return; } - // if not resetting look - Item* itemTransmogrifier = nullptr; - if (newEntries[i]) + // Applying the appearance of a different item onto another + if (item.ItemID) { // entry of the transmogrifier item - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(newEntries[i]); + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item.ItemID); if (!proto) { - TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify to an invalid item (entry: %u).", player->GetGUID().GetCounter(), player->GetName().c_str(), newEntries[i]); + TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify to an invalid item (entry: %u).", player->GetGUID().GetCounter(), player->GetName().c_str(), item.ItemID); return; } // guid of the transmogrifier item - itemTransmogrifier = player->GetItemByGuid(itemGuids[i]); - if (!itemTransmogrifier) + Item const* sourceItem = player->GetItemByGuid(item.SrcItemGUID); + if (!sourceItem) { - TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify with an invalid item (%s).", player->GetGUID().GetCounter(), player->GetName().c_str(), itemGuids[i].ToString().c_str()); + TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify with an invalid item (%s).", player->GetGUID().GetCounter(), player->GetName().c_str(), item.SrcItemGUID.ToString().c_str()); return; } // entry of transmogrifier and from packet - if (itemTransmogrifier->GetEntry() != newEntries[i]) + if (sourceItem->GetEntry() != item.ItemID) { - TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify with an invalid entry (entry: %u) for %s.", player->GetGUID().GetCounter(), player->GetName().c_str(), newEntries[i], itemGuids[i].ToString().c_str()); + TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify with an invalid entry (entry: %u) for %s.", player->GetGUID().GetCounter(), player->GetName().c_str(), item.ItemID, item.SrcItemGUID.ToString().c_str()); return; } // validity of the transmogrification items - if (!Item::CanTransmogrifyItemWithItem(itemTransmogrified, itemTransmogrifier)) + if (!Item::CanTransmogrifyItemWithItem(targetItem, sourceItem)) { - TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) failed CanTransmogrifyItemWithItem (%u with %u).", player->GetGUID().GetCounter(), player->GetName().c_str(), itemTransmogrified->GetEntry(), itemTransmogrifier->GetEntry()); + TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) failed CanTransmogrifyItemWithItem (%u with %u).", player->GetGUID().GetCounter(), player->GetName().c_str(), targetItem->GetEntry(), sourceItem->GetEntry()); return; } // add cost - cost += itemTransmogrified->GetSpecialPrice(); + cost += targetItem->GetSpecialPrice(); } - - transmogrifier[i] = itemTransmogrifier; - transmogrified[i] = itemTransmogrified; } if (cost) // 0 cost if reverting look @@ -1482,32 +1417,36 @@ void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData) // Everything is fine, proceed - for (uint8 i = 0; i < count; ++i) + for (WorldPackets::Item::TransmogrifyItem& item : transmogrifyItems.Items) { - if (transmogrifier[i]) + Item* targetItem = ASSERT_NOTNULL(player->GetItemByPos(INVENTORY_SLOT_BAG_0, item.Slot)); + + if (item.ItemID) { + Item* sourceitem = ASSERT_NOTNULL(player->GetItemByGuid(item.SrcItemGUID)); + // Transmogrify - transmogrified[i]->SetEnchantment(TRANSMOGRIFY_ENCHANTMENT_SLOT, newEntries[i], 0, 0); - player->SetVisibleItemSlot(slots[i], transmogrified[i]); + targetItem->SetEnchantment(TRANSMOGRIFY_ENCHANTMENT_SLOT, item.ItemID, 0, 0); + player->SetVisibleItemSlot(item.Slot, targetItem); - transmogrified[i]->UpdatePlayedTime(player); + targetItem->UpdatePlayedTime(player); - transmogrified[i]->SetOwnerGUID(player->GetGUID()); - transmogrified[i]->SetNotRefundable(player); - transmogrified[i]->ClearSoulboundTradeable(player); + targetItem->SetOwnerGUID(player->GetGUID()); + targetItem->SetNotRefundable(player); + targetItem->ClearSoulboundTradeable(player); - if (transmogrifier[i]->GetTemplate()->GetBonding() == BIND_ON_EQUIP || transmogrifier[i]->GetTemplate()->GetBonding() == BIND_ON_USE) - transmogrifier[i]->SetBinding(true); + if (sourceitem->GetTemplate()->GetBonding() == BIND_ON_EQUIP || sourceitem->GetTemplate()->GetBonding() == BIND_ON_USE) + sourceitem->SetBinding(true); - transmogrifier[i]->SetOwnerGUID(player->GetGUID()); - transmogrifier[i]->SetNotRefundable(player); - transmogrifier[i]->ClearSoulboundTradeable(player); + sourceitem->SetOwnerGUID(player->GetGUID()); + sourceitem->SetNotRefundable(player); + sourceitem->ClearSoulboundTradeable(player); } else { // Reset - transmogrified[i]->ClearEnchantment(TRANSMOGRIFY_ENCHANTMENT_SLOT); - player->SetVisibleItemSlot(slots[i], transmogrified[i]); + targetItem->ClearEnchantment(TRANSMOGRIFY_ENCHANTMENT_SLOT); + player->SetVisibleItemSlot(item.Slot, targetItem); } } } diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp index a39088fbd9..11109f86e1 100644 --- a/src/server/game/Server/Packets/ItemPackets.cpp +++ b/src/server/game/Server/Packets/ItemPackets.cpp @@ -24,3 +24,54 @@ WorldPacket const* WorldPackets::Item::SetProficiency::Write() return &_worldPacket; } + +void WorldPackets::Item::TransmogrifyItems::Read() +{ + Items.resize(_worldPacket.ReadBits(22)); + + for (TransmogrifyItem& item : Items) + { + item.SrcItemGUID[0] = _worldPacket.ReadBit(); + item.SrcItemGUID[5] = _worldPacket.ReadBit(); + item.SrcItemGUID[6] = _worldPacket.ReadBit(); + item.SrcItemGUID[2] = _worldPacket.ReadBit(); + item.SrcItemGUID[3] = _worldPacket.ReadBit(); + item.SrcItemGUID[7] = _worldPacket.ReadBit(); + item.SrcItemGUID[4] = _worldPacket.ReadBit(); + item.SrcItemGUID[1] = _worldPacket.ReadBit(); + } + + Npc[7] = _worldPacket.ReadBit(); + Npc[3] = _worldPacket.ReadBit(); + Npc[5] = _worldPacket.ReadBit(); + Npc[6] = _worldPacket.ReadBit(); + Npc[1] = _worldPacket.ReadBit(); + Npc[4] = _worldPacket.ReadBit(); + Npc[0] = _worldPacket.ReadBit(); + Npc[2] = _worldPacket.ReadBit(); + + for (TransmogrifyItem& item : Items) + { + _worldPacket >> item.ItemID; + + _worldPacket.ReadByteSeq(item.SrcItemGUID[1]); + _worldPacket.ReadByteSeq(item.SrcItemGUID[5]); + _worldPacket.ReadByteSeq(item.SrcItemGUID[0]); + _worldPacket.ReadByteSeq(item.SrcItemGUID[4]); + _worldPacket.ReadByteSeq(item.SrcItemGUID[6]); + _worldPacket.ReadByteSeq(item.SrcItemGUID[7]); + _worldPacket.ReadByteSeq(item.SrcItemGUID[3]); + _worldPacket.ReadByteSeq(item.SrcItemGUID[2]); + + _worldPacket >> item.Slot; + } + + _worldPacket.ReadByteSeq(Npc[7]); + _worldPacket.ReadByteSeq(Npc[2]); + _worldPacket.ReadByteSeq(Npc[5]); + _worldPacket.ReadByteSeq(Npc[4]); + _worldPacket.ReadByteSeq(Npc[3]); + _worldPacket.ReadByteSeq(Npc[1]); + _worldPacket.ReadByteSeq(Npc[6]); + _worldPacket.ReadByteSeq(Npc[0]); +} diff --git a/src/server/game/Server/Packets/ItemPackets.h b/src/server/game/Server/Packets/ItemPackets.h index b046d0f303..4a01af20bd 100644 --- a/src/server/game/Server/Packets/ItemPackets.h +++ b/src/server/game/Server/Packets/ItemPackets.h @@ -34,7 +34,27 @@ namespace WorldPackets uint32 ProficiencyMask = 0; uint8 ProficiencyClass = 0; }; + + struct TransmogrifyItem + { + ObjectGuid SrcItemGUID; + int32 ItemID = 0; + uint32 Slot = 0; + }; + + class TransmogrifyItems final : public ClientPacket + { + public: + TransmogrifyItems(WorldPacket&& packet) : ClientPacket(CMSG_TRANSMOGRIFY_ITEMS, std::move(packet)) { } + + void Read() override; + + ObjectGuid Npc; + std::vector Items; + }; } + + } #endif // ItemPackets_h_ diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 9baac7a3e7..490b83e604 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -148,6 +148,11 @@ namespace WorldPackets class RequestInspectRatedBgStats; } + namespace Item + { + class TransmogrifyItems; + } + namespace Misc { class CompleteCinematic; @@ -1207,7 +1212,7 @@ class TC_GAME_API WorldSession void SendVoidStorageTransferResult(VoidTransferError result); // Transmogrification - void HandleTransmogrifyItems(WorldPacket& recvData); + void HandleTransmogrifyItems(WorldPackets::Item::TransmogrifyItems& packet); // Reforge void HandleReforgeItemOpcode(WorldPacket& recvData);