mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 09:33:51 +00:00
Fix Classic/Turtle spell casting, cast fail parsing, and empty chat
Three Classic packet format fixes: 1. CMSG_CAST_SPELL: target flags are uint32 (not uint16). The wrong size caused the server to misparse the packet as an item enchant operation, returning "item already enchanted". 2. SMSG_CAST_FAILED: Classic has no castCount byte prefix (added in TBC). Added parseCastFailed override to ClassicPacketParsers. Without this, the parser read the wrong bytes and produced "Spell cast failed (error 0)" for every failure. 3. SMSG_MESSAGECHAT: Removed spurious receiverGuid read for SAY/YELL types. Classic chat format has no second GUID before the message body — the extra 8-byte read consumed messageLen + message data, producing empty chat messages.
This commit is contained in:
parent
d22d32838f
commit
139a2f39fe
3 changed files with 27 additions and 14 deletions
|
|
@ -95,6 +95,11 @@ public:
|
||||||
return InitialSpellsParser::parse(packet, data);
|
return InitialSpellsParser::parse(packet, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Parse SMSG_CAST_FAILED */
|
||||||
|
virtual bool parseCastFailed(network::Packet& packet, CastFailedData& data) {
|
||||||
|
return CastFailedParser::parse(packet, data);
|
||||||
|
}
|
||||||
|
|
||||||
/** Parse SMSG_AURA_UPDATE / SMSG_AURA_UPDATE_ALL */
|
/** Parse SMSG_AURA_UPDATE / SMSG_AURA_UPDATE_ALL */
|
||||||
virtual bool parseAuraUpdate(network::Packet& packet, AuraUpdateData& data, bool isAll = false) {
|
virtual bool parseAuraUpdate(network::Packet& packet, AuraUpdateData& data, bool isAll = false) {
|
||||||
return AuraUpdateParser::parse(packet, data, isAll);
|
return AuraUpdateParser::parse(packet, data, isAll);
|
||||||
|
|
@ -207,6 +212,7 @@ public:
|
||||||
const MovementInfo& info,
|
const MovementInfo& info,
|
||||||
uint64_t playerGuid = 0) override;
|
uint64_t playerGuid = 0) override;
|
||||||
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 parseMessageChat(network::Packet& packet, MessageChatData& data) override;
|
bool parseMessageChat(network::Packet& packet, MessageChatData& 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;
|
||||||
|
|
|
||||||
|
|
@ -6570,7 +6570,9 @@ void GameHandler::handleInitialSpells(network::Packet& packet) {
|
||||||
|
|
||||||
void GameHandler::handleCastFailed(network::Packet& packet) {
|
void GameHandler::handleCastFailed(network::Packet& packet) {
|
||||||
CastFailedData data;
|
CastFailedData data;
|
||||||
if (!CastFailedParser::parse(packet, data)) return;
|
bool ok = packetParsers_ ? packetParsers_->parseCastFailed(packet, data)
|
||||||
|
: CastFailedParser::parse(packet, data);
|
||||||
|
if (!ok) return;
|
||||||
|
|
||||||
casting = false;
|
casting = false;
|
||||||
currentCastSpellId = 0;
|
currentCastSpellId = 0;
|
||||||
|
|
|
||||||
|
|
@ -267,9 +267,9 @@ network::Packet ClassicPacketParsers::buildCastSpell(uint32_t spellId, uint64_t
|
||||||
|
|
||||||
packet.writeUInt32(spellId);
|
packet.writeUInt32(spellId);
|
||||||
|
|
||||||
// SpellCastTargets — vanilla uses uint16 target mask (not uint32 like WotLK)
|
// SpellCastTargets — vanilla/CMaNGOS uses uint32 target mask (same as WotLK)
|
||||||
if (targetGuid != 0) {
|
if (targetGuid != 0) {
|
||||||
packet.writeUInt16(0x02); // TARGET_FLAG_UNIT
|
packet.writeUInt32(0x02); // TARGET_FLAG_UNIT
|
||||||
|
|
||||||
// Write packed GUID
|
// Write packed GUID
|
||||||
uint8_t mask = 0;
|
uint8_t mask = 0;
|
||||||
|
|
@ -289,12 +289,24 @@ network::Packet ClassicPacketParsers::buildCastSpell(uint32_t spellId, uint64_t
|
||||||
packet.writeUInt8(bytes[i]);
|
packet.writeUInt8(bytes[i]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
packet.writeUInt16(0x00); // TARGET_FLAG_SELF
|
packet.writeUInt32(0x00); // TARGET_FLAG_SELF
|
||||||
}
|
}
|
||||||
|
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Classic SMSG_CAST_FAILED: no castCount byte (added in TBC/WotLK)
|
||||||
|
// Format: spellId(u32) + result(u8)
|
||||||
|
// ============================================================================
|
||||||
|
bool ClassicPacketParsers::parseCastFailed(network::Packet& packet, CastFailedData& data) {
|
||||||
|
data.castCount = 0;
|
||||||
|
data.spellId = packet.readUInt32();
|
||||||
|
data.result = packet.readUInt8();
|
||||||
|
LOG_INFO("[Classic] Cast failed: spell=", data.spellId, " result=", (int)data.result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Classic 1.12.1 parseCharEnum
|
// Classic 1.12.1 parseCharEnum
|
||||||
// Differences from TBC:
|
// Differences from TBC:
|
||||||
|
|
@ -437,16 +449,9 @@ bool ClassicPacketParsers::parseMessageChat(network::Packet& packet, MessageChat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vanilla/Classic: target GUID follows type-specific header for non-monster types
|
// Classic SAY/YELL/PARTY/GUILD/etc: NO second GUID before message.
|
||||||
// (Monster types already read target/receiver in their switch case)
|
// Only WHISPER_INFORM has a receiver GUID (same as sender for echo).
|
||||||
if (data.type != ChatType::MONSTER_SAY &&
|
// Do NOT read an extra uint64 here — it would consume messageLen + message bytes.
|
||||||
data.type != ChatType::MONSTER_YELL &&
|
|
||||||
data.type != ChatType::MONSTER_EMOTE &&
|
|
||||||
data.type != ChatType::CHANNEL) {
|
|
||||||
if (packet.getReadPos() + 12 <= packet.getSize()) { // 8 (guid) + 4 (msgLen) minimum
|
|
||||||
data.receiverGuid = packet.readUInt64();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read message length
|
// Read message length
|
||||||
uint32_t messageLen = packet.readUInt32();
|
uint32_t messageLen = packet.readUInt32();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue