Skip to main content

azalea_physics/
client_movement.rs

1use azalea_core::position::Vec2;
2use bevy_ecs::component::Component;
3
4/// Component for entities that can move and sprint.
5///
6/// Usually only present for [`LocalEntity`]s.
7///
8/// [`LocalEntity`]: azalea_entity::LocalEntity
9#[derive(Clone, Component, Default)]
10pub struct ClientMovementState {
11    /// Minecraft only sends a movement packet either after 20 ticks or if the
12    /// player moved enough. This is that tick counter.
13    pub position_remainder: u32,
14    pub was_sprinting: bool,
15    // Whether we're going to try to start sprinting this tick. Equivalent to
16    // holding down ctrl for a tick.
17    pub trying_to_sprint: bool,
18
19    /// Whether our player is currently trying to sneak.
20    ///
21    /// This is distinct from
22    /// [`AbstractEntityShiftKeyDown`](azalea_entity::metadata::AbstractEntityShiftKeyDown),
23    /// which is a metadata value that is controlled by the server and affects
24    /// how the nametags of other entities are displayed.
25    ///
26    /// To check whether we're actually sneaking, you can check the
27    /// [`Crouching`](azalea_entity::Crouching) or [`Pose`](azalea_entity::Pose)
28    /// components.
29    pub trying_to_crouch: bool,
30
31    pub move_direction: WalkDirection,
32    pub move_vector: Vec2,
33}
34
35/// A direction that a player can walk in, including none.
36///
37/// Superset of [`SprintDirection`].
38///
39/// This can be freely converted to and from [`DirectionStates`].
40#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
41pub enum WalkDirection {
42    #[default]
43    None,
44    Forward,
45    Backward,
46    Left,
47    Right,
48    ForwardRight,
49    ForwardLeft,
50    BackwardRight,
51    BackwardLeft,
52}
53impl WalkDirection {
54    /// Returns true if the direction is forward, forward-right, or
55    /// forward-left.
56    pub fn forward(self) -> bool {
57        DirectionStates::from(self).forward
58    }
59    /// Returns true if the direction is backward, backward-right, or
60    /// backward-left.
61    pub fn backward(self) -> bool {
62        DirectionStates::from(self).backward
63    }
64    /// Returns true if the direction is left, forward-left, or backward-left.
65    pub fn left(self) -> bool {
66        DirectionStates::from(self).left
67    }
68    /// Returns true if the direction is right, forward-right, or
69    /// backward-right.
70    pub fn right(self) -> bool {
71        DirectionStates::from(self).right
72    }
73
74    pub fn set_forward(&mut self, value: bool) {
75        let mut d = DirectionStates::from(*self);
76        d.forward = value;
77        *self = d.into();
78    }
79    pub fn set_backward(&mut self, value: bool) {
80        let mut d = DirectionStates::from(*self);
81        d.backward = value;
82        *self = d.into();
83    }
84    pub fn set_left(&mut self, value: bool) {
85        let mut d = DirectionStates::from(*self);
86        d.left = value;
87        *self = d.into();
88    }
89    pub fn set_right(&mut self, value: bool) {
90        let mut d = DirectionStates::from(*self);
91        d.right = value;
92        *self = d.into();
93    }
94
95    /// Inverts the walk direction.
96    ///
97    /// ```
98    /// # use azalea_physics::client_movement::WalkDirection;
99    ///
100    /// assert_eq!(WalkDirection::Forward.opposite(), WalkDirection::Backward);
101    /// assert_eq!(
102    ///     WalkDirection::BackwardRight.opposite(),
103    ///     WalkDirection::ForwardLeft
104    /// );
105    /// assert_eq!(WalkDirection::None.opposite(), WalkDirection::None);
106    /// ```
107    pub fn opposite(self) -> Self {
108        match self {
109            Self::None => Self::None,
110            Self::Forward => Self::Backward,
111            Self::Backward => Self::Forward,
112            Self::Left => Self::Right,
113            Self::Right => Self::Left,
114            Self::ForwardRight => Self::BackwardLeft,
115            Self::ForwardLeft => Self::BackwardRight,
116            Self::BackwardRight => Self::ForwardLeft,
117            Self::BackwardLeft => Self::ForwardRight,
118        }
119    }
120}
121/// A struct containing fields for each direction.
122///
123/// This can be freely converted to and from a [`WalkDirection`], and may
124/// simplify certain movement direction checks.
125#[derive(Default)]
126pub struct DirectionStates {
127    pub forward: bool,
128    pub backward: bool,
129    pub left: bool,
130    pub right: bool,
131}
132impl From<WalkDirection> for DirectionStates {
133    fn from(d: WalkDirection) -> Self {
134        let mut s = Self::default();
135        match d {
136            WalkDirection::None => {}
137            WalkDirection::Forward => s.forward = true,
138            WalkDirection::Backward => s.backward = true,
139            WalkDirection::Left => s.left = true,
140            WalkDirection::Right => s.right = true,
141            WalkDirection::ForwardRight => {
142                s.forward = true;
143                s.right = true
144            }
145            WalkDirection::ForwardLeft => {
146                s.forward = true;
147                s.left = true
148            }
149            WalkDirection::BackwardRight => {
150                s.backward = true;
151                s.right = true
152            }
153            WalkDirection::BackwardLeft => {
154                s.backward = true;
155                s.left = true
156            }
157        };
158        s
159    }
160}
161impl From<DirectionStates> for WalkDirection {
162    fn from(d: DirectionStates) -> Self {
163        let left = d.left && !d.right;
164        let right = d.right && !d.left;
165
166        if d.forward && !d.backward {
167            return if right {
168                Self::ForwardRight
169            } else if left {
170                Self::ForwardLeft
171            } else {
172                Self::Forward
173            };
174        } else if d.backward && !d.forward {
175            if right {
176                Self::BackwardRight
177            } else if left {
178                Self::BackwardLeft
179            } else {
180                Self::Backward
181            };
182        }
183        if right {
184            Self::Right
185        } else if left {
186            Self::Left
187        } else {
188            Self::None
189        }
190    }
191}
192
193/// The directions that a player can sprint in. It's a subset of
194/// [`WalkDirection`].
195#[derive(Clone, Copy, Debug)]
196pub enum SprintDirection {
197    Forward,
198    ForwardRight,
199    ForwardLeft,
200}
201
202impl From<SprintDirection> for WalkDirection {
203    fn from(d: SprintDirection) -> Self {
204        match d {
205            SprintDirection::Forward => WalkDirection::Forward,
206            SprintDirection::ForwardRight => WalkDirection::ForwardRight,
207            SprintDirection::ForwardLeft => WalkDirection::ForwardLeft,
208        }
209    }
210}