From 1a6960e3f9ccfa64b359f63b0ee8e71c6b62dc20 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sun, 29 Mar 2026 18:53:16 -0700 Subject: [PATCH] fix: speed ACK sent before validation caused client/server desync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the server sent a NaN or out-of-range speed, the client echoed it back in the ACK (confirming it to the server) but then rejected it locally. This left the server believing the client accepted the speed while the client used the old value — a desync only fixable by relog. Moved validation before the ACK so bad speeds are rejected outright. --- src/game/movement_handler.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/game/movement_handler.cpp b/src/game/movement_handler.cpp index eb5b6210..56840144 100644 --- a/src/game/movement_handler.cpp +++ b/src/game/movement_handler.cpp @@ -787,6 +787,13 @@ void MovementHandler::handleForceSpeedChange(network::Packet& packet, const char if (guid != owner_.playerGuid) return; + // Validate BEFORE sending ACK — if we echo a bad speed back to the server + // but don't apply it locally, the client and server desync on movement speed. + if (std::isnan(newSpeed) || newSpeed < 0.1f || newSpeed > 100.0f) { + LOG_WARNING("Ignoring invalid ", name, " speed: ", newSpeed); + return; + } + if (owner_.socket) { network::Packet ack(wireOpcode(ackOpcode)); const bool legacyGuidAck = @@ -825,11 +832,6 @@ void MovementHandler::handleForceSpeedChange(network::Packet& packet, const char owner_.socket->send(ack); } - if (std::isnan(newSpeed) || newSpeed < 0.1f || newSpeed > 100.0f) { - LOG_WARNING("Ignoring invalid ", name, " speed: ", newSpeed); - return; - } - if (speedStorage) *speedStorage = newSpeed; }