1use crate::action_state::{ActionState, InputMarker};
2use alloc::{vec, vec::Vec};
3use bevy_ecs::entity::{EntityMapper, MapEntities};
4use bevy_reflect::{FromReflect, Reflect, Reflectable};
5use core::cmp::max;
6use core::fmt::Debug;
7use core::time::Duration;
8use lightyear_core::prelude::Tick;
9use lightyear_inputs::input_buffer::{Compressed, InputBuffer};
10use lightyear_inputs::input_message::{ActionStateSequence, InputSnapshot};
11use serde::de::DeserializeOwned;
12use serde::{Deserialize, Serialize};
13
14pub type NativeBuffer<A> = InputBuffer<ActionState<A>, A>;
15
16#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Reflect)]
17pub struct NativeStateSequence<A> {
18 states: Vec<Compressed<A>>,
19}
20
21impl<A: Debug + Default + PartialEq + Clone + Send + Sync + 'static> InputSnapshot
22 for ActionState<A>
23{
24 fn decay_tick(&mut self, tick_duration: Duration) {}
25}
26
27impl<A> IntoIterator for NativeStateSequence<A> {
28 type Item = Compressed<ActionState<A>>;
29 type IntoIter = core::iter::Map<
30 vec::IntoIter<Compressed<A>>,
31 fn(Compressed<A>) -> Compressed<ActionState<A>>,
32 >;
33
34 fn into_iter(self) -> Self::IntoIter {
35 self.states.into_iter().map(|input| match input {
36 Compressed::Absent => Compressed::Absent,
37 Compressed::SameAsPrecedent => Compressed::SameAsPrecedent,
38 Compressed::Input(i) => Compressed::Input(ActionState(i)),
39 })
40 }
41}
42
43impl<
44 A: Serialize
45 + DeserializeOwned
46 + Clone
47 + PartialEq
48 + Send
49 + Sync
50 + Debug
51 + Default
52 + Reflectable
53 + FromReflect
54 + 'static,
55> ActionStateSequence for NativeStateSequence<A>
56{
57 type Action = A;
58 type Snapshot = ActionState<A>;
59 type State = ActionState<A>;
60 type Marker = InputMarker<A>;
61
62 fn len(&self) -> usize {
63 self.states.len()
64 }
65
66 fn get_snapshots_from_message(
67 self,
68 tick_duration: Duration,
69 ) -> impl Iterator<Item = Compressed<Self::Snapshot>> {
70 self.states.into_iter().map(|input| match input {
71 Compressed::Absent => Compressed::Absent,
72 Compressed::SameAsPrecedent => Compressed::SameAsPrecedent,
73 Compressed::Input(i) => Compressed::Input(ActionState(i)),
74 })
75 }
76
77 fn build_from_input_buffer<'w, 's>(
78 input_buffer: &InputBuffer<Self::Snapshot, Self::Action>,
79 num_ticks: u32,
80 end_tick: Tick,
81 ) -> Option<Self> {
82 let buffer_start_tick = input_buffer.start_tick?;
83 let start_tick = max(end_tick - num_ticks + 1, buffer_start_tick);
85
86 let start_state = input_buffer
88 .get(start_tick)
89 .map_or(Compressed::Absent, |input| input.into());
90 let mut states = vec![start_state];
91
92 let buffer_start = (start_tick + 1 - buffer_start_tick) as usize;
94 let buffer_end = (end_tick + 1 - buffer_start_tick) as usize;
95 for idx in buffer_start..buffer_end {
96 let state =
97 input_buffer
98 .buffer
99 .get(idx)
100 .map_or(Compressed::Absent, |input| match input {
101 Compressed::Absent => Compressed::Absent,
102 Compressed::SameAsPrecedent => Compressed::SameAsPrecedent,
103 Compressed::Input(v) => v.into(),
104 });
105 states.push(state);
106 }
107 Some(Self { states })
108 }
109
110 fn to_snapshot(state: &ActionState<A>) -> Self::Snapshot {
111 (*state).clone()
112 }
113
114 fn from_snapshot(state: &mut ActionState<A>, snapshot: &Self::Snapshot) {
115 *state = snapshot.clone();
116 }
117}
118
119impl<A: MapEntities> MapEntities for NativeStateSequence<A> {
120 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
121 self.states.iter_mut().for_each(|state| {
122 if let Compressed::Input(action_state) = state {
123 action_state.map_entities(entity_mapper);
124 }
125 });
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132 use alloc::collections::VecDeque;
133 use std::time::Duration;
134 use test_log::test;
135
136 #[test]
137 fn test_build_sequence_from_buffer() {
138 let mut input_buffer = InputBuffer::default();
139 input_buffer.set_empty(Tick(2));
140 input_buffer.set(Tick(3), ActionState(1));
141 input_buffer.set(Tick(7), ActionState(2));
142
143 let sequence =
144 NativeStateSequence::<usize>::build_from_input_buffer(&input_buffer, 9, Tick(10))
145 .unwrap();
146 assert_eq!(
147 sequence,
148 NativeStateSequence::<usize> {
149 states: vec![
150 Compressed::Absent,
152 Compressed::Input(1),
154 Compressed::SameAsPrecedent,
155 Compressed::SameAsPrecedent,
156 Compressed::SameAsPrecedent,
157 Compressed::Input(2),
158 Compressed::Absent,
161 Compressed::Absent,
162 Compressed::Absent,
163 ],
164 }
165 );
166 }
167
168 #[test]
169 fn test_update_buffer_from_sequence() {
170 let mut input_buffer = InputBuffer::default();
171 let sequence = NativeStateSequence::<i32> {
172 states: vec![
173 Compressed::Absent,
175 Compressed::Input(0),
177 Compressed::SameAsPrecedent,
178 Compressed::Input(1),
180 Compressed::SameAsPrecedent,
181 Compressed::Absent,
183 Compressed::SameAsPrecedent,
184 Compressed::SameAsPrecedent,
186 ],
187 };
188 sequence.update_buffer(&mut input_buffer, Tick(20), Duration::default());
189 assert_eq!(input_buffer.get(Tick(20)), None,);
190 assert_eq!(input_buffer.get(Tick(19)), None,);
191 assert_eq!(input_buffer.get(Tick(18)), None,);
192 assert_eq!(input_buffer.get(Tick(17)), Some(&ActionState::<i32>(1)));
193 assert_eq!(input_buffer.get(Tick(16)), Some(&ActionState::<i32>(1)));
194 assert_eq!(input_buffer.get(Tick(15)), Some(&ActionState::<i32>(0)));
195 assert_eq!(input_buffer.get(Tick(14)), Some(&ActionState::<i32>(0)));
196 assert_eq!(input_buffer.get(Tick(13)), None,);
197 }
198
199 #[test]
202 fn test_update_buffer_from_sequence_lower_start_tick() {
203 let mut input_buffer = InputBuffer {
204 start_tick: Some(Tick(10)),
205 buffer: VecDeque::from([
206 Compressed::Input(ActionState(0)),
207 Compressed::SameAsPrecedent,
208 Compressed::SameAsPrecedent,
209 ]),
210 last_remote_tick: Some(Tick(12)),
211 marker: core::marker::PhantomData,
212 };
213 let sequence = NativeStateSequence::<usize> {
214 states: vec![
215 Compressed::Absent,
217 Compressed::SameAsPrecedent,
218 Compressed::Input(0),
220 Compressed::SameAsPrecedent,
221 Compressed::SameAsPrecedent,
222 Compressed::SameAsPrecedent,
223 Compressed::SameAsPrecedent,
224 Compressed::Input(1),
225 ],
226 };
227 let mismatch = sequence.update_buffer(&mut input_buffer, Tick(14), Duration::default());
228 assert_eq!(mismatch, Some(Tick(14)));
229 assert_eq!(input_buffer.get(Tick(14)), Some(&ActionState(1)));
230 assert_eq!(input_buffer.get(Tick(13)), Some(&ActionState(0)));
231 assert_eq!(input_buffer.get(Tick(12)), Some(&ActionState(0)));
232 assert_eq!(input_buffer.get(Tick(11)), Some(&ActionState(0)));
233 assert_eq!(input_buffer.get(Tick(10)), Some(&ActionState(0)));
234 assert_eq!(input_buffer.get(Tick(9)), None);
235 assert_eq!(input_buffer.get(Tick(8)), None);
236 assert_eq!(input_buffer.get(Tick(7)), None);
237 }
238
239 #[test]
240 fn test_update_buffer_from_sequence_absent() {
241 let mut input_buffer = InputBuffer {
242 start_tick: Some(Tick(10)),
243 buffer: VecDeque::from([
244 Compressed::Input(ActionState(0)),
245 Compressed::Absent,
246 Compressed::SameAsPrecedent,
247 ]),
248 last_remote_tick: Some(Tick(12)),
249 marker: core::marker::PhantomData,
250 };
251 let sequence = NativeStateSequence::<usize> {
252 states: vec![
253 Compressed::Absent,
255 Compressed::SameAsPrecedent,
257 ],
258 };
259 sequence.update_buffer(&mut input_buffer, Tick(12), Duration::default());
260 assert_eq!(input_buffer.get(Tick(12)), None);
261 assert_eq!(input_buffer.get(Tick(11)), None);
262 assert_eq!(input_buffer.get(Tick(10)), Some(&ActionState(0)));
263 }
264
265 #[test]
266 fn test_update_buffer_from_sequence_present() {
267 let mut input_buffer = InputBuffer {
268 start_tick: Some(Tick(10)),
269 buffer: VecDeque::from([Compressed::Absent, Compressed::SameAsPrecedent]),
270 last_remote_tick: Some(Tick(11)),
271 marker: core::marker::PhantomData,
272 };
273 let sequence = NativeStateSequence::<usize> {
274 states: vec![
275 Compressed::Input(0),
277 Compressed::Absent,
279 Compressed::SameAsPrecedent,
281 ],
282 };
283 let mismatch = sequence.update_buffer(&mut input_buffer, Tick(11), Duration::default());
284 assert_eq!(mismatch, None);
285 assert_eq!(input_buffer.get(Tick(11)), None);
286 assert_eq!(input_buffer.get(Tick(10)), None);
287 assert_eq!(input_buffer.get(Tick(9)), None);
288 }
289
290 #[test]
292 fn test_update_buffer_from_sequence_clip_after() {
293 let mut input_buffer = InputBuffer {
294 start_tick: Some(Tick(10)),
295 buffer: VecDeque::from([Compressed::Absent, Compressed::Input(ActionState(3))]),
296 last_remote_tick: Some(Tick(9)),
297 marker: core::marker::PhantomData,
298 };
299 let sequence = NativeStateSequence::<usize> {
300 states: vec![
301 Compressed::Input(0),
303 ],
304 };
305 let mismatch = sequence.update_buffer(&mut input_buffer, Tick(10), Duration::default());
306 assert_eq!(mismatch, Some(Tick(10)));
307 assert_eq!(input_buffer.get(Tick(11)), None);
309 assert_eq!(input_buffer.len(), 1);
310 }
311}