mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
sync - introduceconcept of a rewind_tick
This commit is contained in:
parent
4343dd3aea
commit
820b3f06b0
@ -39,7 +39,7 @@ use common::{
|
||||
mounting::Rider,
|
||||
outcome::Outcome,
|
||||
recipe::{ComponentRecipeBook, RecipeBook},
|
||||
resources::{DeltaTime, GameMode, MonotonicTime, PlayerEntity, Time, TimeOfDay},
|
||||
resources::{MonotonicTime, GameMode, PlayerEntity, Time, TimeOfDay},
|
||||
spiral::Spiral2d,
|
||||
terrain::{
|
||||
block::Block, map::MapConfig, neighbors, site::DungeonKindMeta, BiomeKind,
|
||||
@ -64,7 +64,7 @@ use common_net::{
|
||||
sync::WorldSyncExt,
|
||||
};
|
||||
use common_state::State;
|
||||
use common_systems::add_local_systems;
|
||||
use common_systems::{add_local_systems, add_rewind_systems};
|
||||
use comp::BuffKind;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use image::DynamicImage;
|
||||
@ -237,6 +237,7 @@ pub struct Client {
|
||||
|
||||
local_command_gen: CommandGenerator,
|
||||
next_control: Controller,
|
||||
inter_tick_rewind_time: Option<Duration>,
|
||||
|
||||
network: Option<Network>,
|
||||
participant: Option<Participant>,
|
||||
@ -721,6 +722,7 @@ impl Client {
|
||||
|
||||
local_command_gen: CommandGenerator::default(),
|
||||
next_control: Controller::default(),
|
||||
inter_tick_rewind_time: None,
|
||||
|
||||
network: Some(network),
|
||||
participant: Some(participant),
|
||||
@ -1699,6 +1701,7 @@ impl Client {
|
||||
|
||||
// 1) Build up a list of events for this frame, to be passed to the frontend.
|
||||
let mut frontend_events = Vec::new();
|
||||
self.inter_tick_rewind_time = None;
|
||||
|
||||
// Prepare for new events
|
||||
{
|
||||
@ -1728,6 +1731,36 @@ impl Client {
|
||||
// Handle new messages from the server.
|
||||
frontend_events.append(&mut self.handle_new_messages()?);
|
||||
|
||||
// Simulate Ahead
|
||||
if let Some(_rewind_time) = self.inter_tick_rewind_time {
|
||||
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();
|
||||
let simulate_ahead = simulate_ahead.max(dt) - dt;
|
||||
tracing::warn!(?simulate_ahead, ?dt, "simulating ahead again");
|
||||
self.state.rewind_tick(
|
||||
simulate_ahead.max(dt) - dt,
|
||||
|dispatch_builder| {
|
||||
add_rewind_systems(dispatch_builder);
|
||||
},
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
self.state.tick(
|
||||
dt,
|
||||
|dispatch_builder| {
|
||||
add_local_systems(dispatch_builder);
|
||||
add_foreign_systems(dispatch_builder);
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
// 2) Handle input from frontend.
|
||||
// Pass character actions from frontend input to the player's entity.
|
||||
if self.presence.is_some() {
|
||||
@ -2158,17 +2191,17 @@ impl Client {
|
||||
prof_span!("handle_server_in_game_msg");
|
||||
match msg {
|
||||
ServerGeneral::TimeSync(time) => {
|
||||
let dt = self.state.ecs().read_resource::<DeltaTime>().0 as f64;
|
||||
let simulate_ahead = self
|
||||
.state
|
||||
.ecs()
|
||||
.read_storage::<RemoteController>()
|
||||
.get(self.entity())
|
||||
.map(|rc| rc.simulate_ahead())
|
||||
.unwrap_or_default();
|
||||
//remove dt as it is applied in state.tick again
|
||||
self.state.ecs().write_resource::<Time>().0 =
|
||||
time.0 + simulate_ahead.as_secs_f64() - dt;
|
||||
let old_time = self.state.ecs().read_resource::<Time>().0;
|
||||
let diff = old_time - time.0;
|
||||
self.state.ecs().write_resource::<Time>().0 = time.0;
|
||||
if diff > 0.0 {
|
||||
tracing::warn!(?old_time, ?diff, "Time was reverted by server");
|
||||
let rewind_time = self.inter_tick_rewind_time.unwrap_or_default()
|
||||
+ Duration::from_secs_f64(diff);
|
||||
self.inter_tick_rewind_time = Some(rewind_time);
|
||||
} else {
|
||||
tracing::warn!(?old_time, ?diff, "Time was advanced by server");
|
||||
}
|
||||
},
|
||||
ServerGeneral::AckControl(acked_ids, _time) => {
|
||||
if let Some(remote_controller) = self
|
||||
|
@ -590,6 +590,28 @@ impl State {
|
||||
self.ecs.write_resource::<TerrainChanges>().modified_blocks = modified_blocks;
|
||||
}
|
||||
|
||||
/// Rewind local changes after the server send some old state
|
||||
pub fn rewind_tick(
|
||||
&mut self,
|
||||
simulate_ahead: Duration,
|
||||
add_systems: impl Fn(&mut DispatcherBuilder),
|
||||
update_terrain_and_regions: bool,
|
||||
) {
|
||||
let time_of_day = self.ecs.read_resource::<TimeOfDay>().0;
|
||||
let _time = self.ecs.read_resource::<Time>().0;
|
||||
let monotonic_time = self.ecs.read_resource::<MonotonicTime>().0;
|
||||
let delta_time = self.ecs.read_resource::<DeltaTime>().0;
|
||||
|
||||
self.tick(simulate_ahead, add_systems, update_terrain_and_regions);
|
||||
|
||||
// rewind changes
|
||||
|
||||
self.ecs.write_resource::<TimeOfDay>().0 = time_of_day;
|
||||
//self.ecs.write_resource::<Time>().0 = time;
|
||||
self.ecs.write_resource::<MonotonicTime>().0 = monotonic_time;
|
||||
self.ecs.write_resource::<DeltaTime>().0 = delta_time;
|
||||
}
|
||||
|
||||
/// Execute a single tick, simulating the game state by the given duration.
|
||||
pub fn tick(
|
||||
&mut self,
|
||||
|
@ -39,3 +39,23 @@ pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
|
||||
dispatch::<beam::Sys>(dispatch_builder, &[&phys::Sys::sys_name()]);
|
||||
dispatch::<aura::Sys>(dispatch_builder, &[]);
|
||||
}
|
||||
|
||||
pub fn add_rewind_systems(dispatch_builder: &mut DispatcherBuilder) {
|
||||
//TODO: don't run interpolation on server
|
||||
dispatch::<interpolation::Sys>(dispatch_builder, &[]);
|
||||
dispatch::<mount::Sys>(dispatch_builder, &[]);
|
||||
dispatch::<controller::Sys>(dispatch_builder, &[&mount::Sys::sys_name()]);
|
||||
dispatch::<character_behavior::Sys>(dispatch_builder, &[&controller::Sys::sys_name()]);
|
||||
dispatch::<buff::Sys>(dispatch_builder, &[]);
|
||||
dispatch::<stats::Sys>(dispatch_builder, &[&buff::Sys::sys_name()]);
|
||||
dispatch::<phys::Sys>(dispatch_builder, &[
|
||||
&interpolation::Sys::sys_name(),
|
||||
&controller::Sys::sys_name(),
|
||||
&mount::Sys::sys_name(),
|
||||
&stats::Sys::sys_name(),
|
||||
]);
|
||||
dispatch::<projectile::Sys>(dispatch_builder, &[&phys::Sys::sys_name()]);
|
||||
dispatch::<shockwave::Sys>(dispatch_builder, &[&phys::Sys::sys_name()]);
|
||||
dispatch::<beam::Sys>(dispatch_builder, &[&phys::Sys::sys_name()]);
|
||||
dispatch::<aura::Sys>(dispatch_builder, &[]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user