use core::str; use tokio::io::AsyncWriteExt; use tracing::{info_span, trace, warn, Instrument}; use uuid::Uuid; use wtransport::endpoint::IncomingSession; use xtra::{Actor, Address, Handler, Mailbox}; use zerocopy::IntoBytes; use super::{ listeners, packet::HelloPlayer, ChangedStage, Manager, PlayerConnected, PlayerDisconnected, PlayerMoved, RequestState, }; pub struct ProximityPlayer { id: Uuid, _send: wtransport::SendStream, _connection: wtransport::Connection, } impl ProximityPlayer { pub fn spawn(session: IncomingSession, manager: Address) { tokio::spawn( async move { trace!("proximity chat client connected"); let connection = session.await.expect("failed to acknowledge session").accept().await.expect("failed to accept session"); let (mut send, mut recv) = connection.accept_bi().await.expect("failed to start channel"); trace!("getting peerjs uuid"); let mut buffer = [0; 36]; recv.read_exact(buffer.as_mut_bytes()).await.expect("failed to read uuid"); let id = Uuid::parse_str(str::from_utf8(&buffer).expect("expected utf8")).expect("failed to parse uuid"); let span = info_span!("", %id); span.in_scope(||trace!( "uuid parsed")); let state = manager.send(RequestState).await.unwrap(); send.write_u8(state.len() as u8).await.expect("failed to write length"); for player in state.values() { trace!("sending player {player:?}"); send.write_all(HelloPlayer::from(*player).as_bytes()).await.expect("failed to write player"); } let (address, mailbox) = Mailbox::unbounded(); listeners().write().await.insert(id, address); xtra::run(mailbox, ProximityPlayer { id, _send: send, _connection: connection }).instrument(span).await; } .in_current_span(), ); } } impl Actor for ProximityPlayer { type Stop = (); async fn stopped(self) -> Self::Stop { listeners().write().await.remove(&self.id); } } impl Handler for ProximityPlayer { type Return = (); async fn handle(&mut self, _message: PlayerConnected, _: &mut xtra::Context) -> Self::Return { warn!("todo: implement player connected") } } impl Handler for ProximityPlayer { type Return = (); async fn handle(&mut self, _message: PlayerDisconnected, _: &mut xtra::Context) -> Self::Return { warn!("todo: implement player disconnected") } } impl Handler for ProximityPlayer { type Return = (); async fn handle(&mut self, _message: PlayerMoved, _: &mut xtra::Context) -> Self::Return { warn!("todo: implement player moved") } } impl Handler for ProximityPlayer { type Return = (); async fn handle(&mut self, _message: ChangedStage, _: &mut xtra::Context) -> Self::Return { warn!("todo: implement changed stage") } }