Skip to content

Commit

Permalink
Release 0.17 (#141)
Browse files Browse the repository at this point in the history
- This release is mostly an internal refactor although some APIs have changed.
- Tick/Time synchronization has been completely re-written, and now the Server & Client clocks should be within 1 milliseconds of eachother.
- Another major change is that the synchronization will be resilient to the Server app is running slower than intended. Client time should slow down and speed up seamlessly with the Server.
- Now the Client/Server has a new step in the handshake process which allows them to collect network stats and get in sync before returning a Connect Event and giving control to your app.
-Sending and receiving messages on a TickBufferedChannel now requires a new API so that the app can specify with which Tick the message should be associated. Now use `Client.send_tick_buffered_message(tick, message)` and `Server.receive_tick_buffered_messages(tick)` for TickBuffered channels.
- The API now recognizes that there are two moments in time the Client must be aware of: the authoritative time of the Server, and the time of the Client which is predicted forward into the future. Therefore now there are `Client.client_tick()`, `Client.client_interpolation()`, `Client.server_tick()`, and `Client.server_interpolation()` methods for use.
- In the Bevy adapter crates now, instead of the strange conditional `Tick` stage, there is a Tick event which is triggered from an EventReader like the other Bevy events.
  • Loading branch information
connorcarpenter authored Feb 24, 2023
1 parent 8bb3c91 commit ec5bf55
Show file tree
Hide file tree
Showing 87 changed files with 2,519 additions and 1,599 deletions.
32 changes: 22 additions & 10 deletions adapters/bevy/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use bevy_ecs::{
use naia_client::{Client as NaiaClient, EntityRef, NaiaClientError};

use naia_bevy_shared::{
Channel, EntityDoesNotExistError, EntityHandle, EntityHandleConverter, Message, WorldProxy,
WorldRef,
Channel, EntityDoesNotExistError, EntityHandle, EntityHandleConverter, Message, Tick,
WorldProxy, WorldRef,
};

use super::state::State;
Expand Down Expand Up @@ -69,15 +69,13 @@ impl<'a> Client<'a> {
self.client.jitter()
}

// Interpolation

pub fn interpolation(&self) -> Option<f32> {
self.client.interpolation()
}

//// Messages ////
pub fn send_message<C: Channel, M: Message>(&mut self, message: &M) {
self.client.send_message::<C, M>(message)
self.client.send_message::<C, M>(message);
}

pub fn send_tick_buffer_message<C: Channel, M: Message>(&mut self, tick: &Tick, message: &M) {
self.client.send_tick_buffer_message::<C, M>(tick, message);
}

//// Entities ////
Expand All @@ -92,9 +90,23 @@ impl<'a> Client<'a> {

//// Ticks ////

pub fn client_tick(&self) -> Option<u16> {
pub fn client_tick(&self) -> Option<Tick> {
self.client.client_tick()
}

pub fn server_tick(&self) -> Option<Tick> {
self.client.server_tick()
}

// Interpolation

pub fn client_interpolation(&self) -> Option<f32> {
self.client.client_interpolation()
}

pub fn server_interpolation(&self) -> Option<f32> {
self.client.server_interpolation()
}
}

impl<'a> SystemParam for Client<'a> {
Expand Down
6 changes: 6 additions & 0 deletions adapters/bevy/client/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ impl MessageEvents {
}
}

// ClientTickEvent
pub struct ClientTickEvent(pub Tick);

// ServerTickEvent
pub struct ServerTickEvent(pub Tick);

// SpawnEntityEvent
pub struct SpawnEntityEvent(pub Entity);

Expand Down
1 change: 0 additions & 1 deletion adapters/bevy/client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ pub mod events;
mod client;
mod commands;
mod plugin;
mod resource;
mod stage;
mod state;
mod systems;
Expand Down
25 changes: 7 additions & 18 deletions adapters/bevy/client/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ use naia_bevy_shared::Protocol;

use super::{
events::{
ConnectEvent, DespawnEntityEvent, DisconnectEvent, ErrorEvent, InsertComponentEvents,
MessageEvents, RejectEvent, RemoveComponentEvents, SpawnEntityEvent, UpdateComponentEvents,
ClientTickEvent, ConnectEvent, DespawnEntityEvent, DisconnectEvent, ErrorEvent,
InsertComponentEvents, MessageEvents, RejectEvent, RemoveComponentEvents, ServerTickEvent,
SpawnEntityEvent, UpdateComponentEvents,
},
resource::ClientResource,
stage::{PrivateStage, Stage},
systems::{before_receive_events, finish_tick, should_receive, should_tick},
systems::{before_receive_events, should_receive},
};

struct PluginConfig {
Expand Down Expand Up @@ -56,12 +56,13 @@ impl PluginType for Plugin {
app
// RESOURCES //
.insert_resource(client)
.init_resource::<ClientResource>()
// EVENTS //
.add_event::<ConnectEvent>()
.add_event::<DisconnectEvent>()
.add_event::<RejectEvent>()
.add_event::<ErrorEvent>()
.add_event::<ClientTickEvent>()
.add_event::<ServerTickEvent>()
.add_event::<MessageEvents>()
.add_event::<SpawnEntityEvent>()
.add_event::<DespawnEntityEvent>()
Expand All @@ -80,19 +81,7 @@ impl PluginType for Plugin {
Stage::ReceiveEvents,
SystemStage::single_threaded().with_run_criteria(should_receive),
)
// tick //
.add_stage_after(
CoreStage::PostUpdate,
Stage::Tick,
SystemStage::single_threaded().with_run_criteria(should_tick),
)
.add_stage_after(
Stage::Tick,
PrivateStage::AfterTick,
SystemStage::parallel().with_run_criteria(should_tick),
)
// SYSTEMS //
.add_system_to_stage(PrivateStage::BeforeReceiveEvents, before_receive_events)
.add_system_to_stage(PrivateStage::AfterTick, finish_tick);
.add_system_to_stage(PrivateStage::BeforeReceiveEvents, before_receive_events);
}
}
13 changes: 0 additions & 13 deletions adapters/bevy/client/src/resource.rs

This file was deleted.

2 changes: 0 additions & 2 deletions adapters/bevy/client/src/stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ use bevy_ecs::schedule::StageLabel;
#[derive(Debug, Clone, PartialEq, Eq, Hash, StageLabel)]
pub enum Stage {
ReceiveEvents,
Tick,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, StageLabel)]
pub enum PrivateStage {
BeforeReceiveEvents,
AfterTick,
}
204 changes: 100 additions & 104 deletions adapters/bevy/client/src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use bevy_ecs::event::Events;
use bevy_ecs::{
entity::Entity,
schedule::ShouldRun,
system::{Res, ResMut},
system::Res,
world::{Mut, World},
};

Expand All @@ -12,122 +12,118 @@ use naia_bevy_shared::WorldProxyMut;

mod naia_events {
pub use naia_client::{
ConnectEvent, DespawnEntityEvent, DisconnectEvent, ErrorEvent, InsertComponentEvent,
MessageEvent, RejectEvent, RemoveComponentEvent, SpawnEntityEvent, TickEvent,
UpdateComponentEvent,
ClientTickEvent, ConnectEvent, DespawnEntityEvent, DisconnectEvent, ErrorEvent,
InsertComponentEvent, MessageEvent, RejectEvent, RemoveComponentEvent, ServerTickEvent,
SpawnEntityEvent, UpdateComponentEvent,
};
}

mod bevy_events {
pub use crate::events::{
ConnectEvent, DespawnEntityEvent, DisconnectEvent, ErrorEvent, InsertComponentEvents,
MessageEvents, RejectEvent, RemoveComponentEvents, SpawnEntityEvent, UpdateComponentEvents,
ClientTickEvent, ConnectEvent, DespawnEntityEvent, DisconnectEvent, ErrorEvent,
InsertComponentEvents, MessageEvents, RejectEvent, RemoveComponentEvents, ServerTickEvent,
SpawnEntityEvent, UpdateComponentEvents,
};
}

use crate::resource::ClientResource;

pub fn before_receive_events(world: &mut World) {
world.resource_scope(|world, mut client: Mut<Client<Entity>>| {
world.resource_scope(|world, mut client_resource: Mut<ClientResource>| {
let mut events = client.receive(world.proxy_mut());
if !events.is_empty() {
unsafe {
// Connect Event
let mut connect_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::ConnectEvent>>()
.unwrap();
for _ in events.read::<naia_events::ConnectEvent>() {
connect_event_writer.send(bevy_events::ConnectEvent);
}

// Disconnect Event
let mut disconnect_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::DisconnectEvent>>()
.unwrap();
for _ in events.read::<naia_events::DisconnectEvent>() {
disconnect_event_writer.send(bevy_events::DisconnectEvent);
}

// Reject Event
let mut reject_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::RejectEvent>>()
.unwrap();
for _ in events.read::<naia_events::RejectEvent>() {
reject_event_writer.send(bevy_events::RejectEvent);
}

// Tick Event
for _ in events.read::<naia_events::TickEvent>() {
client_resource.ticker.set();
}

// Error Event
let mut error_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::ErrorEvent>>()
.unwrap();
for error in events.read::<naia_events::ErrorEvent>() {
error_event_writer.send(bevy_events::ErrorEvent(error));
}

// Message Event
let mut message_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::MessageEvents>>()
.unwrap();
message_event_writer.send(bevy_events::MessageEvents::from(&mut events));

// Spawn Entity Event
let mut spawn_entity_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::SpawnEntityEvent>>()
.unwrap();
for entity in events.read::<naia_events::SpawnEntityEvent>() {
spawn_entity_event_writer.send(bevy_events::SpawnEntityEvent(entity));
}

// Despawn Entity Event
let mut despawn_entity_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::DespawnEntityEvent>>()
.unwrap();
for entity in events.read::<naia_events::DespawnEntityEvent>() {
despawn_entity_event_writer.send(bevy_events::DespawnEntityEvent(entity));
}

// Insert Component Event
let mut insert_component_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::InsertComponentEvents>>()
.unwrap();
insert_component_event_writer
.send(bevy_events::InsertComponentEvents::from(&mut events));

// Update Component Event
let mut update_component_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::UpdateComponentEvents>>()
.unwrap();
update_component_event_writer
.send(bevy_events::UpdateComponentEvents::from(&mut events));

// Remove Component Event
let mut remove_component_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::RemoveComponentEvents>>()
.unwrap();
remove_component_event_writer
.send(bevy_events::RemoveComponentEvents::from(&mut events));
let mut events = client.receive(world.proxy_mut());
if !events.is_empty() {
unsafe {
// Connect Event
let mut connect_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::ConnectEvent>>()
.unwrap();
for _ in events.read::<naia_events::ConnectEvent>() {
connect_event_writer.send(bevy_events::ConnectEvent);
}
}
});
});
}

pub fn should_tick(resource: Res<ClientResource>) -> ShouldRun {
if resource.ticker.is_set() {
ShouldRun::Yes
} else {
ShouldRun::No
}
}
// Disconnect Event
let mut disconnect_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::DisconnectEvent>>()
.unwrap();
for _ in events.read::<naia_events::DisconnectEvent>() {
disconnect_event_writer.send(bevy_events::DisconnectEvent);
}

// Reject Event
let mut reject_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::RejectEvent>>()
.unwrap();
for _ in events.read::<naia_events::RejectEvent>() {
reject_event_writer.send(bevy_events::RejectEvent);
}

pub fn finish_tick(mut resource: ResMut<ClientResource>) {
resource.ticker.reset();
// Error Event
let mut error_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::ErrorEvent>>()
.unwrap();
for error in events.read::<naia_events::ErrorEvent>() {
error_event_writer.send(bevy_events::ErrorEvent(error));
}

// Client Tick Event
let mut client_tick_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::ClientTickEvent>>()
.unwrap();
for tick in events.read::<naia_events::ClientTickEvent>() {
client_tick_event_writer.send(bevy_events::ClientTickEvent(tick));
}

// Server Tick Event
let mut server_tick_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::ServerTickEvent>>()
.unwrap();
for tick in events.read::<naia_events::ServerTickEvent>() {
server_tick_event_writer.send(bevy_events::ServerTickEvent(tick));
}

// Message Event
let mut message_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::MessageEvents>>()
.unwrap();
message_event_writer.send(bevy_events::MessageEvents::from(&mut events));

// Spawn Entity Event
let mut spawn_entity_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::SpawnEntityEvent>>()
.unwrap();
for entity in events.read::<naia_events::SpawnEntityEvent>() {
spawn_entity_event_writer.send(bevy_events::SpawnEntityEvent(entity));
}

// Despawn Entity Event
let mut despawn_entity_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::DespawnEntityEvent>>()
.unwrap();
for entity in events.read::<naia_events::DespawnEntityEvent>() {
despawn_entity_event_writer.send(bevy_events::DespawnEntityEvent(entity));
}

// Insert Component Event
let mut insert_component_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::InsertComponentEvents>>()
.unwrap();
insert_component_event_writer
.send(bevy_events::InsertComponentEvents::from(&mut events));

// Update Component Event
let mut update_component_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::UpdateComponentEvents>>()
.unwrap();
update_component_event_writer
.send(bevy_events::UpdateComponentEvents::from(&mut events));

// Remove Component Event
let mut remove_component_event_writer = world
.get_resource_unchecked_mut::<Events<bevy_events::RemoveComponentEvents>>()
.unwrap();
remove_component_event_writer
.send(bevy_events::RemoveComponentEvents::from(&mut events));
}
}
});
}

pub fn should_receive(client: Res<Client<Entity>>) -> ShouldRun {
Expand Down
Loading

0 comments on commit ec5bf55

Please sign in to comment.