Skip to main content

ggpo/
input_queue.rs

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        /*
171         * No one should ever try to grab any input when we have a prediction
172         * error.  Doing so means that we're just going further down the wrong
173         * path.  ASSERT this to verify that it's true.
174         */
175        assert!(self.first_incorrect_frame == None);
176
177        /*
178         * Remember the last requested frame number for later.  We'll need
179         * this in AddInput() to drop out of prediction mode.
180         */
181        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                /*
202                 * The requested frame isn't in the queue.  Bummer.  This means we need
203                 * to return a prediction frame.  Predict that the user will do the
204                 * same thing they did last time.
205                 */
206                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            /*
234             * If we've made it this far, we must be predicting.  Go ahead and
235             * forward the prediction frame contents.  Be sure to return the
236             * frame number requested by the client, though.
237             */
238            *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        /*
269         * Add the frame to the back of the queue
270         */
271        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            /*
283             * We've been predicting...  See if the inputs we've gotten match
284             * what we've been predicting.  If so, don't worry about it.  If not,
285             * remember the first input which was incorrect so we can report it
286             * in GetFirstIncorrectFrame()
287             */
288            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            /*
297             * If this input is the same frame as the last one requested and we
298             * still haven't found any mis-predicted inputs, we can dump out
299             * of predition mode entirely!  Otherwise, advance the prediction frame
300             * count up.
301             */
302            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        // let new_frame: Frame =;
316        if let Some(input_frame) = input.frame {
317            info!("adding input frame number {} to queue.\n", input_frame);
318
319            /*
320             * These next two lines simply verify that inputs are passed in
321             * sequentially by the user, regardless of frame delay.
322             */
323            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            /*
330             * Move the queue head to the correct point in preparation to
331             * input the frame into the queue.
332             */
333            if let Some(new_frame) = self.advance_queue_head(input.frame) {
334                self.add_delayed_input_to_queue(&input, new_frame);
335
336                /*
337                 * Update the frame number for the input.  This will also set the
338                 * frame to GameInput::NullFrame for frames that get dropped (by
339                 * design).
340                 */
341                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                    /*
361                     * This can occur when the frame delay has dropped since the last
362                     * time we shoved a frame into the system.  In this case, there's
363                     * no room on the queue.  Toss it.
364                     */
365                    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                    /*
374                     * This can occur when the frame delay has been increased since the last
375                     * time we shoved a frame into the system.  We need to replicate the
376                     * last frame in the queue several times in order to fill the space
377                     * left.
378                     */
379                    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}