diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f0b3ae..6b410e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,27 @@ Subheadings to categorize changes are `added, changed, deprecated, removed, fixe ## Unreleased +## 0.3.0 + +### added + +- A `prelude` module. + +### changed + +- To fix name conflicts with `AddProtocolExt`, the respective types have changed names. + - The `client` feature trait has changed to `AddClientProtocolExt` + - The `server` feature trait has changed to `AddServerProtocolExt` +- Method names have changed: + - `add_sendonly_protocol` has changed to `add_client_wo_protocol` and `add_server_wo_protocol` + - `add_readonly_bounded_protocol` has changed to `add_client_ro_protocol` and `add_server_ro_protocol` + - `add_readonly_unbounded_protocol` has changed to `add_client_ro_unbounded_protocol` and `add_server_ro_unbounded_protocol` + - `add_bounded_protocol` has changed to `add_client_rw_protocol` and `add_server_rw_protocol` + - `add_unbounded_protocol` has changed to `add_client_rw_unbounded_protocol` and `add_server_rw_unbounded_protocol` +- The `ConnectionRequest` event under the `client` feature has been renamed to `RtcClientRequestEvent` +- The `Payload` derive was renamed to `Protocol` +- Fields on `RtcClientState` and `RtcServerState` are now private, with accessor methods, e.g. `.id()` instead of `.id` + ## 0.2.0 ### added diff --git a/Cargo.toml b/Cargo.toml index 4aa0ec5..d03b598 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ resolver = "2" [workspace.package] edition = "2021" -version = "0.2.0" +version = "0.3.0" license = "MIT OR Apache-2.0" description = "A client-server library designed over WebRTC for Bevy" repository = "https://github.com/loopystudios/bevy_rtc" diff --git a/README.md b/README.md index dd288c5..f7f5e52 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Run the [demos](#demos) and [instructions](#instructions). | bevy | bevy_rtc | |-------|-------------| -| 0.13 | 0.1-0.2, main | +| 0.13 | 0.1-0.3, main | | < 0.13| unsupported | ## Cargo features diff --git a/bevy_rtc/src/client/events.rs b/bevy_rtc/src/client/events.rs index 20127f3..e239d3c 100644 --- a/bevy_rtc/src/client/events.rs +++ b/bevy_rtc/src/client/events.rs @@ -12,8 +12,9 @@ pub enum RtcClientEvent { DisconnectedFromHost { reason: Option }, } +// TODO: This should be a command, e.g. Commands.connect_rtc(addr), Commands.disconnect_rtc #[derive(Debug, Clone, Event)] -pub enum ConnectionRequest { +pub enum RtcClientRequestEvent { /// A request to connect to the server through the signaling server. /// The format of the addr should be ws://host:port or wss://host:port Connect { addr: String }, diff --git a/bevy_rtc/src/client/mod.rs b/bevy_rtc/src/client/mod.rs index 6c97a0a..cda255b 100644 --- a/bevy_rtc/src/client/mod.rs +++ b/bevy_rtc/src/client/mod.rs @@ -5,8 +5,8 @@ mod state; mod system_params; mod systems; -pub use events::{ConnectionRequest, RtcClientEvent}; +pub use events::{RtcClientEvent, RtcClientRequestEvent}; pub use plugin::RtcClientPlugin; -pub use router::AddProtocolExt; +pub use router::AddClientProtocolExt; pub use state::{RtcClientState, RtcClientStatus}; pub use system_params::RtcClient; diff --git a/bevy_rtc/src/client/plugin.rs b/bevy_rtc/src/client/plugin.rs index 7dc8e42..8168c19 100644 --- a/bevy_rtc/src/client/plugin.rs +++ b/bevy_rtc/src/client/plugin.rs @@ -1,5 +1,6 @@ use super::{ - systems, AddProtocolExt, ConnectionRequest, RtcClientEvent, RtcClientState, RtcClientStatus, + systems, AddClientProtocolExt, RtcClientEvent, RtcClientRequestEvent, RtcClientState, + RtcClientStatus, }; use crate::{ events::SocketRecvEvent, @@ -16,9 +17,9 @@ impl Plugin for RtcClientPlugin { fn build(&self, app: &mut App) { app.add_event::() .insert_resource(RtcClientState::default()) - .add_bounded_protocol::(2) + .add_client_rw_protocol::(2) .init_state::() - .add_event::() + .add_event::() .add_event::() .add_systems(OnEnter(RtcClientStatus::Establishing), systems::init_socket) .add_systems( diff --git a/bevy_rtc/src/client/router/mod.rs b/bevy_rtc/src/client/router/mod.rs index 908052e..c2074db 100644 --- a/bevy_rtc/src/client/router/mod.rs +++ b/bevy_rtc/src/client/router/mod.rs @@ -2,7 +2,7 @@ mod receive; mod send; use crate::{ - protocol::Payload, + protocol::Protocol, socket::{common_socket_reader, RtcSocket}, }; use bevy::prelude::*; @@ -11,26 +11,25 @@ use std::collections::VecDeque; pub use receive::IncomingMessages; pub use send::OutgoingMessages; -pub trait AddProtocolExt { - /// Register a protocol that is only sent, never read. Hence, allocate no - /// buffer and do not run systems for receiving. - fn add_sendonly_protocol(&mut self) -> &mut Self; - /// Register a protocol that is only read, never sent. Allocate a bounded - /// buffer per peer for receiving, and do not run systems for sending. - fn add_readonly_bounded_protocol(&mut self, bound: usize) -> &mut Self; - /// Register a protocol that is only read, never sent. Use a growable buffer - /// for receiving, and do not run systems for sending. - fn add_readonly_unbounded_protocol(&mut self) -> &mut Self; - /// Register a protocol for sending and receiving. Allocate a bounded buffer - /// per peer for receiving. - fn add_bounded_protocol(&mut self, bound: usize) -> &mut Self; +pub trait AddClientProtocolExt { + /// Register a protocol that is only written, never read. + fn add_client_wo_protocol(&mut self) -> &mut Self; + /// Register a protocol that is only read, never written. Allocate a bounded + /// buffer per peer for receiving. + fn add_client_ro_protocol(&mut self, bound: usize) -> &mut Self; + /// Register a protocol that is only read, never written. Use a growable buffer + /// for reading. + fn add_client_ro_unbounded_protocol(&mut self) -> &mut Self; + /// Register a protocol for reading and writing. Allocate a bounded buffer + /// per peer for reading. + fn add_client_rw_protocol(&mut self, bound: usize) -> &mut Self; /// Register a protocol for sending and receiving. Use a growable buffer - /// for receiving. - fn add_unbounded_protocol(&mut self) -> &mut Self; + /// for reading. + fn add_client_rw_unbounded_protocol(&mut self) -> &mut Self; } -impl AddProtocolExt for App { - fn add_sendonly_protocol(&mut self) -> &mut Self { +impl AddClientProtocolExt for App { + fn add_client_wo_protocol(&mut self) -> &mut Self { if self.world.contains_resource::>() { panic!("client already contains resource: {}", M::reflect_name()); } @@ -45,11 +44,7 @@ impl AddProtocolExt for App { self } - fn add_readonly_unbounded_protocol(&mut self) -> &mut Self { - self.add_readonly_bounded_protocol::(usize::MAX) - } - - fn add_readonly_bounded_protocol(&mut self, bound: usize) -> &mut Self { + fn add_client_ro_protocol(&mut self, bound: usize) -> &mut Self { if self.world.contains_resource::>() { panic!("client already contains resource: {}", M::reflect_name()); } @@ -66,13 +61,13 @@ impl AddProtocolExt for App { self } - fn add_unbounded_protocol(&mut self) -> &mut Self { - self.add_bounded_protocol::(usize::MAX) + fn add_client_ro_unbounded_protocol(&mut self) -> &mut Self { + self.add_client_ro_protocol::(usize::MAX) } - fn add_bounded_protocol(&mut self, bound: usize) -> &mut Self + fn add_client_rw_protocol(&mut self, bound: usize) -> &mut Self where - M: Payload, + M: Protocol, { if self.world.contains_resource::>() || self.world.contains_resource::>() @@ -99,4 +94,8 @@ impl AddProtocolExt for App { ); self } + + fn add_client_rw_unbounded_protocol(&mut self) -> &mut Self { + self.add_client_rw_protocol::(usize::MAX) + } } diff --git a/bevy_rtc/src/client/router/receive.rs b/bevy_rtc/src/client/router/receive.rs index aeb5457..5a21c81 100644 --- a/bevy_rtc/src/client/router/receive.rs +++ b/bevy_rtc/src/client/router/receive.rs @@ -1,14 +1,14 @@ -use crate::{events::SocketRecvEvent, protocol::Payload}; +use crate::{events::SocketRecvEvent, protocol::Protocol}; use bevy::prelude::*; use std::collections::VecDeque; #[derive(Default, Debug, Resource)] -pub struct IncomingMessages { +pub struct IncomingMessages { pub bound: usize, pub messages: VecDeque, } -impl IncomingMessages { +impl IncomingMessages { pub fn receive_payloads(mut incoming: ResMut, mut events: EventReader) { let bound = incoming.bound; let packets: Vec<_> = events diff --git a/bevy_rtc/src/client/router/send.rs b/bevy_rtc/src/client/router/send.rs index 7fa991c..cbbade8 100644 --- a/bevy_rtc/src/client/router/send.rs +++ b/bevy_rtc/src/client/router/send.rs @@ -1,17 +1,17 @@ use crate::{ client::state::RtcClientState, - protocol::Payload, + protocol::Protocol, socket::{RtcSocket, RELIABLE_CHANNEL_INDEX, UNRELIABLE_CHANNEL_INDEX}, }; use bevy::prelude::*; #[derive(Default, Debug, Resource)] -pub struct OutgoingMessages { +pub struct OutgoingMessages { pub reliable_to_host: Vec, pub unreliable_to_host: Vec, } -impl OutgoingMessages { +impl OutgoingMessages { /// Swaps the event buffers and clears the oldest event buffer. In general, /// this should be called once per frame/update. pub fn flush(&mut self) { @@ -24,7 +24,7 @@ impl OutgoingMessages { mut socket: ResMut, state: Res, ) { - if let Some(host) = state.host_id { + if let Some(host) = state.host_peer_id { // Client is sending for message in queue.reliable_to_host.iter() { if socket diff --git a/bevy_rtc/src/client/state.rs b/bevy_rtc/src/client/state.rs index 53f2dde..9d257c0 100644 --- a/bevy_rtc/src/client/state.rs +++ b/bevy_rtc/src/client/state.rs @@ -17,13 +17,40 @@ pub enum RtcClientStatus { #[derive(Resource, Default)] pub struct RtcClientState { /// The socket address, used for connecting/reconnecting - pub addr: Option, - /// The ID of the host - pub host_id: Option, - /// The ID given by the signaling server - pub id: Option, + pub(crate) addr: Option, + /// The Peer ID of the host + pub(crate) host_peer_id: Option, + /// The Peer ID given by the signaling server + pub(crate) peer_id: Option, /// The latency to the server - pub latency: Option, + pub(crate) latency: Option, /// The smooth latency to the server - pub smoothed_latency: Option, + pub(crate) smoothed_latency: Option, +} + +impl RtcClientState { + /// Returns the address bound by the server/host. + pub fn addr(&self) -> Option<&str> { + self.addr.as_deref() + } + + /// Returns the peer ID of this client if connected + pub fn peer_id(&self) -> Option { + self.peer_id + } + + /// Returns the peer ID of the server if connected + pub fn host_peer_id(&self) -> Option { + self.host_peer_id + } + + /// Return the latency to the server if connected + pub fn latency(&self) -> Option { + self.latency + } + + /// Return the smoothed latency to the server if connected + pub fn smoothed_latency(&self) -> Option { + self.smoothed_latency + } } diff --git a/bevy_rtc/src/client/system_params.rs b/bevy_rtc/src/client/system_params.rs index c2370d3..1d468b4 100644 --- a/bevy_rtc/src/client/system_params.rs +++ b/bevy_rtc/src/client/system_params.rs @@ -1,14 +1,14 @@ use super::router::{IncomingMessages, OutgoingMessages}; -use crate::protocol::Payload; +use crate::protocol::Protocol; use bevy::{ecs::system::SystemParam, prelude::*}; #[derive(SystemParam, Debug)] -pub struct RtcClient<'w, M: Payload> { +pub struct RtcClient<'w, M: Protocol> { pub(crate) incoming: ResMut<'w, IncomingMessages>, pub(crate) outgoing: ResMut<'w, OutgoingMessages>, } -impl<'w, M: Payload> RtcClient<'w, M> { +impl<'w, M: Protocol> RtcClient<'w, M> { /// Returns the capacity of incoming messages. pub fn capacity(&self) -> usize { self.incoming.bound diff --git a/bevy_rtc/src/client/systems.rs b/bevy_rtc/src/client/systems.rs index a567471..a7218cb 100644 --- a/bevy_rtc/src/client/systems.rs +++ b/bevy_rtc/src/client/systems.rs @@ -1,5 +1,5 @@ use super::{ - events::{ConnectionRequest, RtcClientEvent}, + events::{RtcClientEvent, RtcClientRequestEvent}, state::{RtcClientState, RtcClientStatus}, RtcClient, }; @@ -49,8 +49,8 @@ pub(crate) fn reset_socket( *state = RtcClientState { // Keep for reconnecting addr: state.addr.clone(), - host_id: None, - id: None, + host_peer_id: None, + peer_id: None, latency: None, smoothed_latency: None, }; @@ -58,14 +58,14 @@ pub(crate) fn reset_socket( /// Reads and handles connection request events pub(crate) fn connection_request_handler( - mut cxn_event_reader: EventReader, + mut request_reader: EventReader, mut state: ResMut, mut next_connection_state: ResMut>, current_connection_state: Res>, mut event_wtr: EventWriter, ) { - match cxn_event_reader.read().next() { - Some(ConnectionRequest::Connect { addr }) => { + match request_reader.read().next() { + Some(RtcClientRequestEvent::Connect { addr }) => { if let RtcClientStatus::Disconnected = current_connection_state.get() { debug!( previous = format!("{current_connection_state:?}"), @@ -75,7 +75,7 @@ pub(crate) fn connection_request_handler( next_connection_state.set(RtcClientStatus::Establishing); } } - Some(ConnectionRequest::Disconnect) => { + Some(RtcClientRequestEvent::Disconnect) => { debug!( previous = format!("{current_connection_state:?}"), "set state: disconnected" @@ -100,10 +100,10 @@ pub(crate) fn client_event_writer( // Create events // Id changed events - if let Some(id) = socket.id() { - if state.id.is_none() { - state.id.replace(id); - event_wtr.send(RtcClientEvent::IdAssigned(id)); + if let Some(peer_id) = socket.id() { + if state.peer_id.is_none() { + state.peer_id.replace(peer_id); + event_wtr.send(RtcClientEvent::IdAssigned(peer_id)); } } @@ -113,7 +113,7 @@ pub(crate) fn client_event_writer( for (id, peer_state) in updates { match peer_state { matchbox_socket::PeerState::Connected => { - state.host_id.replace(id); + state.host_peer_id.replace(id); commands.spawn(LatencyTracer::new(id)); next_connection_state.set(RtcClientStatus::Connected); event_wtr.send(RtcClientEvent::ConnectedToHost(id)); @@ -144,7 +144,7 @@ pub fn send_latency_tracers( state: Res, mut client: RtcClient, ) { - let peer_id = state.id.expect("expected peer id"); + let peer_id = state.peer_id.expect("expected peer id"); client.unreliable_to_host(LatencyTracerPayload::new(peer_id)); } @@ -153,8 +153,8 @@ pub fn read_latency_tracers( mut trace_query: Query<&mut LatencyTracer>, mut client: RtcClient, ) { - let host_id = state.host_id.expect("expected host id"); - let peer_id = state.id.expect("expected peer id"); + let host_id = state.host_peer_id.expect("expected host id"); + let peer_id = state.peer_id.expect("expected peer id"); let mut tracer = trace_query.single_mut(); for payload in client.read() { diff --git a/bevy_rtc/src/latency.rs b/bevy_rtc/src/latency.rs index 88a0e0f..6e228e2 100644 --- a/bevy_rtc/src/latency.rs +++ b/bevy_rtc/src/latency.rs @@ -9,7 +9,7 @@ mod bevy_rtc { } /// A packet containing information to track a peer's latency -#[derive(proc_macro_payload::Payload, Serialize, Deserialize, Debug, Clone)] +#[derive(proc_macro_protocol::Protocol, Serialize, Deserialize, Debug, Clone)] pub struct LatencyTracerPayload { pub from: PeerId, pub sent: f64, diff --git a/bevy_rtc/src/lib.rs b/bevy_rtc/src/lib.rs index 81a1e0c..86e41b2 100644 --- a/bevy_rtc/src/lib.rs +++ b/bevy_rtc/src/lib.rs @@ -11,6 +11,14 @@ pub(crate) mod socket; // Re-exports pub use bevy_matchbox; +pub mod prelude { + #[cfg(feature = "client")] + pub use crate::client::*; + pub use crate::protocol::Protocol; + #[cfg(feature = "server")] + pub use crate::server::*; +} + #[cfg(feature = "server")] #[cfg_attr(docsrs, doc(cfg(feature = "server")))] pub mod server; diff --git a/bevy_rtc/src/protocol.rs b/bevy_rtc/src/protocol.rs index c980ad6..6e38e6b 100644 --- a/bevy_rtc/src/protocol.rs +++ b/bevy_rtc/src/protocol.rs @@ -4,16 +4,16 @@ use std::fmt::Debug; // Note: Intentional name collision with the trait Payload! // This is done commonly, like `serde::Serialize` is a trait and a derive macro. -pub use proc_macro_payload::Payload; +pub use proc_macro_protocol::Protocol; #[derive(Deserialize, Serialize)] #[serde(bound = "M: DeserializeOwned")] -pub struct RtcPacket { +pub(crate) struct RtcPacket { pub msg_id: u16, pub data: M, } -pub trait Payload: +pub trait Protocol: Debug + Clone + Send + Sync + for<'a> Deserialize<'a> + Serialize + 'static { fn id() -> u16; diff --git a/bevy_rtc/src/server/mod.rs b/bevy_rtc/src/server/mod.rs index 6559d15..19e32d6 100644 --- a/bevy_rtc/src/server/mod.rs +++ b/bevy_rtc/src/server/mod.rs @@ -7,6 +7,6 @@ mod systems; pub use events::RtcServerEvent; pub use plugin::RtcServerPlugin; -pub use router::AddProtocolExt; +pub use router::AddServerProtocolExt; pub use state::{RtcServerState, RtcServerStatus}; pub use system_params::RtcServer; diff --git a/bevy_rtc/src/server/plugin.rs b/bevy_rtc/src/server/plugin.rs index 9ea75a3..f865246 100644 --- a/bevy_rtc/src/server/plugin.rs +++ b/bevy_rtc/src/server/plugin.rs @@ -7,7 +7,7 @@ use bevy::{prelude::*, time::common_conditions::on_timer}; use instant::Duration; use std::net::Ipv4Addr; -use super::{systems, AddProtocolExt, RtcServerEvent, RtcServerState, RtcServerStatus}; +use super::{systems, AddServerProtocolExt, RtcServerEvent, RtcServerState, RtcServerStatus}; /// A plugin to serve a WebRTC server. pub struct RtcServerPlugin { @@ -19,7 +19,7 @@ impl Plugin for RtcServerPlugin { fn build(&self, app: &mut App) { app.add_event::() .add_event::() - .add_bounded_protocol::(2) + .add_server_rw_protocol::(2) .init_state::() .insert_resource(RtcServerState::new( (Ipv4Addr::UNSPECIFIED, self.port).into(), diff --git a/bevy_rtc/src/server/router/mod.rs b/bevy_rtc/src/server/router/mod.rs index e9b94ce..6354256 100644 --- a/bevy_rtc/src/server/router/mod.rs +++ b/bevy_rtc/src/server/router/mod.rs @@ -2,7 +2,7 @@ mod receive; mod send; use crate::{ - protocol::Payload, + protocol::Protocol, socket::{common_socket_reader, RtcSocket}, }; use bevy::{prelude::*, utils::hashbrown::HashMap}; @@ -10,26 +10,25 @@ use bevy::{prelude::*, utils::hashbrown::HashMap}; pub use receive::IncomingMessages; pub use send::OutgoingMessages; -pub trait AddProtocolExt { - /// Register a protocol that is only sent, never read. Hence, allocate no - /// buffer and do not run systems for receiving. - fn add_sendonly_protocol(&mut self) -> &mut Self; - /// Register a protocol that is only read, never sent. Allocate a bounded - /// buffer per peer for receiving, and do not run systems for sending. - fn add_readonly_bounded_protocol(&mut self, bound: usize) -> &mut Self; - /// Register a protocol that is only read, never sent. Use a growable buffer - /// for receiving, and do not run systems for sending. - fn add_readonly_unbounded_protocol(&mut self) -> &mut Self; - /// Register a protocol for sending and receiving. Allocate a bounded buffer - /// per peer for receiving. - fn add_bounded_protocol(&mut self, bound: usize) -> &mut Self; +pub trait AddServerProtocolExt { + /// Register a protocol that is only written, never read. + fn add_server_wo_protocol(&mut self) -> &mut Self; + /// Register a protocol that is only read, never written. Allocate a bounded + /// buffer per peer for receiving. + fn add_server_ro_protocol(&mut self, bound: usize) -> &mut Self; + /// Register a protocol that is only read, never written. Use a growable buffer + /// for reading. + fn add_server_ro_unbounded_protocol(&mut self) -> &mut Self; + /// Register a protocol for reading and writing. Allocate a bounded buffer + /// per peer for reading. + fn add_server_rw_protocol(&mut self, bound: usize) -> &mut Self; /// Register a protocol for sending and receiving. Use a growable buffer - /// for receiving. - fn add_unbounded_protocol(&mut self) -> &mut Self; + /// for reading. + fn add_server_rw_unbounded_protocol(&mut self) -> &mut Self; } -impl AddProtocolExt for App { - fn add_sendonly_protocol(&mut self) -> &mut Self { +impl AddServerProtocolExt for App { + fn add_server_wo_protocol(&mut self) -> &mut Self { if self.world.contains_resource::>() { panic!("server already contains resource: {}", M::reflect_name()); } @@ -49,11 +48,7 @@ impl AddProtocolExt for App { self } - fn add_readonly_unbounded_protocol(&mut self) -> &mut Self { - self.add_readonly_bounded_protocol::(usize::MAX) - } - - fn add_readonly_bounded_protocol(&mut self, bound: usize) -> &mut Self { + fn add_server_ro_protocol(&mut self, bound: usize) -> &mut Self { if self.world.contains_resource::>() { panic!("server already contains resource: {}", M::reflect_name()); } @@ -71,13 +66,13 @@ impl AddProtocolExt for App { self } - fn add_unbounded_protocol(&mut self) -> &mut Self { - self.add_bounded_protocol::(usize::MAX) + fn add_server_ro_unbounded_protocol(&mut self) -> &mut Self { + self.add_server_ro_protocol::(usize::MAX) } - fn add_bounded_protocol(&mut self, bound: usize) -> &mut Self + fn add_server_rw_protocol(&mut self, bound: usize) -> &mut Self where - M: Payload, + M: Protocol, { if self.world.contains_resource::>() || self.world.contains_resource::>() @@ -109,4 +104,8 @@ impl AddProtocolExt for App { self } + + fn add_server_rw_unbounded_protocol(&mut self) -> &mut Self { + self.add_server_rw_protocol::(usize::MAX) + } } diff --git a/bevy_rtc/src/server/router/receive.rs b/bevy_rtc/src/server/router/receive.rs index 2d20343..9f7433c 100644 --- a/bevy_rtc/src/server/router/receive.rs +++ b/bevy_rtc/src/server/router/receive.rs @@ -1,15 +1,15 @@ -use crate::{events::SocketRecvEvent, protocol::Payload}; +use crate::{events::SocketRecvEvent, protocol::Protocol}; use bevy::{prelude::*, utils::hashbrown::HashMap}; use bevy_matchbox::prelude::PeerId; use std::collections::VecDeque; #[derive(Default, Debug, Resource)] -pub struct IncomingMessages { +pub struct IncomingMessages { pub bound: usize, pub messages: HashMap>, } -impl IncomingMessages { +impl IncomingMessages { pub fn receive_payloads(mut incoming: ResMut, mut events: EventReader) { let bound = incoming.bound; let packets: HashMap> = events.read().fold( diff --git a/bevy_rtc/src/server/router/send.rs b/bevy_rtc/src/server/router/send.rs index 078d79a..289aa20 100644 --- a/bevy_rtc/src/server/router/send.rs +++ b/bevy_rtc/src/server/router/send.rs @@ -1,12 +1,12 @@ use crate::{ - protocol::Payload, + protocol::Protocol, socket::{RtcSocket, RELIABLE_CHANNEL_INDEX, UNRELIABLE_CHANNEL_INDEX}, }; use bevy::prelude::*; use bevy_matchbox::prelude::PeerId; #[derive(Default, Debug, Resource)] -pub struct OutgoingMessages { +pub struct OutgoingMessages { pub reliable_to_all: Vec, pub unreliable_to_all: Vec, pub reliable_to_all_except: Vec<(PeerId, M)>, @@ -15,7 +15,7 @@ pub struct OutgoingMessages { pub unreliable_to_peer: Vec<(PeerId, M)>, } -impl OutgoingMessages { +impl OutgoingMessages { /// Swaps the event buffers and clears the oldest event buffer. In general, /// this should be called once per frame/update. pub fn flush(&mut self) { diff --git a/bevy_rtc/src/server/state.rs b/bevy_rtc/src/server/state.rs index 0fb2a3c..7a7928e 100644 --- a/bevy_rtc/src/server/state.rs +++ b/bevy_rtc/src/server/state.rs @@ -20,10 +20,10 @@ pub enum RtcServerStatus { #[derive(Resource)] pub struct RtcServerState { /// The socket address bound - pub addr: SocketAddr, + pub(crate) addr: SocketAddr, - /// The ID the host (server) - pub id: Option, + /// The Peer ID of the host (server) + pub(crate) peer_id: Option, /// A list of connected peers pub(crate) peers: HashSet, @@ -36,16 +36,26 @@ pub struct RtcServerState { } impl RtcServerState { - pub fn new(addr: SocketAddr) -> Self { + pub(crate) fn new(addr: SocketAddr) -> Self { Self { addr, - id: None, + peer_id: None, peers: HashSet::new(), latencies: HashMap::new(), smoothed_latencies: HashMap::new(), } } + /// Returns the address bound by the server/host. + pub fn addr(&self) -> SocketAddr { + self.addr + } + + /// Returns the peer ID of the server/host. Will be None prior until the host is ready. + pub fn peer_id(&self) -> Option { + self.peer_id + } + /// Return the currently connected peers pub fn peers(&self) -> impl Iterator + '_ { self.peers.iter().copied() diff --git a/bevy_rtc/src/server/system_params.rs b/bevy_rtc/src/server/system_params.rs index 4f893b2..bbe95be 100644 --- a/bevy_rtc/src/server/system_params.rs +++ b/bevy_rtc/src/server/system_params.rs @@ -1,16 +1,16 @@ use super::router::{IncomingMessages, OutgoingMessages}; -use crate::protocol::Payload; +use crate::protocol::Protocol; use bevy::{ecs::system::SystemParam, prelude::*}; use bevy_matchbox::prelude::PeerId; /// A [`SystemParam`] for reading payloads of a particular type. #[derive(SystemParam, Debug)] -pub struct RtcServer<'w, M: Payload> { +pub struct RtcServer<'w, M: Protocol> { pub(crate) incoming: ResMut<'w, IncomingMessages>, pub(crate) outgoing: ResMut<'w, OutgoingMessages>, } -impl<'w, M: Payload> RtcServer<'w, M> { +impl<'w, M: Protocol> RtcServer<'w, M> { /// Returns the capacity of incoming messages. pub fn capacity(&self) -> usize { self.incoming.bound diff --git a/bevy_rtc/src/server/systems.rs b/bevy_rtc/src/server/systems.rs index 4ffecee..0ceb78c 100644 --- a/bevy_rtc/src/server/systems.rs +++ b/bevy_rtc/src/server/systems.rs @@ -99,8 +99,8 @@ pub fn server_event_writer( ) { // Id changed events if let Some(id) = socket.id() { - if state.id.is_none() { - state.id.replace(id); + if state.peer_id.is_none() { + state.peer_id.replace(id); event_wtr.send(RtcServerEvent::IdAssigned(id)); next_server_status.set(RtcServerStatus::Ready); } @@ -116,11 +116,16 @@ pub fn server_event_writer( } PeerState::Disconnected => { state.peers.remove(&peer); - if let Some((entity, _)) = tracer_query + state.latencies.remove(&peer); + state.smoothed_latencies.remove(&peer); + if let Some(entity) = tracer_query .iter() .find(|(_, tracer)| tracer.peer_id == peer) + .map(|(e, _)| e) { commands.entity(entity).despawn(); + } else { + error!("No latency tracer found for {peer}"); } event_wtr.send(RtcServerEvent::ClientLeft(peer)); } @@ -132,7 +137,7 @@ pub fn send_latency_tracers( state: Res, mut server: RtcServer, ) { - let peer_id = state.id.expect("expected peer id"); + let peer_id = state.peer_id.expect("expected peer id"); server.unreliable_to_all(LatencyTracerPayload::new(peer_id)); } @@ -141,7 +146,7 @@ pub fn read_latency_tracers( mut tracers: Query<&mut LatencyTracer>, mut server: RtcServer, ) { - let host_id = state.id.expect("expected host id"); + let host_id = state.peer_id.expect("expected host id"); // Handle payloads for (from, payload) in server.read() { diff --git a/bevy_rtc_macros/Cargo.toml b/bevy_rtc_macros/Cargo.toml index 7c68108..d8a0b1d 100644 --- a/bevy_rtc_macros/Cargo.toml +++ b/bevy_rtc_macros/Cargo.toml @@ -12,8 +12,8 @@ readme.workspace = true [lib] proc-macro = true -name = "proc_macro_payload" -path = "src/payload.rs" +name = "proc_macro_protocol" +path = "src/protocol.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/bevy_rtc_macros/src/payload.rs b/bevy_rtc_macros/src/protocol.rs similarity index 88% rename from bevy_rtc_macros/src/payload.rs rename to bevy_rtc_macros/src/protocol.rs index c64ed97..a1b61c1 100644 --- a/bevy_rtc_macros/src/payload.rs +++ b/bevy_rtc_macros/src/protocol.rs @@ -8,7 +8,7 @@ use std::{ }; use syn::{parse_macro_input, DeriveInput}; -#[proc_macro_derive(Payload)] +#[proc_macro_derive(Protocol)] pub fn derive_payload_fn(item: TokenStream) -> TokenStream { let DeriveInput { ident, .. } = parse_macro_input!(item); let mut s = DefaultHasher::new(); @@ -16,7 +16,7 @@ pub fn derive_payload_fn(item: TokenStream) -> TokenStream { let id = s.finish() as u16; let reflect_name = ident.to_string(); quote! { - impl bevy_rtc::protocol::Payload for #ident { + impl bevy_rtc::protocol::Protocol for #ident { fn id() -> u16 { #id } diff --git a/demos/painting-client/src/main.rs b/demos/painting-client/src/main.rs index 6e7d06f..0ecf94a 100644 --- a/demos/painting-client/src/main.rs +++ b/demos/painting-client/src/main.rs @@ -10,10 +10,7 @@ use bevy_egui::{ egui::{self, Pos2}, EguiContexts, EguiPlugin, }; -use bevy_rtc::client::{ - AddProtocolExt, ConnectionRequest, RtcClient, RtcClientEvent, RtcClientPlugin, RtcClientState, - RtcClientStatus, -}; +use bevy_rtc::prelude::*; use chat::ChatState; use painting::PaintingState; use protocol::{ChatPayload, DrawLinePayload}; @@ -32,8 +29,8 @@ fn main() { })) .add_plugins(EguiPlugin) .add_plugins(RtcClientPlugin) - .add_unbounded_protocol::() - .add_unbounded_protocol::() + .add_client_rw_unbounded_protocol::() + .add_client_rw_unbounded_protocol::() .insert_resource(ChatState::default()) .insert_resource(PaintingState::default()) .add_systems(Startup, |mut commands: Commands| { @@ -103,7 +100,7 @@ fn send_chats( ) { if let Some(message) = chat_state.out.take() { let payload = ChatPayload { - from: rtc_state.id.unwrap().to_string(), + from: rtc_state.peer_id().unwrap().to_string(), message, }; client.reliable_to_host(payload); @@ -136,7 +133,7 @@ fn app_ui( connection_status: Res>, mut contexts: EguiContexts, mut painting_state: ResMut, - mut connection_requests: EventWriter, + mut connection_requests: EventWriter, mut chat_state: ResMut, mut room_url: Local, mut chat_line: Local, @@ -163,7 +160,7 @@ fn app_ui( ); }); if ui.button("Connect").clicked() { - connection_requests.send(ConnectionRequest::Connect { + connection_requests.send(RtcClientRequestEvent::Connect { addr: if room_url.is_empty() { "ws://127.0.0.1:3536".to_string() } else { @@ -174,13 +171,13 @@ fn app_ui( } RtcClientStatus::Connected => { if ui.button("Disconnect").clicked() { - connection_requests.send(ConnectionRequest::Disconnect); + connection_requests.send(RtcClientRequestEvent::Disconnect); } - ui.label(format!("Connected as {}", state.id.unwrap())); + ui.label(format!("Connected as {}", state.peer_id().unwrap())); ui.label(format!( "Latency: {:.0?} (smoothed = {:.0?})", - state.latency.unwrap_or_default(), - state.smoothed_latency.unwrap_or_default() + state.latency().unwrap_or_default(), + state.smoothed_latency().unwrap_or_default() )); ui.separator(); diff --git a/demos/painting-server/src/main.rs b/demos/painting-server/src/main.rs index ce5d313..cde4d5d 100644 --- a/demos/painting-server/src/main.rs +++ b/demos/painting-server/src/main.rs @@ -1,18 +1,15 @@ -use std::time::Duration; - use bevy::{log::LogPlugin, prelude::*, time::common_conditions::on_timer}; -use bevy_rtc::server::{ - AddProtocolExt, RtcServer, RtcServerEvent, RtcServerPlugin, RtcServerState, -}; +use bevy_rtc::prelude::*; use protocol::{ChatPayload, DrawLinePayload}; +use std::time::Duration; fn main() { let mut app = App::new(); app.add_plugins(MinimalPlugins) .add_plugins(LogPlugin::default()) .add_plugins(RtcServerPlugin { port: 3536 }) - .add_bounded_protocol::(2) - .add_bounded_protocol::(2) + .add_server_rw_protocol::(2) + .add_server_rw_protocol::(2) .add_systems( Update, ( diff --git a/demos/ping-client/src/main.rs b/demos/ping-client/src/main.rs index 579513d..2f93d6d 100644 --- a/demos/ping-client/src/main.rs +++ b/demos/ping-client/src/main.rs @@ -1,21 +1,18 @@ -use std::time::Duration; - use bevy::{log::LogPlugin, prelude::*, time::common_conditions::on_timer}; -use bevy_rtc::client::{ - AddProtocolExt, ConnectionRequest, RtcClient, RtcClientPlugin, RtcClientStatus, -}; +use bevy_rtc::prelude::*; use protocol::PingPayload; +use std::time::Duration; fn main() { App::new() .add_plugins(MinimalPlugins) .add_plugins(LogPlugin::default()) .add_plugins(RtcClientPlugin) - .add_bounded_protocol::(1) + .add_client_rw_protocol::(1) .add_systems( OnEnter(RtcClientStatus::Disconnected), // Automatically-reconnect - |mut connection_requests: EventWriter| { - connection_requests.send(ConnectionRequest::Connect { + |mut connection_requests: EventWriter| { + connection_requests.send(RtcClientRequestEvent::Connect { addr: "ws://127.0.0.1:3536".to_string(), }); }, diff --git a/demos/ping-server/src/main.rs b/demos/ping-server/src/main.rs index e010b35..7b395c1 100644 --- a/demos/ping-server/src/main.rs +++ b/demos/ping-server/src/main.rs @@ -1,5 +1,5 @@ use bevy::{log::LogPlugin, prelude::*}; -use bevy_rtc::server::{AddProtocolExt, RtcServer, RtcServerPlugin}; +use bevy_rtc::prelude::*; use protocol::PingPayload; fn main() { @@ -7,7 +7,7 @@ fn main() { .add_plugins(MinimalPlugins) .add_plugins(LogPlugin::default()) .add_plugins(RtcServerPlugin { port: 3536 }) - .add_bounded_protocol::(1) + .add_server_rw_protocol::(1) .add_systems(Update, |mut server: RtcServer| { for (peer_id, packet) in server.read() { if let PingPayload::Ping = packet { diff --git a/demos/protocol/src/lib.rs b/demos/protocol/src/lib.rs index edf4fcf..da66b25 100644 --- a/demos/protocol/src/lib.rs +++ b/demos/protocol/src/lib.rs @@ -1,9 +1,9 @@ -use bevy_rtc::protocol::Payload; +use bevy_rtc::protocol::Protocol; use serde::{Deserialize, Serialize}; // Used by painting demo -#[derive(Payload, Serialize, Deserialize, Debug, Clone)] +#[derive(Protocol, Serialize, Deserialize, Debug, Clone)] pub struct DrawLinePayload { pub x1: f32, pub y1: f32, @@ -11,7 +11,7 @@ pub struct DrawLinePayload { pub y2: f32, } -#[derive(Payload, Serialize, Deserialize, Debug, Clone)] +#[derive(Protocol, Serialize, Deserialize, Debug, Clone)] pub struct ChatPayload { pub from: String, pub message: String, @@ -19,7 +19,7 @@ pub struct ChatPayload { // Used by ping demo -#[derive(Payload, Serialize, Deserialize, Debug, Clone)] +#[derive(Protocol, Serialize, Deserialize, Debug, Clone)] pub enum PingPayload { Ping, Pong,