rbp_server/hosting/
client.rs1use 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
15pub 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}