1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use crate::game_input::{FrameNum, GameInput};
use log::{error, info};
use std::cmp::min;
const FRAME_WINDOW_SIZE: usize = 40;
const MIN_UNIQUE_FRAMES: usize = 10;
const MIN_FRAME_ADVANTAGE: usize = 3;
const MAX_FRAME_ADVANTAGE: usize = 9;
pub struct TimeSync {
local: [i32; FRAME_WINDOW_SIZE],
remote: [i32; FRAME_WINDOW_SIZE],
last_inputs: [GameInput; MIN_UNIQUE_FRAMES],
_next_prediction: usize,
}
impl Default for TimeSync {
fn default() -> Self {
TimeSync::new()
}
}
impl TimeSync {
pub const fn new() -> Self {
TimeSync {
local: [0; FRAME_WINDOW_SIZE],
remote: [0; FRAME_WINDOW_SIZE],
_next_prediction: FRAME_WINDOW_SIZE * 3,
last_inputs: [GameInput::new(); MIN_UNIQUE_FRAMES],
}
}
pub fn advance_frame(&mut self, input: &GameInput, advantage: i32, r_advantage: i32) {
let _sleep_time: i32 = 0;
match input.frame {
Some(frame) => {
self.last_inputs[frame as usize % MIN_UNIQUE_FRAMES] = input.clone();
self.local[frame as usize % FRAME_WINDOW_SIZE] = advantage;
self.remote[frame as usize % FRAME_WINDOW_SIZE] = r_advantage;
}
None => error!("game input frame is null"),
}
}
pub fn recommend_frame_wait_duration(&mut self, require_idle_input: bool) -> FrameNum {
let mut count = 0;
let mut sum = 0;
let (advantage, r_advantage): (f32, f32);
for i in 0..FRAME_WINDOW_SIZE {
sum += self.local[i];
}
advantage = sum as f32 / FRAME_WINDOW_SIZE as f32;
sum = 0;
for i in 0..FRAME_WINDOW_SIZE {
sum += self.remote[i];
}
r_advantage = sum as f32 / FRAME_WINDOW_SIZE as f32;
count += 1;
if advantage >= r_advantage {
return 0;
}
let sleep_frames: FrameNum = (((r_advantage - advantage) / 2.) + 0.5) as FrameNum;
info!("iteration {}: sleep frames is {}\n", count, sleep_frames);
if sleep_frames < MIN_FRAME_ADVANTAGE as u32 {
return 0;
}
if require_idle_input {
for i in 1..MIN_UNIQUE_FRAMES {
if !self.last_inputs[i].equal(&self.last_inputs[0], true) {
info!(
"iteration {}: rejecting due to input stuff at position {}...!!!\n",
count, i
);
return 0;
}
}
}
return min(sleep_frames, MAX_FRAME_ADVANTAGE as FrameNum);
}
}