#![deny(
missing_docs,
trivial_casts,
trivial_numeric_casts,
unstable_features,
unused_import_braces,
unused_qualifications,
clippy::unwrap_used
)]
#![allow(clippy::type_complexity)]
pub mod error;
mod network_message;
pub mod managers;
pub use managers::{network::AppNetworkMessage, Network};
mod runtime;
use managers::NetworkProvider;
use runtime::JoinHandle;
pub use runtime::Runtime;
use std::{
fmt::{Debug, Display},
marker::PhantomData,
};
pub use async_channel;
use async_channel::{unbounded, Receiver, Sender};
pub use async_trait::async_trait;
use bevy::prelude::*;
use error::NetworkError;
pub use network_message::NetworkMessage;
use serde::{Deserialize, Serialize};
use std::ops::Deref;
#[cfg(feature = "tcp")]
pub mod tcp;
struct AsyncChannel<T> {
pub(crate) sender: Sender<T>,
pub(crate) receiver: Receiver<T>,
}
impl<T> AsyncChannel<T> {
fn new() -> Self {
let (sender, receiver) = unbounded();
Self { sender, receiver }
}
}
#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)]
pub struct ConnectionId {
pub id: u32,
}
impl Display for ConnectionId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("Connection with ID={0}", self.id))
}
}
#[derive(Serialize, Deserialize)]
pub struct NetworkPacket {
kind: String,
data: Vec<u8>,
}
impl Debug for NetworkPacket {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("NetworkPacket")
.field("kind", &self.kind)
.finish()
}
}
#[derive(Debug)]
pub enum NetworkEvent {
Connected(ConnectionId),
Disconnected(ConnectionId),
Error(NetworkError),
}
#[derive(Debug)]
pub struct NetworkData<T> {
source: ConnectionId,
inner: T,
}
impl<T> Deref for NetworkData<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T> NetworkData<T> {
pub fn source(&self) -> &ConnectionId {
&self.source
}
pub fn into_inner(self) -> T {
self.inner
}
}
struct Connection {
receive_task: Box<dyn JoinHandle>,
map_receive_task: Box<dyn JoinHandle>,
send_task: Box<dyn JoinHandle>,
send_message: Sender<NetworkPacket>,
}
impl Connection {
fn stop(mut self) {
self.receive_task.abort();
self.send_task.abort();
self.map_receive_task.abort();
}
}
#[derive(Default, Copy, Clone, Debug)]
pub struct EventworkPlugin<NP: NetworkProvider, RT: Runtime = bevy::tasks::TaskPool>(
PhantomData<(NP, RT)>,
);
impl<NP: NetworkProvider + Default, RT: Runtime> Plugin for EventworkPlugin<NP, RT> {
fn build(&self, app: &mut App) {
app.insert_resource(managers::Network::new(NP::default()));
app.add_event::<NetworkEvent>();
app.add_system_to_stage(
CoreStage::PreUpdate,
managers::network::handle_new_incoming_connections::<NP, RT>,
);
}
}