Skip to main content

rbp_server/hosting/
client.rs

1use rbp_gameplay::Action;
2use rbp_gameplay::Partial;
3use rbp_gameplay::Recall;
4use rbp_gameroom::Event;
5use rbp_gameroom::Player;
6use rbp_gameroom::Protocol;
7use rbp_gameroom::ServerMessage;
8use std::sync::Arc;
9use std::sync::atomic::AtomicBool;
10use std::sync::atomic::Ordering;
11use tokio::sync::Mutex;
12use tokio::sync::mpsc::UnboundedReceiver;
13use tokio::sync::mpsc::UnboundedSender;
14
15/// Network player that communicates via tokio channels.
16/// Designed to bridge WebSocket connections to the Room actor system.
17///
18/// The tx channel sends JSON (ServerMessage) to the WebSocket client.
19/// The rx channel receives action strings from the WebSocket client.
20pub struct Client {
21    tx: UnboundedSender<String>,
22    rx: Arc<Mutex<UnboundedReceiver<String>>>,
23    alive: Arc<AtomicBool>,
24}
25
26impl Client {
27    pub fn new(tx: UnboundedSender<String>, rx: Arc<Mutex<UnboundedReceiver<String>>>) -> Self {
28        Self {
29            tx,
30            rx,
31            alive: Arc::new(AtomicBool::new(true)),
32        }
33    }
34    fn send(&self, msg: ServerMessage) {
35        let _ = self.tx.send(msg.to_json());
36    }
37}
38
39#[async_trait::async_trait]
40impl Player for Client {
41    fn alive(&self) -> bool {
42        self.alive.load(Ordering::SeqCst)
43    }
44    async fn decide(&mut self, recall: &Partial) -> Action {
45        loop {
46            match self.rx.lock().await.recv().await {
47                None => {
48                    self.alive.store(false, Ordering::SeqCst);
49                    return recall.head().passive();
50                }
51                Some(s) => match Action::try_from(s.as_str())
52                    .ok()
53                    .filter(|a| recall.head().is_allowed(a))
54                {
55                    Some(a) => return a,
56                    None => continue,
57                },
58            }
59        }
60    }
61    async fn notify(&mut self, event: &Event) {
62        if let Some(msg) = Protocol::encode(event) {
63            self.send(msg);
64        }
65    }
66}