void HandleMoveSetModMovementForceMagnitudeAck(MovementSpeedAck setModMovementForceMagnitudeAck)
        {
            Unit mover = _player.m_unitMovedByMe;

            Cypher.Assert(mover != null);                      // there must always be a mover
            _player.ValidateMovementInfo(setModMovementForceMagnitudeAck.Ack.Status);

            // prevent tampered movement data
            if (setModMovementForceMagnitudeAck.Ack.Status.Guid != mover.GetGUID())
            {
                Log.outError(LogFilter.Network, $"HandleSetModMovementForceMagnitudeAck: guid error, expected {mover.GetGUID()}, got {setModMovementForceMagnitudeAck.Ack.Status.Guid}");
                return;
            }

            // skip all except last
            if (_player.m_movementForceModMagnitudeChanges > 0)
            {
                --_player.m_movementForceModMagnitudeChanges;
                if (_player.m_movementForceModMagnitudeChanges == 0)
                {
                    float          expectedModMagnitude = 1.0f;
                    MovementForces movementForces       = mover.GetMovementForces();
                    if (movementForces != null)
                    {
                        expectedModMagnitude = movementForces.GetModMagnitude();
                    }

                    if (Math.Abs(expectedModMagnitude - setModMovementForceMagnitudeAck.Speed) > 0.01f)
                    {
                        Log.outDebug(LogFilter.Misc, $"Player {_player.GetName()} from account id {_player.GetSession().GetAccountId()} kicked for incorrect movement force magnitude (must be {expectedModMagnitude} instead {setModMovementForceMagnitudeAck.Speed})");
                        _player.GetSession().KickPlayer();
                        return;
                    }
                }
            }

            setModMovementForceMagnitudeAck.Ack.Status.Time += m_clientTimeDelay;

            MoveUpdateSpeed updateModMovementForceMagnitude = new MoveUpdateSpeed(ServerOpcodes.MoveUpdateModMovementForceMagnitude);

            updateModMovementForceMagnitude.Status = setModMovementForceMagnitudeAck.Ack.Status;
            updateModMovementForceMagnitude.Speed  = setModMovementForceMagnitudeAck.Speed;
            mover.SendMessageToSet(updateModMovementForceMagnitude, false);
        }
        void HandleForceSpeedChangeAck(MovementSpeedAck packet)
        {
            GetPlayer().ValidateMovementInfo(packet.Ack.Status);

            // now can skip not our packet
            if (GetPlayer().GetGUID() != packet.Ack.Status.Guid)
            {
                return;
            }

            /*----------------*/
            // client ACK send one packet for mounted/run case and need skip all except last from its
            // in other cases anti-cheat check can be fail in false case
            UnitMoveType move_type;

            ClientOpcodes opcode = packet.GetOpcode();

            switch (opcode)
            {
            case ClientOpcodes.MoveForceWalkSpeedChangeAck:
                move_type = UnitMoveType.Walk;
                break;

            case ClientOpcodes.MoveForceRunSpeedChangeAck:
                move_type = UnitMoveType.Run;
                break;

            case ClientOpcodes.MoveForceRunBackSpeedChangeAck:
                move_type = UnitMoveType.RunBack;
                break;

            case ClientOpcodes.MoveForceSwimSpeedChangeAck:
                move_type = UnitMoveType.Swim;
                break;

            case ClientOpcodes.MoveForceSwimBackSpeedChangeAck:
                move_type = UnitMoveType.SwimBack;
                break;

            case ClientOpcodes.MoveForceTurnRateChangeAck:
                move_type = UnitMoveType.TurnRate;
                break;

            case ClientOpcodes.MoveForceFlightSpeedChangeAck:
                move_type = UnitMoveType.Flight;
                break;

            case ClientOpcodes.MoveForceFlightBackSpeedChangeAck:
                move_type = UnitMoveType.FlightBack;
                break;

            case ClientOpcodes.MoveForcePitchRateChangeAck:
                move_type = UnitMoveType.PitchRate;
                break;

            default:
                Log.outError(LogFilter.Network, "WorldSession.HandleForceSpeedChangeAck: Unknown move type opcode: {0}", opcode);
                return;
            }

            // skip all forced speed changes except last and unexpected
            // in run/mounted case used one ACK and it must be skipped. m_forced_speed_changes[MOVE_RUN] store both.
            if (GetPlayer().m_forced_speed_changes[(int)move_type] > 0)
            {
                --GetPlayer().m_forced_speed_changes[(int)move_type];
                if (GetPlayer().m_forced_speed_changes[(int)move_type] > 0)
                {
                    return;
                }
            }

            if (!GetPlayer().GetTransport() && Math.Abs(GetPlayer().GetSpeed(move_type) - packet.Speed) > 0.01f)
            {
                if (GetPlayer().GetSpeed(move_type) > packet.Speed)         // must be greater - just correct
                {
                    Log.outError(LogFilter.Network, "{0}SpeedChange player {1} is NOT correct (must be {2} instead {3}), force set to correct value",
                                 move_type, GetPlayer().GetName(), GetPlayer().GetSpeed(move_type), packet.Speed);
                    GetPlayer().SetSpeedRate(move_type, GetPlayer().GetSpeedRate(move_type));
                }
                else                                                // must be lesser - cheating
                {
                    Log.outDebug(LogFilter.Server, "Player {0} from account id {1} kicked for incorrect speed (must be {2} instead {3})",
                                 GetPlayer().GetName(), GetPlayer().GetSession().GetAccountId(), GetPlayer().GetSpeed(move_type), packet.Speed);
                    GetPlayer().GetSession().KickPlayer();
                }
            }
        }