mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Fix gossip message parsing for Vanilla/Turtle (flight master hang)
Classic gossip packets lack the menuId field and quest items don't have questFlags/isRepeatable, causing the WotLK parser to read garbage counts (541M quests) and hang. Added ClassicPacketParsers::parseGossipMessage override with the correct vanilla format.
This commit is contained in:
parent
a96dc4ebcc
commit
cbb3035313
3 changed files with 60 additions and 1 deletions
|
|
@ -117,6 +117,13 @@ public:
|
|||
return NameQueryResponseParser::parse(packet, data);
|
||||
}
|
||||
|
||||
// --- Gossip ---
|
||||
|
||||
/** Parse SMSG_GOSSIP_MESSAGE */
|
||||
virtual bool parseGossipMessage(network::Packet& packet, GossipMessageData& data) {
|
||||
return GossipMessageParser::parse(packet, data);
|
||||
}
|
||||
|
||||
// --- Destroy Object ---
|
||||
|
||||
/** Parse SMSG_DESTROY_OBJECT */
|
||||
|
|
@ -226,6 +233,7 @@ public:
|
|||
network::Packet buildCastSpell(uint32_t spellId, uint64_t targetGuid, uint8_t castCount) override;
|
||||
bool parseCastFailed(network::Packet& packet, CastFailedData& data) override;
|
||||
bool parseMessageChat(network::Packet& packet, MessageChatData& data) override;
|
||||
bool parseGossipMessage(network::Packet& packet, GossipMessageData& data) override;
|
||||
bool parseGuildRoster(network::Packet& packet, GuildRosterData& data) override;
|
||||
bool parseGuildQueryResponse(network::Packet& packet, GuildQueryResponseData& data) override;
|
||||
network::Packet buildJoinChannel(const std::string& channelName, const std::string& password) override;
|
||||
|
|
|
|||
|
|
@ -7655,7 +7655,9 @@ void GameHandler::handleLootRemoved(network::Packet& packet) {
|
|||
}
|
||||
|
||||
void GameHandler::handleGossipMessage(network::Packet& packet) {
|
||||
if (!GossipMessageParser::parse(packet, currentGossip)) return;
|
||||
bool ok = packetParsers_ ? packetParsers_->parseGossipMessage(packet, currentGossip)
|
||||
: GossipMessageParser::parse(packet, currentGossip);
|
||||
if (!ok) return;
|
||||
if (questDetailsOpen) return; // Don't reopen gossip while viewing quest
|
||||
gossipWindowOpen = true;
|
||||
vendorWindowOpen = false; // Close vendor if gossip opens
|
||||
|
|
|
|||
|
|
@ -580,5 +580,54 @@ bool ClassicPacketParsers::parseGuildQueryResponse(network::Packet& packet, Guil
|
|||
return true;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Gossip — Classic has no menuId, and quest items lack questFlags + isRepeatable
|
||||
// ============================================================================
|
||||
|
||||
bool ClassicPacketParsers::parseGossipMessage(network::Packet& packet, GossipMessageData& data) {
|
||||
size_t remaining = packet.getSize() - packet.getReadPos();
|
||||
if (remaining < 8 + 4 + 4) {
|
||||
LOG_ERROR("Classic SMSG_GOSSIP_MESSAGE too small: ", remaining, " bytes");
|
||||
return false;
|
||||
}
|
||||
|
||||
data.npcGuid = packet.readUInt64();
|
||||
// Classic: NO menuId field (WotLK adds uint32 menuId here)
|
||||
data.menuId = 0;
|
||||
data.titleTextId = packet.readUInt32();
|
||||
uint32_t optionCount = packet.readUInt32();
|
||||
|
||||
data.options.clear();
|
||||
data.options.reserve(optionCount);
|
||||
for (uint32_t i = 0; i < optionCount; ++i) {
|
||||
GossipOption opt;
|
||||
opt.id = packet.readUInt32();
|
||||
opt.icon = packet.readUInt8();
|
||||
opt.isCoded = (packet.readUInt8() != 0);
|
||||
opt.boxMoney = packet.readUInt32();
|
||||
opt.text = packet.readString();
|
||||
opt.boxText = packet.readString();
|
||||
data.options.push_back(opt);
|
||||
}
|
||||
|
||||
uint32_t questCount = packet.readUInt32();
|
||||
data.quests.clear();
|
||||
data.quests.reserve(questCount);
|
||||
for (uint32_t i = 0; i < questCount; ++i) {
|
||||
GossipQuestItem quest;
|
||||
quest.questId = packet.readUInt32();
|
||||
quest.questIcon = packet.readUInt32();
|
||||
quest.questLevel = static_cast<int32_t>(packet.readUInt32());
|
||||
// Classic: NO questFlags, NO isRepeatable
|
||||
quest.questFlags = 0;
|
||||
quest.isRepeatable = 0;
|
||||
quest.title = packet.readString();
|
||||
data.quests.push_back(quest);
|
||||
}
|
||||
|
||||
LOG_INFO("Classic Gossip: ", optionCount, " options, ", questCount, " quests");
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
} // namespace wowee
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue