Fixed timestamps! (use them to fix networking)

This commit is contained in:
griffi-gh 2023-05-20 15:59:52 +02:00
parent 7ab7a36d85
commit 0affc06e09
3 changed files with 56 additions and 5 deletions

View file

@ -0,0 +1,45 @@
use shipyard::{Workload, WorkloadModificator, Unique, AllStoragesView, UniqueViewMut, IntoWorkload};
use hashbrown::HashMap;
use std::time::{Duration, Instant};
use nohash_hasher::BuildNoHashHasher;
#[derive(Unique)]
#[repr(transparent)]
struct FixedTimestampStorage(HashMap<u32, Instant, BuildNoHashHasher<u32>>);
impl FixedTimestampStorage {
pub fn new() -> Self {
Self(HashMap::with_capacity_and_hasher(16, BuildNoHashHasher::default()))
}
}
impl Default for FixedTimestampStorage {
fn default() -> Self {
Self::new()
}
}
pub trait FixedTimestamp {
fn make_fixed(self, rate_millis: u16, unique_id: u16) -> Self;
}
impl FixedTimestamp for Workload {
fn make_fixed(self, rate_millis: u16, unique_id: u16) -> Self {
let key = (rate_millis as u32) | ((unique_id as u32) << 16);
let duration = Duration::from_millis(rate_millis as u64);
(self,).into_workload().run_if(move |mut timestamps: UniqueViewMut<FixedTimestampStorage>| {
let Some(t) = timestamps.0.get_mut(&key) else {
timestamps.0.insert_unique_unchecked(key, Instant::now());
return true
};
if t.elapsed() >= duration {
*t = Instant::now();
return true
}
false
})
}
}
pub fn init_fixed_timestamp_storage(
storages: AllStoragesView
) {
storages.add_unique(FixedTimestampStorage::new());
}

View file

@ -41,6 +41,7 @@ pub(crate) mod init;
pub(crate) mod color;
pub(crate) mod loading_screen;
pub(crate) mod connecting_screen;
pub(crate) mod fixed_timestamp;
use world::{
init_game_world,
@ -83,6 +84,7 @@ use init::initialize_from_args;
use gui::{render_gui, init_gui, update_gui};
use loading_screen::update_loading_screen;
use connecting_screen::switch_to_loading_if_connected;
use fixed_timestamp::init_fixed_timestamp_storage;
/// stuff required to init the renderer and other basic systems
fn pre_startup() -> Workload {
@ -93,6 +95,7 @@ fn pre_startup() -> Workload {
fn startup() -> Workload {
(
init_fixed_timestamp_storage,
initial_resize_event,
init_window_size,
load_prefabs,
@ -119,7 +122,7 @@ fn update() -> Workload {
spawn_player.run_if_storage_empty::<MainPlayer>(),
).into_sequential_workload().run_if(is_singleplayer),
).into_sequential_workload().run_if(is_ingame_or_loading),
update_networking.run_if(is_multiplayer),
update_networking().run_if(is_multiplayer),
(
switch_to_loading_if_connected
).into_sequential_workload().run_if(is_connecting),

View file

@ -14,7 +14,8 @@ use crate::{
events::EventComponent,
control_flow::SetControlFlow,
world::tasks::ChunkTaskManager,
state::is_ingame_or_loading
state::is_ingame_or_loading,
fixed_timestamp::FixedTimestamp
};
mod handshake;
@ -34,9 +35,11 @@ use world::{
use player::{
init_client_map,
send_player_movement_events,
receive_player_movement_events,
receive_player_connect_events
};
use self::player::{receive_player_movement_events, receive_player_connect_events};
const NET_TICKRATE: u16 = 33;
#[derive(Unique, Clone, Copy, PartialEq, Eq)]
pub enum GameType {
@ -119,7 +122,7 @@ pub fn update_networking() -> Workload {
(
init_client_map.run_if_missing_unique::<ClientIdMap>(),
connect_client.run_if_missing_unique::<UdpClient>(),
poll_client,
poll_client.into_workload().make_fixed(NET_TICKRATE, 0),
(
set_client_join_state_to_connected,
say_hello,
@ -147,7 +150,7 @@ pub fn update_networking_late() -> Workload {
send_block_place_events,
send_player_movement_events,
).into_workload().run_if(is_join_state::<{ClientJoinState::Joined as u8}>),
flush_client,
flush_client.into_workload().make_fixed(NET_TICKRATE, 1)
).into_sequential_workload()
}