From b5336d784ab2ae7b8d96871e2161bb58f33ba890 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 6 Feb 2026 09:14:22 -0800 Subject: [PATCH] Fix movement packet format: write fallTime unconditionally AzerothCore's ReadMovementInfo always reads fallTime regardless of flags. Also write all four jump fields together when FALLING (remove nested FALLINGFAR check), and use real millisecond timestamps via steady_clock. --- src/game/game_handler.cpp | 7 +++++-- src/game/world_packets.cpp | 28 ++++++++++++++-------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index f5eaf1b9..8af98f75 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -2251,8 +2251,11 @@ void GameHandler::sendMovement(Opcode opcode) { return; } - // Update movement time - movementInfo.time = ++movementTime; + // Use real millisecond timestamp (server validates for anti-cheat) + static auto startTime = std::chrono::steady_clock::now(); + auto now = std::chrono::steady_clock::now(); + movementInfo.time = static_cast( + std::chrono::duration_cast(now - startTime).count()); // Update movement flags based on opcode switch (opcode) { diff --git a/src/game/world_packets.cpp b/src/game/world_packets.cpp index ac8730cb..66358591 100644 --- a/src/game/world_packets.cpp +++ b/src/game/world_packets.cpp @@ -564,23 +564,23 @@ network::Packet MovementPacket::build(Opcode opcode, const MovementInfo& info, u packet.writeBytes(reinterpret_cast(&info.pitch), sizeof(float)); } - // Write fall time if falling - if (info.hasFlag(MovementFlags::FALLING)) { - packet.writeUInt32(info.fallTime); - packet.writeBytes(reinterpret_cast(&info.jumpVelocity), sizeof(float)); + // Fall time is ALWAYS present in the packet (server reads it unconditionally). + // Jump velocity/angle data is only present when FALLING flag is set. + packet.writeUInt32(info.fallTime); - // Extended fall data if far falling - if (info.hasFlag(MovementFlags::FALLINGFAR)) { - packet.writeBytes(reinterpret_cast(&info.jumpSinAngle), sizeof(float)); - packet.writeBytes(reinterpret_cast(&info.jumpCosAngle), sizeof(float)); - packet.writeBytes(reinterpret_cast(&info.jumpXYSpeed), sizeof(float)); - } + if (info.hasFlag(MovementFlags::FALLING)) { + packet.writeBytes(reinterpret_cast(&info.jumpVelocity), sizeof(float)); + packet.writeBytes(reinterpret_cast(&info.jumpSinAngle), sizeof(float)); + packet.writeBytes(reinterpret_cast(&info.jumpCosAngle), sizeof(float)); + packet.writeBytes(reinterpret_cast(&info.jumpXYSpeed), sizeof(float)); } - LOG_DEBUG("Built movement packet: opcode=0x", std::hex, static_cast(opcode), std::dec); - LOG_DEBUG(" Flags: 0x", std::hex, info.flags, std::dec); - LOG_DEBUG(" Position: (", info.x, ", ", info.y, ", ", info.z, ")"); - LOG_DEBUG(" Orientation: ", info.orientation); + static int mvLog = 10; + if (mvLog-- > 0) { + LOG_INFO("Movement pkt: opcode=0x", std::hex, static_cast(opcode), std::dec, + " size=", packet.getSize(), " flags=0x", std::hex, info.flags, std::dec, + " pos=(", info.x, ",", info.y, ",", info.z, ")"); + } return packet; }