public RawMotionState(MoveToState moveToState, BinaryReader reader)
        {
            MoveToState = moveToState;

            PackedFlags = reader.ReadUInt32();

            // security vulnerability here:
            // untrusted client input sending command list length
            Flags             = (RawMotionFlags)(PackedFlags & 0x7FF);
            CommandListLength = (ushort)(PackedFlags >> 11);

            if ((Flags & RawMotionFlags.CurrentHoldKey) != 0)
            {
                CurrentHoldKey = (HoldKey)reader.ReadUInt32();
            }
            if ((Flags & RawMotionFlags.CurrentStyle) != 0)
            {
                CurrentStyle = (MotionStance)reader.ReadUInt32();
            }
            if ((Flags & RawMotionFlags.ForwardCommand) != 0)
            {
                ForwardCommand = (MotionCommand)reader.ReadUInt32();
            }
            if ((Flags & RawMotionFlags.ForwardHoldKey) != 0)
            {
                ForwardHoldKey = (HoldKey)reader.ReadUInt32();
            }
            if ((Flags & RawMotionFlags.ForwardSpeed) != 0)
            {
                ForwardSpeed = reader.ReadSingle();
            }
            if ((Flags & RawMotionFlags.SideStepCommand) != 0)
            {
                SidestepCommand = (MotionCommand)reader.ReadUInt32();
            }
            if ((Flags & RawMotionFlags.SideStepHoldKey) != 0)
            {
                SidestepHoldKey = (HoldKey)reader.ReadUInt32();
            }
            if ((Flags & RawMotionFlags.SideStepSpeed) != 0)
            {
                SidestepSpeed = reader.ReadSingle();
            }
            if ((Flags & RawMotionFlags.TurnCommand) != 0)
            {
                TurnCommand = (MotionCommand)reader.ReadUInt32();
            }
            if ((Flags & RawMotionFlags.TurnHoldKey) != 0)
            {
                TurnHoldKey = reader.ReadUInt32();
            }
            if ((Flags & RawMotionFlags.TurnSpeed) != 0)
            {
                TurnSpeed = reader.ReadSingle();
            }

            if (CommandListLength > 0)
            {
                Commands = new List <MotionItem>();
                for (var i = 0; i < CommandListLength; i++)
                {
                    Commands.Add(new MotionItem(moveToState.WorldObject, reader));
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Converts a MoveToState packet from the client -> MovementData packet to send to other clients
        /// This is effectively a shortcut for converting RawMotionState -> InterpretedMotionState
        /// </summary>
        public MovementData(Creature creature, MoveToState state)
        {
            WorldObject = creature;

            var rawState = state.RawMotionState;

            // keeping most of this existing logic, ported from ConvertToClientAccepted
            if ((rawState.Flags & RawMotionFlags.CurrentStyle) != 0)
            {
                CurrentStyle = rawState.CurrentStyle;
            }

            // only using primary hold key?
            var holdKey = rawState.CurrentHoldKey;
            var speed   = holdKey == HoldKey.Run ? creature.GetRunRate() : 1.0f;

            var interpState = new InterpretedMotionState(this);

            // move forwards / backwards / animation
            if ((rawState.Flags & RawMotionFlags.ForwardCommand) != 0 && !state.StandingLongJump)
            {
                if (rawState.ForwardCommand == MotionCommand.WalkForward || rawState.ForwardCommand == MotionCommand.WalkBackwards)
                {
                    interpState.ForwardCommand = MotionCommand.WalkForward;

                    if (rawState.ForwardCommand == MotionCommand.WalkForward && holdKey == HoldKey.Run)
                    {
                        interpState.ForwardCommand = MotionCommand.RunForward;
                    }

                    interpState.ForwardSpeed = speed;

                    if (rawState.ForwardCommand == MotionCommand.WalkBackwards)
                    {
                        interpState.ForwardSpeed *= -0.65f;
                    }
                }
                else
                {
                    interpState.ForwardCommand = rawState.ForwardCommand;
                }
            }

            // sidestep
            if ((rawState.Flags & RawMotionFlags.SideStepCommand) != 0 && !state.StandingLongJump)
            {
                interpState.SidestepCommand = MotionCommand.SideStepRight;
                interpState.SidestepSpeed   = speed * 3.12f / 1.25f * 0.5f;

                if (rawState.SidestepCommand == MotionCommand.SideStepLeft)
                {
                    interpState.SidestepSpeed *= -1;
                }

                Math.Clamp(interpState.SidestepSpeed, -3, 3);
            }

            // rotate
            if ((rawState.Flags & RawMotionFlags.TurnCommand) != 0)
            {
                interpState.TurnCommand = MotionCommand.TurnRight;
                interpState.TurnSpeed   = holdKey == HoldKey.Run ? 1.5f : 1.0f;

                if (rawState.TurnCommand == MotionCommand.TurnLeft)
                {
                    interpState.TurnSpeed *= -1;
                }
            }

            // contact/sticky?
            // this alone isn't enough for standing long jump,
            // and observing clients seems to show a buggy shallow arc jump
            // without the above exclusions of ForwardCommand / SidestepCommand
            if (state.StandingLongJump)
            {
                MotionFlags |= MotionFlags.StandingLongJump;
            }

            interpState.Commands = rawState.Commands;
            interpState.Flags    = interpState.BuildMovementFlags();

            // this is a hack to make walking work correctly - investigate this
            // wouldn't all of these be autonomous?
            // walk backwards?
            //if (holdKey != HoldKey.Invalid || rawState.ForwardCommand == MotionCommand.WalkForward)
            IsAutonomous = true;

            Invalid = new MovementInvalid(this, interpState);
        }