use bevy::ecs::system::Command;
use bevy::prelude::{Commands, Resource, World};
use bevy::tasks::{IoTaskPool, Task};
use matchbox_socket::{MessageLoopFuture, WebRtcSocket, WebRtcSocketBuilder};
use std::ops::{Deref, DerefMut};
#[derive(Resource)]
pub struct MatchboxSocket {
socket: WebRtcSocket,
_message_loop: Task<Result<(), matchbox_socket::Error>>,
}
impl std::fmt::Debug for MatchboxSocket {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MatchboxSocket")
.field("socket", &self.socket)
.finish_non_exhaustive()
}
}
impl Deref for MatchboxSocket {
type Target = WebRtcSocket;
fn deref(&self) -> &Self::Target {
&self.socket
}
}
impl DerefMut for MatchboxSocket {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.socket
}
}
impl From<WebRtcSocketBuilder> for MatchboxSocket {
fn from(builder: WebRtcSocketBuilder) -> Self {
Self::from(builder.build())
}
}
impl From<(WebRtcSocket, MessageLoopFuture)> for MatchboxSocket {
fn from((socket, message_loop): (WebRtcSocket, MessageLoopFuture)) -> Self {
let _message_loop = IoTaskPool::get().spawn(message_loop);
Self {
socket,
_message_loop,
}
}
}
impl MatchboxSocket {
pub fn new_unreliable(room_url: impl Into<String>) -> Self {
Self::from(WebRtcSocket::new_unreliable(room_url))
}
pub fn new_reliable(room_url: impl Into<String>) -> Self {
Self::from(WebRtcSocket::new_reliable(room_url))
}
}
struct OpenSocket(WebRtcSocketBuilder);
impl Command for OpenSocket {
type Out = ();
fn apply(self, world: &mut World) {
world.insert_resource(MatchboxSocket::from(self.0));
}
}
pub trait OpenSocketExt {
fn open_socket(&mut self, socket_builder: WebRtcSocketBuilder);
}
impl OpenSocketExt for Commands<'_, '_> {
fn open_socket(&mut self, socket_builder: WebRtcSocketBuilder) {
self.queue(OpenSocket(socket_builder));
}
}
struct CloseSocket;
impl Command for CloseSocket {
type Out = ();
fn apply(self, world: &mut World) {
world.remove_resource::<MatchboxSocket>();
}
}
pub trait CloseSocketExt {
fn close_socket(&mut self);
}
impl CloseSocketExt for Commands<'_, '_> {
fn close_socket(&mut self) {
self.queue(CloseSocket);
}
}