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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*! Handles syncing the time between the client and the server
*/
use crateTimelineSyncPlugin;
use crateInputTimeline;
use crateRemoteTimeline;
use crateInputTimelineConfig;
use crateremote;
use crateSyncedTimelinePlugin;
use *;
use Client;
use NetworkTimelinePlugin;
// When a Client is created; we want to add a PredictedTimeline? InterpolatedTimeline?
// or should we let the user do it?
// Systems we need:
// - We want FixedUpdate to slow down if Predicted timeline slows down, because FixedUpdate is fundamentally
// what decides
// - we update
;
// TODO: we might need a separate Predicted<Virtual> and Predicted<FixedUpdate>, and Predicted<()> fetches the correct one
// depending on the Schedule? exactly like bevy does
// and so that the Time is updated based on whether we're in Update
// First
// - Time<Virtual>/Time<()> advance by delta
// - Advance Predicted<()> and Predicted<Virtual> by delta * 1.0 (the predicted timeline is the main timeline so we purely match)
// - Advance Interpolated<()> and Interpolated<Virtual> by delta
// FixedUpdate:
// - Advance Predicted<Fixed> and Interpolated<Fixed> by accumulation
// PostUpdate:
// - Sync timelines in PostUpdate because the server sends messages in PostUpdate (however maybe that's not relevant
// because the server time is updated in First? Think about it) But we receive the server's Tick at frame end
// (after the server ran FixedUpdateLoop)
// - Update the Predicted<Virtual> and Interpolated<Virtual> relative speeds
// - Set the relative speed of Time<Virtual> to Predicted<Virtual>'s relative speed
// Let's handle the Context later! it's a bit tricky
// Maybe this is confusing? What if we tried updating the timeline only in FixedUpdate?
// - in FixedUpdate the tick/overstep would be correct
// - in PostUpdate too
// - in PreUpdate the Time<Virtual> has been updated but not the timelines! Maybe we could just store a PreUpdate now()?
// #[cfg(test)]
// mod tests {
// use super::*;
// use crate::prelude::server::Replicate;
// use crate::prelude::*;
// use crate::tests::protocol::*;
// use crate::tests::stepper::BevyStepper;
// use core::time::Duration;
//
// /// Check that after a big tick discrepancy between server/client, the client tick gets updated
// /// to match the server tick
// #[test]
// fn test_sync_after_tick_wrap() {
// let tick_duration = Duration::from_millis(10);
// let mut stepper = BevyStepper::default();
//
// // set time to end of wrapping
// let new_tick = Tick(u16::MAX - 1000);
// let new_time = WrappedTime::from_duration(tick_duration * (new_tick.0 as u32));
//
// stepper
// .server_app
// .world_mut()
// .resource_mut::<TimeManager>()
// .set_current_time(new_time);
// stepper
// .server_app
// .world_mut()
// .resource_mut::<TickManager>()
// .set_tick_to(new_tick);
//
// let server_entity = stepper
// .server_app
// .world_mut()
// .spawn((ComponentSyncModeFull(0.0), Replicate::default()))
// .id();
//
// // cross tick boundary
// for i in 0..200 {
// stepper.frame_step();
// }
// stepper
// .server_app
// .world_mut()
// .entity_mut(server_entity)
// .insert(ComponentSyncModeFull(1.0));
// // dbg!(&stepper.server_tick());
// // dbg!(&stepper.client_tick());
// // dbg!(&stepper
// // .server_app
// // .world()
// // .get::<ComponentSyncModeFull>(server_entity));
//
// // make sure the client receives the replication message
// for i in 0..5 {
// stepper.frame_step();
// }
//
// let client_entity = stepper
// .client_app
// .world()
// .resource::<client::ConnectionManager>()
// .replication_receiver
// .remote_entity_map
// .get_local(server_entity)
// .unwrap();
// assert_eq!(
// stepper
// .client_app
// .world()
// .get::<ComponentSyncModeFull>(client_entity)
// .unwrap(),
// &ComponentSyncModeFull(1.0)
// );
// }
// }