use aetheris_protocol::events::NetworkEvent;
use aetheris_protocol::traits::{ClientId, GameTransport, TransportError};
use async_trait::async_trait;
pub struct MultiTransport {
transports: Vec<Box<dyn GameTransport>>,
}
impl MultiTransport {
#[must_use]
pub fn new() -> Self {
Self {
transports: Vec::new(),
}
}
pub fn add_transport(&mut self, transport: Box<dyn GameTransport>) {
self.transports.push(transport);
}
}
impl Default for MultiTransport {
fn default() -> Self {
Self::new()
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl GameTransport for MultiTransport {
async fn send_unreliable(
&self,
client_id: ClientId,
data: &[u8],
) -> Result<(), TransportError> {
for transport in &self.transports {
match transport.send_unreliable(client_id, data).await {
Ok(()) => return Ok(()),
Err(TransportError::ClientNotConnected(_)) => {}
Err(e) => {
tracing::error!("MultiTransport: individual transport send error: {:?}", e);
return Err(e);
}
}
}
Err(TransportError::ClientNotConnected(client_id))
}
async fn send_reliable(&self, client_id: ClientId, data: &[u8]) -> Result<(), TransportError> {
for transport in &self.transports {
match transport.send_reliable(client_id, data).await {
Ok(()) => return Ok(()),
Err(TransportError::ClientNotConnected(_)) => {}
Err(e) => {
tracing::error!("MultiTransport: individual transport send error: {:?}", e);
return Err(e);
}
}
}
Err(TransportError::ClientNotConnected(client_id))
}
async fn broadcast_unreliable(&self, data: &[u8]) -> Result<(), TransportError> {
let mut first_error = None;
for transport in &self.transports {
if let Err(e) = transport.broadcast_unreliable(data).await
&& first_error.is_none()
{
first_error = Some(e);
}
}
if let Some(e) = first_error {
Err(e)
} else {
Ok(())
}
}
async fn poll_events(&mut self) -> Result<Vec<NetworkEvent>, TransportError> {
let mut all_events = Vec::new();
for transport in &mut self.transports {
all_events.extend(transport.poll_events().await?);
}
Ok(all_events)
}
async fn connected_client_count(&self) -> usize {
let mut total = 0;
for transport in &self.transports {
total += transport.connected_client_count().await;
}
total
}
}