mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-03 08:03:50 +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
35d91ebfe1
commit
a01bcb3a00
3 changed files with 60 additions and 1 deletions
|
|
@ -117,6 +117,13 @@ public:
|
||||||
return NameQueryResponseParser::parse(packet, data);
|
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 ---
|
// --- Destroy Object ---
|
||||||
|
|
||||||
/** Parse SMSG_DESTROY_OBJECT */
|
/** Parse SMSG_DESTROY_OBJECT */
|
||||||
|
|
@ -226,6 +233,7 @@ public:
|
||||||
network::Packet buildCastSpell(uint32_t spellId, uint64_t targetGuid, uint8_t castCount) override;
|
network::Packet buildCastSpell(uint32_t spellId, uint64_t targetGuid, uint8_t castCount) override;
|
||||||
bool parseCastFailed(network::Packet& packet, CastFailedData& data) override;
|
bool parseCastFailed(network::Packet& packet, CastFailedData& data) override;
|
||||||
bool parseMessageChat(network::Packet& packet, MessageChatData& 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 parseGuildRoster(network::Packet& packet, GuildRosterData& data) override;
|
||||||
bool parseGuildQueryResponse(network::Packet& packet, GuildQueryResponseData& data) override;
|
bool parseGuildQueryResponse(network::Packet& packet, GuildQueryResponseData& data) override;
|
||||||
network::Packet buildJoinChannel(const std::string& channelName, const std::string& password) 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) {
|
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
|
if (questDetailsOpen) return; // Don't reopen gossip while viewing quest
|
||||||
gossipWindowOpen = true;
|
gossipWindowOpen = true;
|
||||||
vendorWindowOpen = false; // Close vendor if gossip opens
|
vendorWindowOpen = false; // Close vendor if gossip opens
|
||||||
|
|
|
||||||
|
|
@ -580,5 +580,54 @@ bool ClassicPacketParsers::parseGuildQueryResponse(network::Packet& packet, Guil
|
||||||
return true;
|
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 game
|
||||||
} // namespace wowee
|
} // namespace wowee
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue