use crate::ClientId;
use bevy_ecs::prelude::*;
use crate::Message;
use crate::channel::{Channel, SessionConfig};
use crate::events::{SessionConnectedEvent, SessionDisconnectedEvent};
use std::marker::PhantomData;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use tracing::debug;
use tracing::error;
pub struct SessionConnectCommand<T: Message> {
config: SessionConfig,
_t: PhantomData<T>,
}
impl<T: Message> Command for SessionConnectCommand<T> {
fn apply(self, world: &mut World) {
let SessionConfig::Direct {
addr,
port,
host,
compress: _,
key: _,
options: _,
} = self.config;
let addr = addr.unwrap_or(IpAddr::V4(Ipv4Addr::UNSPECIFIED));
let addr = SocketAddr::from((addr, port));
if host {
debug!("Creating new host to {addr}...");
let channel = Channel::<T>::new_host(&self.config);
let Ok(channel) = channel else {
error!("Could not connect to host {addr}");
return;
};
let uuid = channel.uuid();
world.insert_resource(channel);
world.write_message(SessionConnectedEvent::<T> { _t: PhantomData });
debug!("Host created on {addr} with uuid {uuid}.");
} else {
debug!("Connecting new client to {addr}...");
let channel = Channel::<T>::try_new_client(&self.config);
let Ok(channel) = channel else {
error!("Could not connect to host {addr}");
return;
};
let uuid = channel.uuid();
world.insert_resource(channel);
world.write_message(SessionConnectedEvent::<T> { _t: PhantomData });
debug!("Client connected to {addr} with uuid {uuid}.");
}
}
}
impl<T: Message> SessionConnectCommand<T> {
#[must_use]
pub fn from_config(config: SessionConfig) -> Self {
Self {
config,
_t: PhantomData,
}
}
}
pub struct SessionDisconnectCommand<T: Message> {
_t: PhantomData<T>,
}
impl<T: Message> Default for SessionDisconnectCommand<T> {
fn default() -> Self {
Self { _t: PhantomData }
}
}
impl<T: Message> Command for SessionDisconnectCommand<T> {
fn apply(self, world: &mut World) {
debug!("Disconnecting channel...");
if let Some(c) = world.remove_resource::<Channel<T>>() {
drop(c);
}
world.write_message(SessionDisconnectedEvent::<T> { _t: PhantomData });
debug!("Channel disconnected.");
}
}
pub struct SessionPromoteToHostCommand<T: Message> {
pub(crate) new_host: ClientId,
pub(crate) port: Option<u16>,
_t: PhantomData<T>,
}
impl<T: Message> SessionPromoteToHostCommand<T> {
#[must_use]
pub fn new(new_host: ClientId, port: Option<u16>) -> Self {
Self {
new_host,
port,
_t: PhantomData,
}
}
}
impl<T: Message> Command for SessionPromoteToHostCommand<T> {
fn apply(self, world: &mut World) {
let mut channel = world.resource_mut::<Channel<T>>();
channel.promote_new_host(self.new_host, self.port);
}
}