From 068b6bc2cbb3a8d371ced0da0c006e2f9a82ff27 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Tue, 10 Mar 2026 17:10:31 -0700 Subject: [PATCH] fix: parse SMSG_INVENTORY_CHANGE_FAILURE additional fields correctly Previously the handler read only the error byte, producing: - A literal "%d" in the "requires level" message (error 1) - No consumption of the following item GUIDs and bag slot bytes Now reads item_guid1(8) + item_guid2(8) + bag_slot(1) after the error byte, and for error 1 (EQUIP_ERR_LEVEL_REQ) reads the required level uint32 and shows the correct message: "You must reach level N to use that item." --- src/game/game_handler.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index a8841074..1b20c142 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -3603,10 +3603,29 @@ void GameHandler::handlePacket(network::Packet& packet) { uint8_t error = packet.readUInt8(); if (error != 0) { LOG_WARNING("SMSG_INVENTORY_CHANGE_FAILURE: error=", (int)error); + // After error byte: item_guid1(8) + item_guid2(8) + bag_slot(1) = 17 bytes + uint32_t requiredLevel = 0; + if (packet.getSize() - packet.getReadPos() >= 17) { + packet.readUInt64(); // item_guid1 + packet.readUInt64(); // item_guid2 + packet.readUInt8(); // bag_slot + // Error 1 = EQUIP_ERR_LEVEL_REQ: server appends required level as uint32 + if (error == 1 && packet.getSize() - packet.getReadPos() >= 4) + requiredLevel = packet.readUInt32(); + } // InventoryResult enum (AzerothCore 3.3.5a) const char* errMsg = nullptr; + char levelBuf[64]; switch (error) { - case 1: errMsg = "You must reach level %d to use that item."; break; + case 1: + if (requiredLevel > 0) { + std::snprintf(levelBuf, sizeof(levelBuf), + "You must reach level %u to use that item.", requiredLevel); + addSystemChatMessage(levelBuf); + } else { + addSystemChatMessage("You must reach a higher level to use that item."); + } + break; case 2: errMsg = "You don't have the required skill."; break; case 3: errMsg = "That item doesn't go in that slot."; break; case 4: errMsg = "That bag is full."; break;