mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
sync
current problems: - [X] time was wiggling to much => resolved, we state.ticked twice per client.tick - [ ] Jump Reset to 0, see issue #1512 => Jump z reset to 0 after 200ms (time ahead) for 1 tick, on_ground is one tick behind JumpEvent, could be disabled by modifying common/state/src/state.rs handle_jump if condition remove on_ground check - [ ] X/Y wiggle which looks like this -/'\,/- => The error actually persists in the last 1 before we receive no data from server /''''*\ => The error exist equally in X and Y regardless of direction => The error already exsits before we apply the state.tick or state.rewind_tick, so it maybe comes from server via sync ? - [X] Cant look around when holding the admin staff => we used Dir::new() which was 0/1/0 and due to normalizing limited the final range to around 5 degree - [X] Slower when zommed in than when zoomed out => fixed by the look_dir fix above :)
This commit is contained in:
parent
819661d1bb
commit
65a0c15054
@ -237,8 +237,9 @@ pub struct Client {
|
|||||||
|
|
||||||
local_command_gen: CommandGenerator,
|
local_command_gen: CommandGenerator,
|
||||||
next_control: Controller,
|
next_control: Controller,
|
||||||
inter_tick_rewind_time: Option<Duration>,
|
inter_tick_reverted_time: Option<Duration>,
|
||||||
_rewind_fluctuation_budget: f64,
|
inter_tick_time_syncs: usize,
|
||||||
|
rewind_fluctuation_budget: f64,
|
||||||
|
|
||||||
network: Option<Network>,
|
network: Option<Network>,
|
||||||
participant: Option<Participant>,
|
participant: Option<Participant>,
|
||||||
@ -723,8 +724,9 @@ impl Client {
|
|||||||
|
|
||||||
local_command_gen: CommandGenerator::default(),
|
local_command_gen: CommandGenerator::default(),
|
||||||
next_control: Controller::default(),
|
next_control: Controller::default(),
|
||||||
inter_tick_rewind_time: None,
|
inter_tick_reverted_time: None,
|
||||||
_rewind_fluctuation_budget: 0.0,
|
inter_tick_time_syncs: 0,
|
||||||
|
rewind_fluctuation_budget: 0.0,
|
||||||
|
|
||||||
network: Some(network),
|
network: Some(network),
|
||||||
participant: Some(participant),
|
participant: Some(participant),
|
||||||
@ -1703,7 +1705,8 @@ impl Client {
|
|||||||
|
|
||||||
// 1) Build up a list of events for this frame, to be passed to the frontend.
|
// 1) Build up a list of events for this frame, to be passed to the frontend.
|
||||||
let mut frontend_events = Vec::new();
|
let mut frontend_events = Vec::new();
|
||||||
self.inter_tick_rewind_time = None;
|
self.inter_tick_reverted_time = None;
|
||||||
|
self.inter_tick_time_syncs = 0;
|
||||||
|
|
||||||
// Prepare for new events
|
// Prepare for new events
|
||||||
{
|
{
|
||||||
@ -1734,10 +1737,16 @@ impl Client {
|
|||||||
frontend_events.append(&mut self.handle_new_messages()?);
|
frontend_events.append(&mut self.handle_new_messages()?);
|
||||||
|
|
||||||
// Simulate Ahead
|
// Simulate Ahead
|
||||||
common_base::plot!("recived_time_sync", 0.0);
|
|
||||||
if let Some(rewind_time) = self.inter_tick_rewind_time {
|
//TODO: also waro budget in non rewind workflow
|
||||||
common_base::plot!("recived_time_sync", 1.0);
|
//Dies hier. außerdem ist immernoch 200 als fixer wert im controler drinn
|
||||||
let _time = self.state.ecs().read_resource::<Time>().0 as f64;
|
|
||||||
|
let time = self.state.ecs().read_resource::<Time>().0 as f64;
|
||||||
|
|
||||||
|
common_base::plot!("recived_time_sync", self.inter_tick_time_syncs as f64);
|
||||||
|
|
||||||
|
if let Some(rewind_time) = self.inter_tick_reverted_time {
|
||||||
|
let time = self.state.ecs().read_resource::<Time>().0 as f64;
|
||||||
let simulate_ahead = self
|
let simulate_ahead = self
|
||||||
.state
|
.state
|
||||||
.ecs()
|
.ecs()
|
||||||
@ -1758,33 +1767,48 @@ impl Client {
|
|||||||
// end_tick=130+100+30=260 Tick3: server_time=160ms dt=60ms ping=30
|
// end_tick=130+100+30=260 Tick3: server_time=160ms dt=60ms ping=30
|
||||||
// simulate_ahead=130ms, rewind_tick=70ms end_tick=160+70+60=290
|
// simulate_ahead=130ms, rewind_tick=70ms end_tick=160+70+60=290
|
||||||
let simulate_ahead = simulate_ahead.max(dt) - dt;
|
let simulate_ahead = simulate_ahead.max(dt) - dt;
|
||||||
// measurements lead to the effect that smooth_diff is == 0.0 when we add 2
|
|
||||||
// server ticks here.
|
|
||||||
let simulate_ahead = simulate_ahead + Duration::from_secs_f64(1.0 / 30.0);
|
let simulate_ahead = simulate_ahead + Duration::from_secs_f64(1.0 / 30.0);
|
||||||
|
/*
|
||||||
let _strict_end_tick_time =
|
let x = if rewind_time > simulate_ahead + Duration::from_millis(25) {
|
||||||
simulate_ahead.as_secs_f64() + /*simulated dt of this tick*/dt.as_secs_f64();
|
common_base::plot!("xxx", 1.0);
|
||||||
|
common_base::plot!("gggggg", simulate_ahead.as_secs_f64() - rewind_time.as_secs_f64() );
|
||||||
// Simulate_ahead still fluctionates because Server Tick != Client Tick, and we
|
simulate_ahead + Duration::from_millis(15)
|
||||||
// cant control the phase in which the sync happens.
|
} else if rewind_time < simulate_ahead - Duration::from_millis(25) {
|
||||||
// In order to dampen it, we calculate the smooth_time and make sure to not
|
common_base::plot!("xxx", -1.0);
|
||||||
// derive to much from it
|
simulate_ahead - Duration::from_millis(15)
|
||||||
let smooth_diff = simulate_ahead.as_secs_f64() - rewind_time.as_secs_f64();
|
|
||||||
|
|
||||||
//const WARP_PERCENT: f64 = 0.05; // make sure we end up not further than 5%
|
|
||||||
// from the estimated tick let warp_budget
|
|
||||||
let simulate_ahead = if smooth_diff / dt.as_secs_f64() > 0.05 {
|
|
||||||
// use
|
|
||||||
simulate_ahead
|
|
||||||
} else {
|
} else {
|
||||||
|
common_base::plot!("xxx", 0.0);
|
||||||
simulate_ahead
|
simulate_ahead
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
let time = self.state.ecs().read_resource::<Time>().0;
|
||||||
|
common_base::plot!("tick_before", time);
|
||||||
|
|
||||||
common_base::plot!("smooth_diff", smooth_diff);
|
let vel = self
|
||||||
|
.state
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<Vel>()
|
||||||
|
.get(self.entity())
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(Vel(Vec3::zero()));
|
||||||
|
|
||||||
|
common_base::plot!("vel_x_before1", vel.0.x as f64);
|
||||||
|
common_base::plot!("vel_y_before1", vel.0.y as f64);
|
||||||
|
common_base::plot!("vel_z_before1", vel.0.z as f64);
|
||||||
|
let pos = self
|
||||||
|
.state
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<common::comp::Pos>()
|
||||||
|
.get(self.entity())
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(common::comp::Pos(Vec3::zero()));
|
||||||
|
|
||||||
|
common_base::plot!("pos_x_before1", pos.0.x as f64);
|
||||||
|
common_base::plot!("pos_y_before1", pos.0.y as f64);
|
||||||
|
common_base::plot!("pos_z_before1", pos.0.z as f64);
|
||||||
|
}
|
||||||
|
|
||||||
//let simulate_ahead = simulate_ahead.max(dt)/* - dt*/;
|
|
||||||
//let simulate_ahead = rewind_time.min(simulate_ahead);
|
|
||||||
tracing::warn!(?simulate_ahead, ?dt, "simulating ahead again");
|
|
||||||
common_base::plot!("rewind_time", rewind_time.as_secs_f64());
|
common_base::plot!("rewind_time", rewind_time.as_secs_f64());
|
||||||
self.state.rewind_tick(
|
self.state.rewind_tick(
|
||||||
simulate_ahead,
|
simulate_ahead,
|
||||||
@ -1793,40 +1817,175 @@ impl Client {
|
|||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
let time = self.state.ecs().read_resource::<Time>().0;
|
||||||
|
common_base::plot!("tick_afterwards1", time);
|
||||||
|
let vel = self
|
||||||
|
.state
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<Vel>()
|
||||||
|
.get(self.entity())
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(Vel(Vec3::zero()));
|
||||||
|
|
||||||
|
common_base::plot!("vel_x_after1", vel.0.x as f64);
|
||||||
|
common_base::plot!("vel_y_after1", vel.0.y as f64);
|
||||||
|
common_base::plot!("vel_z_after1", vel.0.z as f64);
|
||||||
|
let pos = self
|
||||||
|
.state
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<common::comp::Pos>()
|
||||||
|
.get(self.entity())
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(common::comp::Pos(Vec3::zero()));
|
||||||
|
|
||||||
|
common_base::plot!("pos_x_after1", pos.0.x as f64);
|
||||||
|
common_base::plot!("pos_y_after1", pos.0.y as f64);
|
||||||
|
common_base::plot!("pos_z_after1", pos.0.z as f64);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
common_base::plot!("dt", dt.as_secs_f64());
|
/*
|
||||||
self.state.tick(
|
let mut rewind_time = Duration::from_secs_f64(0.0);
|
||||||
dt,
|
const WARP_PERCENT: f64 = 0.05; // make sure we end up not further than 5% from the estimated tick
|
||||||
|
let mut target_smooth_dt = dt.as_secs_f64();
|
||||||
|
common_base::plot!("recived_time_sync", 0.0);
|
||||||
|
if let Some(reverted_time) = self.inter_tick_reverted_time {
|
||||||
|
// At smooth_time we wouldn't notice any rewind
|
||||||
|
let smooth_time = reverted_time + dt;
|
||||||
|
common_base::plot!("recived_time_sync", 1.0);
|
||||||
|
common_base::plot!("reverted_time", reverted_time.as_secs_f64());
|
||||||
|
let time = self.state.ecs().read_resource::<Time>().0 as f64;
|
||||||
|
let simulate_ahead = self
|
||||||
|
.state
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<RemoteController>()
|
||||||
|
.get(self.entity())
|
||||||
|
.map(|rc| rc.simulate_ahead())
|
||||||
|
.unwrap_or_default();
|
||||||
|
// We substract `dt` here, as otherwise we
|
||||||
|
// Tick1: server_time=100ms dt=60ms ping=30 simulate_ahead=130ms, rewind_tick=130ms end_tick=100+130+60=290
|
||||||
|
// Tick2: server_time=130ms dt=30ms ping=30 simulate_ahead=130ms, rewind_tick=130ms end_tick=130+130+30=290
|
||||||
|
// Tick3: server_time=160ms dt=60ms ping=30 simulate_ahead=130ms, rewind_tick=130ms end_tick=160+130+60=350
|
||||||
|
// with dt substraction
|
||||||
|
// Tick1: server_time=100ms dt=60ms ping=30 simulate_ahead=130ms, rewind_tick=70ms end_tick=100+70+60=230
|
||||||
|
// Tick2: server_time=130ms dt=30ms ping=30 simulate_ahead=130ms, rewind_tick=100ms end_tick=130+100+30=260
|
||||||
|
// Tick3: server_time=160ms dt=60ms ping=30 simulate_ahead=130ms, rewind_tick=70ms end_tick=160+70+60=290
|
||||||
|
let simulate_ahead = simulate_ahead.max(dt) - dt;
|
||||||
|
// measurements lead to the effect that smooth_diff is == 0.0 when we add 2 server ticks here.
|
||||||
|
let simulate_ahead = simulate_ahead + Duration::from_secs_f64(1.0 / 30.0);
|
||||||
|
rewind_time = simulate_ahead;
|
||||||
|
|
||||||
|
// Simulate_ahead still fluctionates because Server Tick != Client Tick, and we cant
|
||||||
|
// control the phase in which the sync happens.
|
||||||
|
// In order to dampen it, we calculate the target_smooth_dt and make sure to not derive
|
||||||
|
// to much from it
|
||||||
|
|
||||||
|
ERROR, muss man das hier swappen ?
|
||||||
|
target_smooth_dt = reverted_time.as_secs_f64() - simulate_ahead.as_secs_f64();
|
||||||
|
// we store it, and will apply it over the course of the next ticks
|
||||||
|
self.rewind_fluctuation_budget = target_smooth_dt;
|
||||||
|
common_base::plot!("new_rewind_fluctuation_budget", self.rewind_fluctuation_budget);
|
||||||
|
}
|
||||||
|
common_base::plot!("rewind_time", rewind_time.as_secs_f64());
|
||||||
|
|
||||||
|
|
||||||
|
// we need to subtract the normal dt as we have a separate tick call for it.
|
||||||
|
// make it positive as we wont allow direct go in past
|
||||||
|
let corrected_target_smooth_dt = (target_smooth_dt - dt.as_secs_f64()).max(0.0);
|
||||||
|
common_base::plot!("corrected_target_smooth_dt", corrected_target_smooth_dt);
|
||||||
|
|
||||||
|
// apply our budget to rewind_time
|
||||||
|
let mut smooth_rewind_time = rewind_time.as_secs_f64();
|
||||||
|
smooth_rewind_time += self.rewind_fluctuation_budget;
|
||||||
|
let xxx = smooth_rewind_time.clamp( corrected_target_smooth_dt * (1.0-WARP_PERCENT), corrected_target_smooth_dt * (1.0+WARP_PERCENT));
|
||||||
|
common_base::plot!("xxx", xxx);
|
||||||
|
smooth_rewind_time = xxx;
|
||||||
|
self.rewind_fluctuation_budget -= smooth_rewind_time - rewind_time.as_secs_f64();
|
||||||
|
|
||||||
|
common_base::plot!("rewind_fluctuation_budget", self.rewind_fluctuation_budget);
|
||||||
|
common_base::plot!("target_smooth_dt", target_smooth_dt);
|
||||||
|
|
||||||
|
|
||||||
|
tracing::warn!(?smooth_rewind_time, ?dt, "simulating ahead again");
|
||||||
|
self.state.rewind_tick(
|
||||||
|
Duration::from_secs_f64(smooth_rewind_time),
|
||||||
|dispatch_builder| {
|
|dispatch_builder| {
|
||||||
add_local_systems(dispatch_builder);
|
add_rewind_systems(dispatch_builder);
|
||||||
add_foreign_systems(dispatch_builder);
|
|
||||||
},
|
},
|
||||||
true,
|
false,
|
||||||
);
|
);
|
||||||
let time = self.state.ecs().read_resource::<Time>().0;
|
|
||||||
common_base::plot!("tick_afterwards", time);
|
|
||||||
let vel = self
|
|
||||||
.state
|
|
||||||
.ecs()
|
|
||||||
.read_storage::<Vel>()
|
|
||||||
.get(self.entity())
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or(Vel(Vec3::zero()));
|
|
||||||
|
|
||||||
common_base::plot!("vel_x_after", vel.0.x as f64);
|
*/
|
||||||
common_base::plot!("vel_y_after", vel.0.y as f64);
|
|
||||||
let pos = self
|
|
||||||
.state
|
|
||||||
.ecs()
|
|
||||||
.read_storage::<common::comp::Pos>()
|
|
||||||
.get(self.entity())
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or(common::comp::Pos(Vec3::zero()));
|
|
||||||
|
|
||||||
common_base::plot!("pos_x_after", pos.0.x as f64);
|
/*
|
||||||
common_base::plot!("pos_y_after", pos.0.y as f64);
|
if let Some(rewind_time) = self.inter_tick_reverted_time {
|
||||||
common_base::plot!("pos_z_after", pos.0.z as f64);
|
common_base::plot!("recived_time_sync", 1.0);
|
||||||
|
let _time = self.state.ecs().read_resource::<Time>().0 as f64;
|
||||||
|
let simulate_ahead = self
|
||||||
|
.state
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<RemoteController>()
|
||||||
|
.get(self.entity())
|
||||||
|
.map(|rc| rc.simulate_ahead())
|
||||||
|
.unwrap_or_default();
|
||||||
|
// We substract `dt` here, as otherwise we
|
||||||
|
// Tick1: server_time=100ms dt=60ms ping=30 simulate_ahead=130ms,
|
||||||
|
// rewind_tick=130ms end_tick=100+130+60=290
|
||||||
|
// Tick2: server_time=130ms dt=30ms ping=30 simulate_ahead=130ms,
|
||||||
|
// rewind_tick=130ms end_tick=130+130+30=290
|
||||||
|
// Tick3: server_time=160ms dt=60ms ping=30 simulate_ahead=130ms,
|
||||||
|
// rewind_tick=130ms end_tick=160+130+60=350 with dt substraction
|
||||||
|
// Tick1: server_time=100ms dt=60ms ping=30 simulate_ahead=130ms,
|
||||||
|
// rewind_tick=70ms end_tick=100+70+60=230 Tick2: server_time=130ms
|
||||||
|
// dt=30ms ping=30 simulate_ahead=130ms, rewind_tick=100ms
|
||||||
|
// end_tick=130+100+30=260 Tick3: server_time=160ms dt=60ms ping=30
|
||||||
|
// simulate_ahead=130ms, rewind_tick=70ms end_tick=160+70+60=290
|
||||||
|
let simulate_ahead = simulate_ahead.max(dt) - dt;
|
||||||
|
// measurements lead to the effect that smooth_diff is == 0.0 when we add 2
|
||||||
|
// server ticks here.
|
||||||
|
let simulate_ahead = simulate_ahead + Duration::from_secs_f64(1.0 / 30.0);
|
||||||
|
|
||||||
|
// Simulate_ahead still fluctionates because Server Tick != Client Tick, and we cant
|
||||||
|
// control the phase in which the sync happens.
|
||||||
|
// In order to dampen it, we calculate the smooth_time and make sure to not derive
|
||||||
|
// to much from it
|
||||||
|
let smooth_diff = simulate_ahead.as_secs_f64() - rewind_time.as_secs_f64();
|
||||||
|
|
||||||
|
const WARP_PERCENT: f64 = 0.05; // make sure we end up not further than 5% from the estimated tick
|
||||||
|
let mut warp_budget = dt.as_secs_f64() * WARP_PERCENT;
|
||||||
|
if smooth_diff.abs() > warp_budget {
|
||||||
|
self.rewind_fluctuation_budget += (dt.as_secs_f64() * (1.0-WARP_PERCENT)) * smooth_diff.signum();
|
||||||
|
warp_budget = warp_budget.clamp(-warp_budget, warp_budget);
|
||||||
|
}
|
||||||
|
|
||||||
|
// extend from
|
||||||
|
let add = if smooth_diff >= 0.0 {
|
||||||
|
smooth_diff.min(self.rewind_fluctuation_budget).max(0.0)
|
||||||
|
} else {
|
||||||
|
smooth_diff.max(self.rewind_fluctuation_budget).min(0.0)
|
||||||
|
};
|
||||||
|
self.rewind_fluctuation_budget -= add;
|
||||||
|
let simulate_ahead = Duration::from_secs_f64(time + rewind_time.as_secs_f64() + add);
|
||||||
|
|
||||||
|
common_base::plot!("rewind_fluctuation_budget", self.rewind_fluctuation_budget);
|
||||||
|
common_base::plot!("smooth_diff", smooth_diff);
|
||||||
|
|
||||||
|
//let simulate_ahead = simulate_ahead.max(dt)/* - dt*/;
|
||||||
|
//let simulate_ahead = rewind_time.min(simulate_ahead);
|
||||||
|
tracing::warn!(?simulate_ahead, ?dt, "simulating ahead again");
|
||||||
|
common_base::plot!("rewind_time", rewind_time.as_secs_f64());
|
||||||
|
self.state.rewind_tick(
|
||||||
|
simulate_ahead,
|
||||||
|
|dispatch_builder| {
|
||||||
|
add_rewind_systems(dispatch_builder);
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
// 2) Handle input from frontend.
|
// 2) Handle input from frontend.
|
||||||
// Pass character actions from frontend input to the player's entity.
|
// Pass character actions from frontend input to the player's entity.
|
||||||
@ -1885,6 +2044,35 @@ impl Client {
|
|||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
common_base::plot!("dt", dt.as_secs_f64());
|
||||||
|
let time = self.state.ecs().read_resource::<Time>().0;
|
||||||
|
common_base::plot!("tick_afterwards", time);
|
||||||
|
let vel = self
|
||||||
|
.state
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<Vel>()
|
||||||
|
.get(self.entity())
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(Vel(Vec3::zero()));
|
||||||
|
|
||||||
|
common_base::plot!("vel_x_after", vel.0.x as f64);
|
||||||
|
common_base::plot!("vel_y_after", vel.0.y as f64);
|
||||||
|
common_base::plot!("vel_z_after", vel.0.z as f64);
|
||||||
|
let pos = self
|
||||||
|
.state
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<common::comp::Pos>()
|
||||||
|
.get(self.entity())
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(common::comp::Pos(Vec3::zero()));
|
||||||
|
|
||||||
|
common_base::plot!("pos_x_after", pos.0.x as f64);
|
||||||
|
common_base::plot!("pos_y_after", pos.0.y as f64);
|
||||||
|
common_base::plot!("pos_z_after", pos.0.z as f64);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: avoid emitting these in the first place
|
// TODO: avoid emitting these in the first place
|
||||||
let _ = self
|
let _ = self
|
||||||
.state
|
.state
|
||||||
@ -2222,6 +2410,7 @@ impl Client {
|
|||||||
*self.state.ecs_mut().write_resource() = time;
|
*self.state.ecs_mut().write_resource() = time;
|
||||||
},
|
},
|
||||||
ServerGeneral::EntitySync(entity_sync_package) => {
|
ServerGeneral::EntitySync(entity_sync_package) => {
|
||||||
|
common_base::plot!("EntitySync", 1.0);
|
||||||
self.state
|
self.state
|
||||||
.ecs_mut()
|
.ecs_mut()
|
||||||
.apply_entity_sync_package(entity_sync_package);
|
.apply_entity_sync_package(entity_sync_package);
|
||||||
@ -2258,6 +2447,7 @@ impl Client {
|
|||||||
prof_span!("handle_server_in_game_msg");
|
prof_span!("handle_server_in_game_msg");
|
||||||
match msg {
|
match msg {
|
||||||
ServerGeneral::TimeSync(time) => {
|
ServerGeneral::TimeSync(time) => {
|
||||||
|
self.inter_tick_time_syncs += 1;
|
||||||
// Even with a stable network, expect time to oscillate around the actual time
|
// Even with a stable network, expect time to oscillate around the actual time
|
||||||
// by SERVER_TICK (33.3ms)
|
// by SERVER_TICK (33.3ms)
|
||||||
let old_time = self.state.ecs().read_resource::<Time>().0;
|
let old_time = self.state.ecs().read_resource::<Time>().0;
|
||||||
@ -2265,9 +2455,9 @@ impl Client {
|
|||||||
self.state.ecs().write_resource::<Time>().0 = time.0;
|
self.state.ecs().write_resource::<Time>().0 = time.0;
|
||||||
if diff > 0.0 {
|
if diff > 0.0 {
|
||||||
tracing::warn!(?old_time, ?diff, "Time was reverted by server");
|
tracing::warn!(?old_time, ?diff, "Time was reverted by server");
|
||||||
let rewind_time = self.inter_tick_rewind_time.unwrap_or_default()
|
let rewind_time = self.inter_tick_reverted_time.unwrap_or_default()
|
||||||
+ Duration::from_secs_f64(diff);
|
+ Duration::from_secs_f64(diff);
|
||||||
self.inter_tick_rewind_time = Some(rewind_time);
|
self.inter_tick_reverted_time = Some(rewind_time);
|
||||||
} else {
|
} else {
|
||||||
tracing::warn!(?old_time, ?diff, "Time was advanced by server");
|
tracing::warn!(?old_time, ?diff, "Time was advanced by server");
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ use hashbrown::HashSet;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, DenseVecStorage};
|
use specs::{Component, DenseVecStorage};
|
||||||
use std::{collections::VecDeque, time::Duration};
|
use std::{collections::VecDeque, time::Duration};
|
||||||
|
use vek::Vec3;
|
||||||
|
|
||||||
pub type ControlCommands = VecDeque<ControlCommand>;
|
pub type ControlCommands = VecDeque<ControlCommand>;
|
||||||
|
|
||||||
@ -240,7 +241,7 @@ impl RemoteController {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let mut result = Controller::default();
|
let mut result = Controller::default();
|
||||||
let mut look_dir = result.inputs.look_dir.to_vec();
|
let mut look_dir = Vec3::default(); // explicitly set to 0/0/0, as Dir::default ist 0/1/0
|
||||||
//if self.commands[start_i].source_time
|
//if self.commands[start_i].source_time
|
||||||
// Inputs are averaged over all elements by time
|
// Inputs are averaged over all elements by time
|
||||||
// Queued Inputs are just added
|
// Queued Inputs are just added
|
||||||
@ -292,9 +293,14 @@ impl RemoteController {
|
|||||||
}) {
|
}) {
|
||||||
tracing::error!("jump detencted");
|
tracing::error!("jump detencted");
|
||||||
}
|
}
|
||||||
|
let look_dir = if !look_dir.is_approx_zero() {
|
||||||
|
look_dir.normalized()
|
||||||
|
} else {
|
||||||
|
Dir::default().to_vec()
|
||||||
|
};
|
||||||
result.inputs.move_dir /= dt.as_secs_f32();
|
result.inputs.move_dir /= dt.as_secs_f32();
|
||||||
result.inputs.move_z /= dt.as_secs_f32();
|
result.inputs.move_z /= dt.as_secs_f32();
|
||||||
result.inputs.look_dir = Dir::new(look_dir.normalized());
|
result.inputs.look_dir = Dir::new(look_dir);
|
||||||
|
|
||||||
Some(result)
|
Some(result)
|
||||||
}
|
}
|
||||||
@ -307,8 +313,11 @@ impl RemoteController {
|
|||||||
pub fn avg_latency(&self) -> Duration { self.avg_latency }
|
pub fn avg_latency(&self) -> Duration { self.avg_latency }
|
||||||
|
|
||||||
pub fn simulate_ahead(&self) -> Duration {
|
pub fn simulate_ahead(&self) -> Duration {
|
||||||
const FIXED_OFFSET: Duration = Duration::from_millis(0);
|
//const FIXED_OFFSET: Duration = Duration::from_millis(0);
|
||||||
self.avg_latency() + FIXED_OFFSET
|
//self.avg_latency() + FIXED_OFFSET
|
||||||
|
// TODO:: mocked, as we use it internally for the new input functions and assume
|
||||||
|
// that time - simulate ahead = server time iirc
|
||||||
|
Duration::from_millis(200)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,6 +422,11 @@ mod tests {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prepare_send(command: &mut ControlCommand, monotinic_time: Duration, simulate_ahead: f64) {
|
||||||
|
command.first_send_monotonic_time = Some(monotinic_time);
|
||||||
|
command.first_send_simulate_ahead_time = Some(simulate_ahead);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn resend_data() {
|
fn resend_data() {
|
||||||
let data = generate_control_cmds(5);
|
let data = generate_control_cmds(5);
|
||||||
@ -467,6 +481,26 @@ mod tests {
|
|||||||
assert_eq!(list.commands[3].id, 6);
|
assert_eq!(list.commands[3].id, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dropping_all_commands_when_then_become_outdated() {
|
||||||
|
let data = generate_control_cmds(7);
|
||||||
|
let mut list = RemoteController::default();
|
||||||
|
assert_eq!(list.push(data[0].clone()), Some(1));
|
||||||
|
assert_eq!(list.push(data[1].clone()), Some(2));
|
||||||
|
assert_eq!(list.push(data[2].clone()), Some(3));
|
||||||
|
assert_eq!(list.push(data[3].clone()), Some(4));
|
||||||
|
assert_eq!(list.push(data[4].clone()), Some(5));
|
||||||
|
assert_eq!(list.push(data[5].clone()), Some(6));
|
||||||
|
assert_eq!(list.push(data[6].clone()), Some(7));
|
||||||
|
assert_eq!(list.commands.len(), 7);
|
||||||
|
list.maintain(Some(Duration::from_millis(0)));
|
||||||
|
assert_eq!(list.commands.len(), 7);
|
||||||
|
list.maintain(Some(INCREASE * 2));
|
||||||
|
assert_eq!(list.commands.len(), 5);
|
||||||
|
list.maintain(Some(INCREASE * 7));
|
||||||
|
assert_eq!(list.commands.len(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn acked() {
|
fn acked() {
|
||||||
let data = generate_control_cmds(7);
|
let data = generate_control_cmds(7);
|
||||||
@ -477,18 +511,23 @@ mod tests {
|
|||||||
assert_eq!(list.push(data[3].clone()), Some(4));
|
assert_eq!(list.push(data[3].clone()), Some(4));
|
||||||
assert_eq!(list.push(data[4].clone()), Some(5));
|
assert_eq!(list.push(data[4].clone()), Some(5));
|
||||||
let mut to_export = list.commands().iter().map(|e| e.id).collect::<HashSet<_>>();
|
let mut to_export = list.commands().iter().map(|e| e.id).collect::<HashSet<_>>();
|
||||||
|
prepare_send(&mut list.commands[0], Duration::from_millis(100), 200.0);
|
||||||
|
prepare_send(&mut list.commands[1], Duration::from_millis(100), 200.0);
|
||||||
|
prepare_send(&mut list.commands[2], Duration::from_millis(100), 200.0);
|
||||||
|
prepare_send(&mut list.commands[3], Duration::from_millis(100), 200.0);
|
||||||
|
prepare_send(&mut list.commands[4], Duration::from_millis(100), 200.0);
|
||||||
// damange one entry
|
// damange one entry
|
||||||
to_export.remove(&3);
|
to_export.remove(&3);
|
||||||
list.acked(to_export, Duration::from_secs(6));
|
list.acked(to_export, Duration::from_secs(6), 200.0);
|
||||||
|
list.maintain(Some(Duration::from_millis(1000)));
|
||||||
assert_eq!(list.push(data[5].clone()), Some(6));
|
assert_eq!(list.push(data[5].clone()), Some(6));
|
||||||
assert_eq!(list.push(data[6].clone()), Some(7));
|
assert_eq!(list.push(data[6].clone()), Some(7));
|
||||||
println!("asd{:?}", &list);
|
println!("asd{:?}", &list);
|
||||||
|
|
||||||
let to_export = list.commands().clone();
|
let to_export = list.commands().clone();
|
||||||
assert_eq!(to_export.len(), 3);
|
assert_eq!(to_export.len(), 2);
|
||||||
assert_eq!(to_export[0].id, 3);
|
assert_eq!(to_export[0].id, 6);
|
||||||
assert_eq!(to_export[1].id, 6);
|
assert_eq!(to_export[1].id, 7);
|
||||||
assert_eq!(to_export[2].id, 7);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1026,6 +1026,18 @@ pub fn handle_jump(
|
|||||||
strength: f32,
|
strength: f32,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
common_base::plot!("jumps", 0.0);
|
common_base::plot!("jumps", 0.0);
|
||||||
|
let x = if input_is_pressed(data, InputKind::Jump) {
|
||||||
|
1.0
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
common_base::plot!("jumps_pressed", x);
|
||||||
|
let y = if data.physics.on_ground.is_some() {
|
||||||
|
1.0
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
common_base::plot!("jumps_ground", y);
|
||||||
(input_is_pressed(data, InputKind::Jump) && data.physics.on_ground.is_some())
|
(input_is_pressed(data, InputKind::Jump) && data.physics.on_ground.is_some())
|
||||||
.then(|| data.body.jump_impulse())
|
.then(|| data.body.jump_impulse())
|
||||||
.flatten()
|
.flatten()
|
||||||
|
@ -604,7 +604,7 @@ impl State {
|
|||||||
let delta_time = self.ecs.read_resource::<DeltaTime>().0;
|
let delta_time = self.ecs.read_resource::<DeltaTime>().0;
|
||||||
|
|
||||||
const MAX_INCREMENTS: usize = 100; // The maximum number of collision tests per tick
|
const MAX_INCREMENTS: usize = 100; // The maximum number of collision tests per tick
|
||||||
const STEP_SEC: f64 = 0.1;
|
const STEP_SEC: f64 = 0.04;
|
||||||
let increments =
|
let increments =
|
||||||
((simulate_ahead.as_secs_f64() / STEP_SEC).ceil() as usize).clamped(1, MAX_INCREMENTS);
|
((simulate_ahead.as_secs_f64() / STEP_SEC).ceil() as usize).clamped(1, MAX_INCREMENTS);
|
||||||
for _i in 0..increments {
|
for _i in 0..increments {
|
||||||
@ -691,6 +691,7 @@ impl State {
|
|||||||
LocalEvent::Jump(entity, impulse) => {
|
LocalEvent::Jump(entity, impulse) => {
|
||||||
if let Some(vel) = velocities.get_mut(entity) {
|
if let Some(vel) = velocities.get_mut(entity) {
|
||||||
vel.0.z = impulse + physics.get(entity).map_or(0.0, |ps| ps.ground_vel.z);
|
vel.0.z = impulse + physics.get(entity).map_or(0.0, |ps| ps.ground_vel.z);
|
||||||
|
common_base::plot!("state_jump_event", impulse as f64);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
LocalEvent::ApplyImpulse { entity, impulse } => {
|
LocalEvent::ApplyImpulse { entity, impulse } => {
|
||||||
|
@ -637,6 +637,8 @@ impl<'a> PhysicsData<'a> {
|
|||||||
.terrain
|
.terrain
|
||||||
.contains_key(read.terrain.pos_key(pos.0.map(|e| e.floor() as i32)));
|
.contains_key(read.terrain.pos_key(pos.0.map(|e| e.floor() as i32)));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Apply physics only if in a loaded chunk
|
// Apply physics only if in a loaded chunk
|
||||||
if in_loaded_chunk
|
if in_loaded_chunk
|
||||||
// And not already stuck on a block (e.g., for arrows)
|
// And not already stuck on a block (e.g., for arrows)
|
||||||
@ -1174,6 +1176,10 @@ impl<'a> PhysicsData<'a> {
|
|||||||
}
|
}
|
||||||
physics_state.on_ground =
|
physics_state.on_ground =
|
||||||
physics_state.on_ground.or(physics_state_delta.on_ground);
|
physics_state.on_ground.or(physics_state_delta.on_ground);
|
||||||
|
common_base::plot!(
|
||||||
|
"on_ground_1",
|
||||||
|
physics_state.on_ground.map(|_| 1.0f64).unwrap_or_default()
|
||||||
|
);
|
||||||
physics_state.on_ceiling |= physics_state_delta.on_ceiling;
|
physics_state.on_ceiling |= physics_state_delta.on_ceiling;
|
||||||
physics_state.on_wall = physics_state.on_wall.or_else(|| {
|
physics_state.on_wall = physics_state.on_wall.or_else(|| {
|
||||||
physics_state_delta
|
physics_state_delta
|
||||||
@ -1431,6 +1437,10 @@ fn box_voxel_collision<T: BaseVol<Vox = Block> + ReadVol>(
|
|||||||
let z_range = z_min..z_max;
|
let z_range = z_min..z_max;
|
||||||
|
|
||||||
// Setup values for the loop below
|
// Setup values for the loop below
|
||||||
|
common_base::plot!(
|
||||||
|
"on_ground_2",
|
||||||
|
physics_state.on_ground.map(|_| 1.0f64).unwrap_or_default()
|
||||||
|
);
|
||||||
physics_state.on_ground = None;
|
physics_state.on_ground = None;
|
||||||
physics_state.on_ceiling = false;
|
physics_state.on_ceiling = false;
|
||||||
|
|
||||||
@ -1441,8 +1451,6 @@ fn box_voxel_collision<T: BaseVol<Vox = Block> + ReadVol>(
|
|||||||
|
|
||||||
let mut pos_delta = tgt_pos - pos.0;
|
let mut pos_delta = tgt_pos - pos.0;
|
||||||
|
|
||||||
common_base::plot!("z", pos.0.z as f64);
|
|
||||||
|
|
||||||
// Don't jump too far at once
|
// Don't jump too far at once
|
||||||
const MAX_INCREMENTS: usize = 100; // The maximum number of collision tests per tick
|
const MAX_INCREMENTS: usize = 100; // The maximum number of collision tests per tick
|
||||||
let increments = ((pos_delta.map(|e| e.abs()).reduce_partial_max() / 0.3).ceil() as usize)
|
let increments = ((pos_delta.map(|e| e.abs()).reduce_partial_max() / 0.3).ceil() as usize)
|
||||||
@ -1607,6 +1615,7 @@ fn box_voxel_collision<T: BaseVol<Vox = Block> + ReadVol>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if on_ground.is_some() {
|
if on_ground.is_some() {
|
||||||
|
common_base::plot!("on_ground_3", on_ground.map(|_| 1.0f64).unwrap_or_default());
|
||||||
physics_state.on_ground = on_ground;
|
physics_state.on_ground = on_ground;
|
||||||
// If the space below us is free, then "snap" to the ground
|
// If the space below us is free, then "snap" to the ground
|
||||||
} else if vel.0.z <= 0.0 && was_on_ground && block_snap && {
|
} else if vel.0.z <= 0.0 && was_on_ground && block_snap && {
|
||||||
@ -1632,6 +1641,10 @@ fn box_voxel_collision<T: BaseVol<Vox = Block> + ReadVol>(
|
|||||||
.get(Vec3::new(pos.0.x, pos.0.y, pos.0.z - 0.01).map(|e| e.floor() as i32))
|
.get(Vec3::new(pos.0.x, pos.0.y, pos.0.z - 0.01).map(|e| e.floor() as i32))
|
||||||
.ok()
|
.ok()
|
||||||
.copied();
|
.copied();
|
||||||
|
common_base::plot!(
|
||||||
|
"on_ground_4",
|
||||||
|
physics_state.on_ground.map(|_| 1.0f64).unwrap_or_default()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find liquid immersion and wall collision all in one round of iteration
|
// Find liquid immersion and wall collision all in one round of iteration
|
||||||
|
@ -60,7 +60,21 @@ impl<'a> System<'a> for Sys {
|
|||||||
let r = remote_controller.compress(time, dt);
|
let r = remote_controller.compress(time, dt);
|
||||||
// Do nothing when already populated and we dont have a new value
|
// Do nothing when already populated and we dont have a new value
|
||||||
if let Some(r) = r {
|
if let Some(r) = r {
|
||||||
*controller = r.clone()
|
*controller = r.clone();
|
||||||
|
let mut action = 0.0;
|
||||||
|
for a in r.actions {
|
||||||
|
if let common::comp::ControlAction::StartInput {
|
||||||
|
input,
|
||||||
|
target_entity,
|
||||||
|
select_pos,
|
||||||
|
} = a
|
||||||
|
{
|
||||||
|
if input == common::comp::InputKind::Jump {
|
||||||
|
action = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
common_base::plot!("action_contains_jump", action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user