From e1be8667ed120c6fbac3bafe33e501fc2d3b8e95 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Tue, 17 Mar 2026 11:20:50 -0700 Subject: [PATCH] fix: add TBC game object query parser for correct string count TBC 2.4.3 SMSG_GAMEOBJECT_QUERY_RESPONSE has 2 extra strings after name[4] (iconName + castBarCaption). WotLK has 3 (adds unk1). Without this override, the WotLK parser's third readString() consumed bytes from the data[24] fields, corrupting game object type-specific data and breaking interactions with doors, chests, mailboxes, and transports on TBC servers. --- include/game/packet_parsers.hpp | 3 ++ src/game/packet_parsers_tbc.cpp | 65 +++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/include/game/packet_parsers.hpp b/include/game/packet_parsers.hpp index d009204b..d2a8203a 100644 --- a/include/game/packet_parsers.hpp +++ b/include/game/packet_parsers.hpp @@ -370,6 +370,9 @@ public: bool parseGuildRoster(network::Packet& packet, GuildRosterData& data) override; // TBC 2.4.3 SMSG_QUESTGIVER_STATUS: uint32 status (WotLK uses uint8) uint8_t readQuestGiverStatus(network::Packet& packet) override; + // TBC 2.4.3 SMSG_GAMEOBJECT_QUERY_RESPONSE: 2 extra strings after names + // (iconName + castBarCaption); WotLK has 3 (adds unk1) + bool parseGameObjectQueryResponse(network::Packet& packet, GameObjectQueryResponseData& data) override; // TBC 2.4.3 CMSG_JOIN_CHANNEL: name+password only (WotLK prepends channelId+hasVoice+joinedByZone) network::Packet buildJoinChannel(const std::string& channelName, const std::string& password) override; // TBC 2.4.3 CMSG_LEAVE_CHANNEL: name only (WotLK prepends channelId) diff --git a/src/game/packet_parsers_tbc.cpp b/src/game/packet_parsers_tbc.cpp index f8344cb0..4dac23ec 100644 --- a/src/game/packet_parsers_tbc.cpp +++ b/src/game/packet_parsers_tbc.cpp @@ -1580,6 +1580,71 @@ network::Packet TbcPacketParsers::buildLeaveChannel(const std::string& channelNa return packet; } +// ============================================================================ +// TBC 2.4.3 SMSG_GAMEOBJECT_QUERY_RESPONSE +// TBC has 2 extra strings after name[4] (iconName + castBarCaption). +// WotLK has 3 (adds unk1). Classic has 0. +// ============================================================================ + +bool TbcPacketParsers::parseGameObjectQueryResponse(network::Packet& packet, GameObjectQueryResponseData& data) { + if (packet.getSize() < 4) { + LOG_ERROR("TBC SMSG_GAMEOBJECT_QUERY_RESPONSE: packet too small (", packet.getSize(), " bytes)"); + return false; + } + + data.entry = packet.readUInt32(); + + if (data.entry & 0x80000000) { + data.entry &= ~0x80000000; + data.name = ""; + return true; + } + + if (packet.getSize() - packet.getReadPos() < 8) { + LOG_ERROR("TBC SMSG_GAMEOBJECT_QUERY_RESPONSE: truncated before names (entry=", data.entry, ")"); + return false; + } + + data.type = packet.readUInt32(); + data.displayId = packet.readUInt32(); + // 4 name strings + data.name = packet.readString(); + packet.readString(); + packet.readString(); + packet.readString(); + + // TBC: 2 extra strings (iconName + castBarCaption) — WotLK has 3, Classic has 0 + packet.readString(); // iconName + packet.readString(); // castBarCaption + + // Read 24 type-specific data fields + size_t remaining = packet.getSize() - packet.getReadPos(); + if (remaining >= 24 * 4) { + for (int i = 0; i < 24; i++) { + data.data[i] = packet.readUInt32(); + } + data.hasData = true; + } else if (remaining > 0) { + uint32_t fieldsToRead = remaining / 4; + for (uint32_t i = 0; i < fieldsToRead && i < 24; i++) { + data.data[i] = packet.readUInt32(); + } + if (fieldsToRead < 24) { + LOG_WARNING("TBC SMSG_GAMEOBJECT_QUERY_RESPONSE: truncated in data fields (", fieldsToRead, + " of 24, entry=", data.entry, ")"); + } + } + + if (data.type == 15) { // MO_TRANSPORT + LOG_DEBUG("TBC GO query: MO_TRANSPORT entry=", data.entry, + " name=\"", data.name, "\" displayId=", data.displayId, + " taxiPathId=", data.data[0], " moveSpeed=", data.data[1]); + } else { + LOG_DEBUG("TBC GO query: ", data.name, " type=", data.type, " entry=", data.entry); + } + return true; +} + // ============================================================================ // TBC 2.4.3 guild roster parser // Same rank structure as WotLK (variable rankCount + goldLimit + bank tabs),