mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 17:43:52 +00:00
fix: pet opcodes shared unlearn handler despite incompatible formats
SMSG_PET_GUIDS, SMSG_PET_DISMISS_SOUND, and SMSG_PET_ACTION_SOUND were registered with the same handler as SMSG_PET_UNLEARN_CONFIRM. Their different formats (GUID lists, sound IDs with position) were misread as unlearn cost, potentially triggering a bogus unlearn confirmation dialog. Also extracts resetWardenState() from 13 lines duplicated verbatim between connect() and disconnect().
This commit is contained in:
parent
bed859d8db
commit
6f6571fc7a
2 changed files with 35 additions and 37 deletions
|
|
@ -621,6 +621,7 @@ public:
|
||||||
void reportPlayer(uint64_t targetGuid, const std::string& reason);
|
void reportPlayer(uint64_t targetGuid, const std::string& reason);
|
||||||
void stopCasting();
|
void stopCasting();
|
||||||
void resetCastState(); // force-clear all cast/craft/queue state without sending packets
|
void resetCastState(); // force-clear all cast/craft/queue state without sending packets
|
||||||
|
void resetWardenState(); // clear all warden module/crypto state for connect/disconnect
|
||||||
void clearUnitCaches(); // clear per-unit cast states and aura caches
|
void clearUnitCaches(); // clear per-unit cast states and aura caches
|
||||||
|
|
||||||
// ---- Phase 1: Name queries (delegated to EntityController) ----
|
// ---- Phase 1: Name queries (delegated to EntityController) ----
|
||||||
|
|
|
||||||
|
|
@ -714,19 +714,7 @@ bool GameHandler::connect(const std::string& host,
|
||||||
// Diagnostic: dump session key for AUTH_REJECT debugging
|
// Diagnostic: dump session key for AUTH_REJECT debugging
|
||||||
LOG_INFO("GameHandler session key (", sessionKey.size(), "): ",
|
LOG_INFO("GameHandler session key (", sessionKey.size(), "): ",
|
||||||
core::toHexString(sessionKey.data(), sessionKey.size()));
|
core::toHexString(sessionKey.data(), sessionKey.size()));
|
||||||
requiresWarden_ = false;
|
resetWardenState();
|
||||||
wardenGateSeen_ = false;
|
|
||||||
wardenGateElapsed_ = 0.0f;
|
|
||||||
wardenGateNextStatusLog_ = 2.0f;
|
|
||||||
wardenPacketsAfterGate_ = 0;
|
|
||||||
wardenCharEnumBlockedLogged_ = false;
|
|
||||||
wardenCrypto_.reset();
|
|
||||||
wardenState_ = WardenState::WAIT_MODULE_USE;
|
|
||||||
wardenModuleHash_.clear();
|
|
||||||
wardenModuleKey_.clear();
|
|
||||||
wardenModuleSize_ = 0;
|
|
||||||
wardenModuleData_.clear();
|
|
||||||
wardenLoadedModule_.reset();
|
|
||||||
|
|
||||||
// Generate random client seed
|
// Generate random client seed
|
||||||
this->clientSeed = generateClientSeed();
|
this->clientSeed = generateClientSeed();
|
||||||
|
|
@ -755,6 +743,22 @@ bool GameHandler::connect(const std::string& host,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameHandler::resetWardenState() {
|
||||||
|
requiresWarden_ = false;
|
||||||
|
wardenGateSeen_ = false;
|
||||||
|
wardenGateElapsed_ = 0.0f;
|
||||||
|
wardenGateNextStatusLog_ = 2.0f;
|
||||||
|
wardenPacketsAfterGate_ = 0;
|
||||||
|
wardenCharEnumBlockedLogged_ = false;
|
||||||
|
wardenCrypto_.reset();
|
||||||
|
wardenState_ = WardenState::WAIT_MODULE_USE;
|
||||||
|
wardenModuleHash_.clear();
|
||||||
|
wardenModuleKey_.clear();
|
||||||
|
wardenModuleSize_ = 0;
|
||||||
|
wardenModuleData_.clear();
|
||||||
|
wardenLoadedModule_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
void GameHandler::disconnect() {
|
void GameHandler::disconnect() {
|
||||||
if (onTaxiFlight_) {
|
if (onTaxiFlight_) {
|
||||||
taxiRecoverPending_ = true;
|
taxiRecoverPending_ = true;
|
||||||
|
|
@ -771,19 +775,7 @@ void GameHandler::disconnect() {
|
||||||
friendGuids_.clear();
|
friendGuids_.clear();
|
||||||
contacts_.clear();
|
contacts_.clear();
|
||||||
transportAttachments_.clear();
|
transportAttachments_.clear();
|
||||||
requiresWarden_ = false;
|
resetWardenState();
|
||||||
wardenGateSeen_ = false;
|
|
||||||
wardenGateElapsed_ = 0.0f;
|
|
||||||
wardenGateNextStatusLog_ = 2.0f;
|
|
||||||
wardenPacketsAfterGate_ = 0;
|
|
||||||
wardenCharEnumBlockedLogged_ = false;
|
|
||||||
wardenCrypto_.reset();
|
|
||||||
wardenState_ = WardenState::WAIT_MODULE_USE;
|
|
||||||
wardenModuleHash_.clear();
|
|
||||||
wardenModuleKey_.clear();
|
|
||||||
wardenModuleSize_ = 0;
|
|
||||||
wardenModuleData_.clear();
|
|
||||||
wardenLoadedModule_.reset();
|
|
||||||
pendingIncomingPackets_.clear();
|
pendingIncomingPackets_.clear();
|
||||||
// Fire despawn callbacks so the renderer releases M2/character model resources.
|
// Fire despawn callbacks so the renderer releases M2/character model resources.
|
||||||
for (const auto& [guid, entity] : entityController_->getEntityManager().getEntities()) {
|
for (const auto& [guid, entity] : entityController_->getEntityManager().getEntities()) {
|
||||||
|
|
@ -3126,17 +3118,22 @@ void GameHandler::registerOpcodeHandlers() {
|
||||||
packet.skipAll();
|
packet.skipAll();
|
||||||
};
|
};
|
||||||
|
|
||||||
// uint64 petGuid + uint32 cost (copper)
|
// SMSG_PET_UNLEARN_CONFIRM: uint64 petGuid + uint32 cost (copper).
|
||||||
for (auto op : { Opcode::SMSG_PET_GUIDS, Opcode::SMSG_PET_DISMISS_SOUND, Opcode::SMSG_PET_ACTION_SOUND, Opcode::SMSG_PET_UNLEARN_CONFIRM }) {
|
// The other pet opcodes have different formats and must NOT set unlearn state.
|
||||||
dispatchTable_[op] = [this](network::Packet& packet) {
|
dispatchTable_[Opcode::SMSG_PET_UNLEARN_CONFIRM] = [this](network::Packet& packet) {
|
||||||
// uint64 petGuid + uint32 cost (copper)
|
if (packet.hasRemaining(12)) {
|
||||||
if (packet.hasRemaining(12)) {
|
petUnlearnGuid_ = packet.readUInt64();
|
||||||
petUnlearnGuid_ = packet.readUInt64();
|
petUnlearnCost_ = packet.readUInt32();
|
||||||
petUnlearnCost_ = packet.readUInt32();
|
petUnlearnPending_ = true;
|
||||||
petUnlearnPending_ = true;
|
}
|
||||||
}
|
packet.skipAll();
|
||||||
packet.skipAll();
|
};
|
||||||
};
|
// These pet opcodes have incompatible formats — just consume the packet.
|
||||||
|
// Previously they shared the unlearn handler, which misinterpreted sound IDs
|
||||||
|
// or GUID lists as unlearn costs and could trigger a bogus unlearn dialog.
|
||||||
|
for (auto op : { Opcode::SMSG_PET_GUIDS, Opcode::SMSG_PET_DISMISS_SOUND,
|
||||||
|
Opcode::SMSG_PET_ACTION_SOUND }) {
|
||||||
|
dispatchTable_[op] = [](network::Packet& packet) { packet.skipAll(); };
|
||||||
}
|
}
|
||||||
// Server signals that the pet can now be named (first tame)
|
// Server signals that the pet can now be named (first tame)
|
||||||
dispatchTable_[Opcode::SMSG_PET_RENAMEABLE] = [this](network::Packet& packet) {
|
dispatchTable_[Opcode::SMSG_PET_RENAMEABLE] = [this](network::Packet& packet) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue