firecore_battle/
endpoint.rs

1use crate::message::{ClientMessage, ServerMessage};
2
3/// Represents a client endpoint for the battle host.
4pub trait BattleEndpoint<ID, T> {
5    fn send(&mut self, message: ServerMessage<ID, T>);
6
7    fn receive(&mut self) -> Result<ClientMessage<ID>, Option<ReceiveError>>;
8}
9
10#[derive(Debug)]
11pub enum ReceiveError {
12    Disconnected,
13}
14
15#[cfg(feature = "mpsc_endpoint")]
16pub use mpsc::*;
17
18#[cfg(feature = "mpsc_endpoint")]
19mod mpsc {
20
21    use crossbeam_channel::{unbounded, Receiver, Sender, TryRecvError};
22
23    use crate::message::{ClientMessage, ServerMessage};
24
25    use super::{BattleEndpoint, ReceiveError};
26
27    pub fn create<ID, T>() -> (MpscClient<ID, T>, MpscEndpoint<ID, T>) {
28        let (serv_sender, receiver) = unbounded();
29        let (sender, serv_receiver) = unbounded();
30
31        (
32            MpscClient { sender, receiver },
33            MpscEndpoint {
34                receiver: serv_receiver,
35                sender: serv_sender,
36            },
37        )
38    }
39
40    #[derive(Clone)]
41    pub struct MpscClient<ID, T> {
42        pub sender: Sender<ClientMessage<ID>>,
43        pub receiver: Receiver<ServerMessage<ID, T>>,
44    }
45
46    #[derive(Clone)]
47    pub struct MpscEndpoint<ID, T> {
48        pub receiver: Receiver<ClientMessage<ID>>,
49        pub sender: Sender<ServerMessage<ID, T>>,
50    }
51
52    impl<ID, T> MpscClient<ID, T> {
53        pub fn send(&self, message: ClientMessage<ID>) {
54            if let Err(err) = self.sender.try_send(message) {
55                log::error!("AI cannot send client message with error {}", err);
56            }
57        }
58    }
59
60    impl<ID, T> BattleEndpoint<ID, T> for MpscEndpoint<ID, T> {
61        fn send(&mut self, message: ServerMessage<ID, T>) {
62            if let Err(err) = self.sender.try_send(message) {
63                log::error!("Cannot send server message to AI with error {}", err);
64            }
65        }
66
67        fn receive(&mut self) -> Result<ClientMessage<ID>, Option<ReceiveError>> {
68            match self.receiver.try_recv() {
69                Ok(m) => Ok(m),
70                Err(err) => Err(match err {
71                    TryRecvError::Empty => None,
72                    TryRecvError::Disconnected => Some(ReceiveError::Disconnected),
73                }),
74            }
75        }
76    }
77}