1use crate::game_input::{Frame, FrameNum, GameInput, GAMEINPUT_MAX_BYTES, GAMEINPUT_MAX_PLAYERS};
2use log::info;
3use std::cmp;
4
5const INPUT_QUEUE_LENGTH: usize = 128;
6const DEFAULT_INPUT_SIZE: usize = 4;
7
8macro_rules! previous_frame {
9 ($offset:expr, $INPUT_QUEUE_LENGTH:expr) => {
10 if $offset == 0 {
11 $INPUT_QUEUE_LENGTH - 1
12 } else {
13 $offset - 1
14 }
15 };
16}
17
18#[derive(Copy, Clone)]
19pub struct InputQueue {
20 _id: usize,
21 head: usize,
22 tail: usize,
23 length: usize,
24 first_frame: bool,
25
26 last_user_added_frame: Frame,
27 last_added_frame: Frame,
28 first_incorrect_frame: Frame,
29 last_frame_requested: Frame,
30
31 frame_delay: usize,
32
33 inputs: [GameInput; INPUT_QUEUE_LENGTH],
34 prediction: GameInput,
35}
36
37impl Default for InputQueue {
38 fn default() -> Self {
39 InputQueue {
40 _id: 0,
41 head: 0,
42 tail: 0,
43 length: 0,
44 frame_delay: 0,
45 first_frame: true,
46 last_user_added_frame: None,
47 last_added_frame: None,
48 first_incorrect_frame: None,
49 last_frame_requested: None,
50
51 prediction: GameInput::init(None, None, DEFAULT_INPUT_SIZE),
52 inputs: [GameInput::init(
53 None,
54 Some(&[[b'0'; GAMEINPUT_MAX_BYTES]; GAMEINPUT_MAX_PLAYERS]),
55 DEFAULT_INPUT_SIZE,
56 ); INPUT_QUEUE_LENGTH],
57 }
58 }
59}
60
61impl InputQueue {
62 pub fn new() -> Self {
63 InputQueue {
64 ..Default::default()
65 }
66 }
67 pub fn init(id: usize, input_size: usize) -> Self {
68 InputQueue {
69 _id: id,
70 head: 0,
71 tail: 0,
72 length: 0,
73 frame_delay: 0,
74 first_frame: true,
75 last_user_added_frame: None,
76 last_added_frame: None,
77 first_incorrect_frame: None,
78 last_frame_requested: None,
79
80 prediction: GameInput::init(None, None, input_size),
81 inputs: [GameInput::init(
82 None,
83 Some(&[[b'0'; GAMEINPUT_MAX_BYTES]; GAMEINPUT_MAX_PLAYERS]),
84 input_size,
85 ); INPUT_QUEUE_LENGTH],
86 }
87 }
88 pub fn get_confirmed_input(&self, requested_frame: Frame, input: &mut GameInput) -> bool {
89 if let Some(_first_incorrect_frame) = self.first_incorrect_frame {
90 assert!(requested_frame < self.first_incorrect_frame);
91 }
92
93 if let Some(requested_frame_value) = requested_frame {
94 let offset = requested_frame_value as usize % INPUT_QUEUE_LENGTH;
95
96 if self.inputs[offset].frame != requested_frame {
97 return false;
98 }
99 *input = self.inputs[offset].clone();
100 return true;
101 }
102
103 false
104 }
105 pub fn get_last_confirmed_frame(&self) -> Frame {
106 info!(
107 "returning last confirmed frame: {:?}\n",
108 self.last_added_frame
109 );
110
111 self.last_added_frame
112 }
113
114 pub fn set_frame_delay(&mut self, delay: usize) {
115 self.frame_delay = delay;
116 }
117
118 pub fn get_first_incorrect_frame(&self) -> Frame {
119 self.first_incorrect_frame
120 }
121
122 pub fn discard_confirmed_frames(&mut self, in_frame: FrameNum) {
123 let mut frame = in_frame;
124
125 if let Some(last_frame_requested) = self.last_frame_requested {
126 frame = cmp::min(frame, last_frame_requested);
127 }
128
129 if let Some(last_added_frame) = self.last_added_frame {
130 info!(
131 "discarding confirmed frames up to {} (last_added:{} length:{} [head:{} tail:{}]).\n",
132 frame, last_added_frame, self.length, self.head, self.tail
133 );
134
135 if frame >= last_added_frame {
136 self.tail = self.head;
137 } else {
138 if let Some(tail_frame) = self.inputs[self.tail].frame {
139 let offset: usize = (frame - tail_frame + 1) as usize;
140
141 info!("difference of {} frames.\n", offset);
142
143 self.tail = (self.tail + offset) % INPUT_QUEUE_LENGTH;
144 self.length -= offset;
145
146 info!(
147 "after discarding, new tail is {} (frame:{}).\n",
148 self.tail, tail_frame,
149 );
150 }
151 }
152 }
153 }
154
155 pub fn reset_prediction(&mut self, frame: FrameNum) {
156 if let Some(first_incorrect_frame) = self.first_incorrect_frame {
157 assert!(frame <= first_incorrect_frame);
158 }
159
160 info!("resetting all prediction errors back to frame {}.\n", frame);
161
162 self.prediction.frame = None;
163 self.first_incorrect_frame = None;
164 self.last_frame_requested = None;
165 }
166
167 pub fn get_input(&mut self, requested_frame: FrameNum, input: &mut GameInput) -> bool {
168 info!("requesting input frame {}.\n", requested_frame);
169
170 assert!(self.first_incorrect_frame == None);
176
177 self.last_frame_requested = Some(requested_frame);
182
183 if let Some(input_tail_frame) = self.inputs[self.tail].frame {
184 assert!(requested_frame >= input_tail_frame);
185
186 if self.prediction.frame == None {
187 let mut offset: usize = (requested_frame - input_tail_frame) as usize;
188
189 if offset < self.length {
190 offset = (offset + self.tail) % INPUT_QUEUE_LENGTH;
191 if let Some(input_offset_frame) = self.inputs[offset].frame {
192 assert!(input_offset_frame == requested_frame);
193 *input = self.inputs[offset];
194 }
195 if let Some(input_frame) = input.frame {
196 info!("returning confirmed frame number {}.\n", input_frame);
197 return true;
198 }
199 }
200
201 if requested_frame == 0 {
207 info!(
208 "basing new prediction frame from nothing, you're client wants frame 0.\n"
209 );
210 self.prediction.erase();
211 } else if self.last_added_frame == None {
212 info!(
213 "basing new prediction frame from nothing, since we have no frames yet.\n"
214 );
215 self.prediction.erase();
216 } else {
217 if let Some(input_previous_frame) =
218 self.inputs[previous_frame!(self.head, INPUT_QUEUE_LENGTH)].frame
219 {
220 info!("basing new prediction frame from previously added frame (queue entry:{}, frame:{}).\n",
221 previous_frame!(self.head, INPUT_QUEUE_LENGTH), input_previous_frame);
222 }
223 self.prediction = self.inputs[previous_frame!(self.head, INPUT_QUEUE_LENGTH)];
224 }
225 if let Some(prediction_frame) = self.prediction.frame {
226 self.prediction.frame = Some(prediction_frame + 1);
227 }
228 }
229 }
230
231 assert!(self.prediction.frame != None);
232 if let Some(prediction_frame) = self.prediction.frame {
233 *input = self.prediction;
239 input.frame = Some(requested_frame);
240 if let Some(input_frame) = input.frame {
241 info!(
242 "returning prediction frame number {} ({}).\n",
243 input_frame, prediction_frame
244 );
245 }
246 }
247
248 false
249 }
250
251 pub fn add_delayed_input_to_queue(&mut self, input: &GameInput, frame_number: FrameNum) {
252 info!(
253 "adding delayed input frame number {} to queue.\n",
254 frame_number
255 );
256 assert!(input.size == self.prediction.size);
257 if let Some(last_added_frame) = self.last_added_frame {
258 assert!(frame_number == last_added_frame + 1);
259 }
260 if let Some(input_previous_head_frame) =
261 self.inputs[previous_frame!(self.head, INPUT_QUEUE_LENGTH)].frame
262 {
263 assert!(frame_number == 0 || input_previous_head_frame == frame_number - 1);
264 } else {
265 assert!(frame_number == 0);
266 }
267
268 self.inputs[self.head] = input.clone();
272 self.inputs[self.head].frame = Some(frame_number);
273 self.head = (self.head + 1) % INPUT_QUEUE_LENGTH;
274 self.length += 1;
275 self.first_frame = false;
276
277 self.last_added_frame = Some(frame_number);
278
279 if let Some(prediction_frame) = self.prediction.frame {
280 assert!(frame_number == prediction_frame);
281
282 if self.first_incorrect_frame == None && !self.prediction.equal(input, true) {
289 info!(
290 "frame {} does not match prediction. marking error.\n",
291 frame_number,
292 );
293 self.first_incorrect_frame = Some(frame_number);
294 }
295
296 if self.prediction.frame == self.last_frame_requested
303 && self.first_incorrect_frame == None
304 {
305 info!("prediction is correct! dumping out of prediction mode.\n");
306 self.prediction.frame = None;
307 } else {
308 self.prediction.frame = Some(prediction_frame + 1);
309 }
310 }
311 assert!(self.length <= INPUT_QUEUE_LENGTH);
312 }
313
314 pub fn add_input(&mut self, mut input: GameInput) {
315 if let Some(input_frame) = input.frame {
317 info!("adding input frame number {} to queue.\n", input_frame);
318
319 if let Some(last_user_added_frame) = self.last_user_added_frame {
324 assert!(input_frame == last_user_added_frame + 1);
325 }
326
327 self.last_user_added_frame = input.frame;
328
329 if let Some(new_frame) = self.advance_queue_head(input.frame) {
334 self.add_delayed_input_to_queue(&input, new_frame);
335
336 input.frame = Some(new_frame);
342 } else {
343 input.frame = None
344 }
345 }
346 }
347
348 pub fn advance_queue_head(&mut self, input_frame: Frame) -> Frame {
349 if let Some(frame) = input_frame {
350 info!("advancing queue head to frame {}.\n", frame);
351 if let Some(input_previous_head) =
352 self.inputs[previous_frame!(self.head, INPUT_QUEUE_LENGTH)].frame
353 {
354 let mut expected_frame = if self.first_frame {
355 0
356 } else {
357 input_previous_head + 1
358 };
359 if expected_frame > frame {
360 info!(
366 "Dropping input frame {} (expected next frame to be {}).\n",
367 frame, expected_frame
368 );
369 return None;
370 }
371
372 while expected_frame < frame {
373 info!(
380 "Adding padding frame {} to account for change in frame delay.\n",
381 expected_frame
382 );
383 let last_frame_input: GameInput =
384 self.inputs[previous_frame!(self.head, INPUT_QUEUE_LENGTH)];
385
386 self.add_delayed_input_to_queue(&last_frame_input, expected_frame);
387 expected_frame += 1;
388 }
389
390 assert!(frame == 0 || frame == input_previous_head + 1);
391 }
392 return Some(frame);
393 }
394 input_frame
395 }
396}