Skip to content

Commit

Permalink
Add bevy_matchbox signaling feature
Browse files Browse the repository at this point in the history
  • Loading branch information
garryod committed Apr 16, 2023
1 parent de01337 commit 7f87a0d
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions bevy_matchbox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ readme = "../README.md"

[features]
ggrs = ["matchbox_socket/ggrs"]
signaling = ["matchbox_signaling"]

[dependencies]
bevy = { version = "0.10", default-features = false }
matchbox_socket = { path = "../matchbox_socket", version = "0.6" }
cfg-if = "1.0"

# signaling
matchbox_signaling = { path = "../matchbox_signaling", version = "0.6", optional = true }
18 changes: 17 additions & 1 deletion bevy_matchbox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,31 @@
#![doc = include_str!("../README.md")]
#![forbid(unsafe_code)]

mod socket;
use cfg_if::cfg_if;

mod socket;
pub use socket::*;

cfg_if! {
if #[cfg(feature = "signaling")] {
mod signaling;
pub use signaling::*;
}
}

/// use `bevy_matchbox::prelude::*;` to import common resources and commands
pub mod prelude {
pub use crate::{CloseSocketExt, MatchboxSocket, OpenSocketExt};
use cfg_if::cfg_if;
pub use matchbox_socket::{
BuildablePlurality, ChannelConfig, MultipleChannels, PeerId, PeerState, SingleChannel,
WebRtcSocketBuilder,
};

cfg_if! {
if #[cfg(feature = "signaling")] {
pub use crate::signaling::{MatchboxServer, StartServerExt, StopServerExt};
pub use matchbox_signaling::SignalingServerBuilder;
}
}
}
161 changes: 161 additions & 0 deletions bevy_matchbox/src/signaling.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
use std::net::SocketAddr;

use bevy::{
ecs::system::Command,
prelude::{Commands, Resource},
tasks::IoTaskPool,
};
pub use matchbox_signaling;
use matchbox_signaling::{
topologies::{
client_server::{ClientServer, ClientServerCallbacks, ClientServerState},
full_mesh::{FullMesh, FullMeshCallbacks, FullMeshState},
SignalingTopology,
},
SignalingCallbacks, SignalingServer, SignalingServerBuilder, SignalingState,
};

/// A [`SignalingServer`] as a [`Resource`].
///
/// As a [`Resource`], with [`Commands`]
/// ```
/// use std::net::Ipv4Addr;
/// use bevy_matchbox::{
/// prelude::*,
/// matchbox_signaling::topologies::full_mesh::{FullMesh, FullMeshState}
/// };
/// use bevy::prelude::*;
///
/// fn start_server_system(mut commands: Commands) {
/// let builder = SignalingServerBuilder::new(
/// (Ipv4Addr::UNSPECIFIED, 3536),
/// FullMesh,
/// FullMeshState::default(),
/// );
/// commands.start_server(builder);
/// }
///
/// fn stop_server_system(mut commands: Commands) {
/// commands.stop_server();
/// }
/// ```
///
/// As a [`Resource`], directly
/// ```
/// use std::net::Ipv4Addr;
/// use bevy_matchbox::{
/// prelude::*,
/// matchbox_signaling::topologies::full_mesh::{FullMesh, FullMeshState}
/// };
/// use bevy::prelude::*;
///
/// fn start_server_system(mut commands: Commands) {
/// let server: MatchboxServer = SignalingServerBuilder::new(
/// (Ipv4Addr::UNSPECIFIED, 3536),
/// FullMesh,
/// FullMeshState::default(),
/// ).into();
///
/// commands.insert_resource(MatchboxServer::from(server));
/// }
///
/// fn stop_server_system(mut commands: Commands) {
/// commands.remove_resource::<MatchboxServer>();
/// }
/// ```
#[derive(Debug, Resource)]
pub struct MatchboxServer;

impl<Topology, Cb, S> From<SignalingServerBuilder<Topology, Cb, S>> for MatchboxServer
where
Topology: SignalingTopology<Cb, S>,
Cb: SignalingCallbacks,
S: SignalingState,
{
fn from(value: SignalingServerBuilder<Topology, Cb, S>) -> Self {
MatchboxServer::from(value.build())
}
}

impl From<SignalingServer> for MatchboxServer {
fn from(server: SignalingServer) -> Self {
let task_pool = IoTaskPool::get();
task_pool.spawn(server.serve()).detach();
MatchboxServer
}
}

struct StartServer<Topology, Cb, S>(SignalingServerBuilder<Topology, Cb, S>)
where
Topology: SignalingTopology<Cb, S>,
Cb: SignalingCallbacks,
S: SignalingState;

impl<Topology, Cb, S> Command for StartServer<Topology, Cb, S>
where
Topology: SignalingTopology<Cb, S> + Send + 'static,
Cb: SignalingCallbacks,
S: SignalingState,
{
fn write(self, world: &mut bevy::prelude::World) {
world.insert_resource(MatchboxServer::from(self.0))
}
}

/// A [`Commands`] extension used to start a [`MatchboxServer`].
pub trait StartServerExt<
Topology: SignalingTopology<Cb, S>,
Cb: SignalingCallbacks,
S: SignalingState,
>
{
/// Starts a [`MatchboxServer`] and allocates it as a resource.
fn start_server(&mut self, builder: SignalingServerBuilder<Topology, Cb, S>);
}

impl<'w, 's, Topology, Cb, S> StartServerExt<Topology, Cb, S> for Commands<'w, 's>
where
Topology: SignalingTopology<Cb, S> + Send + 'static,
Cb: SignalingCallbacks,
S: SignalingState,
{
fn start_server(&mut self, builder: SignalingServerBuilder<Topology, Cb, S>) {
self.add(StartServer(builder))
}
}

struct StopServer;

impl Command for StopServer {
fn write(self, world: &mut bevy::prelude::World) {
world.remove_resource::<MatchboxServer>();
}
}

/// A [`Commands`] extension used to stop a [`MatchboxServer`].
pub trait StopServerExt {
/// Delete the [`MatchboxServer`] resource.
fn stop_server(&mut self);
}

impl<'w, 's> StopServerExt for Commands<'w, 's> {
fn stop_server(&mut self) {
self.add(StopServer)
}
}

impl MatchboxServer {
/// Creates a new builder for a [`SignalingServer`] with full-mesh topology.
pub fn full_mesh_builder(
socket_addr: impl Into<SocketAddr>,
) -> SignalingServerBuilder<FullMesh, FullMeshCallbacks, FullMeshState> {
SignalingServer::full_mesh_builder(socket_addr)
}

/// Creates a new builder for a [`SignalingServer`] with client-server topology.
pub fn client_server_builder(
socket_addr: impl Into<SocketAddr>,
) -> SignalingServerBuilder<ClientServer, ClientServerCallbacks, ClientServerState> {
SignalingServer::client_server_builder(socket_addr)
}
}

0 comments on commit 7f87a0d

Please sign in to comment.