evoke_core/client_server/
client.rs1use std::error::Error;
2
3use alkahest::{Schema, Unpacked};
4use scoped_arena::Scope;
5
6use crate::channel::Channel;
7
8use super::*;
9
10#[derive(Debug, thiserror::Error)]
11pub enum ClientError<E: Error + 'static> {
12 #[error("Client channel error: {source}")]
13 ChannelError {
14 #[from]
15 source: E,
16 },
17
18 #[error("Unexpected server message")]
19 UnexpectedMessage,
20}
21pub struct Updates<'a, U: Schema> {
22 pub server_step: u64,
23 pub updates: Unpacked<'a, U>,
24}
25
26pub struct ClientSession<C> {
27 channel: C,
28 current_step: u64,
29 next_update_step: u64,
30}
31
32impl<C> ClientSession<C>
33where
34 C: Channel,
35{
36 pub async fn new(channel: C, scope: &Scope<'_>) -> Result<Self, ClientError<C::Error>> {
38 let mut channel = channel;
39 channel
40 .send_reliable::<ClientMessage, _>(ClientMessageConnectPack { token: "evoke" }, scope)
41 .await?;
42
43 loop {
44 match channel.recv::<ServerMessage>(scope) {
45 Ok(Some(ServerMessageUnpacked::Connected { step })) => {
46 return Ok(ClientSession {
47 channel,
48 current_step: step,
49 next_update_step: 0,
50 });
51 }
52 Ok(Some(ServerMessageUnpacked::Updates { .. })) => {}
53 Ok(Some(ServerMessageUnpacked::PlayerJoined { .. })) => {
54 return Err(ClientError::UnexpectedMessage)
55 }
56 Ok(None) => {
57 channel.recv_ready().await?;
58 }
59 Err(err) => return Err(err.into()),
60 }
61 }
62 }
63
64 pub fn current_step(&self) -> u64 {
65 self.current_step
66 }
67
68 pub async fn add_player<'a, P, J, K>(
70 &mut self,
71 player: K,
72 scope: &'a Scope<'a>,
73 ) -> Result<Unpacked<'a, J>, ClientError<C::Error>>
74 where
75 P: Schema,
76 J: Schema,
77 K: Pack<P>,
78 {
79 self.channel
80 .send_reliable::<ClientMessage<P>, _>(ClientMessageAddPlayerPack { player }, scope)
81 .await?;
82
83 loop {
84 match self.channel.recv::<ServerMessage<J>>(scope) {
85 Ok(Some(ServerMessageUnpacked::PlayerJoined { info })) => return Ok(info),
86 Ok(Some(ServerMessageUnpacked::Connected { .. })) => {
87 return Err(ClientError::UnexpectedMessage)
88 }
89 Ok(Some(ServerMessageUnpacked::Updates { .. })) => {}
90 Ok(None) => {
91 self.channel.recv_ready().await?;
92 }
93 Err(err) => return Err(err.into()),
94 }
95 }
96 }
97
98 pub async fn send_inputs<T, K, I>(
100 &mut self,
101 inputs: I,
102 scope: &Scope<'_>,
103 ) -> Result<(), C::Error>
104 where
105 T: Schema,
106 K: Pack<T>,
107 I: IntoIterator,
108 I::IntoIter: ExactSizeIterator<Item = (PlayerId, K)>,
109 {
110 self.channel
111 .send_reliable::<ClientMessage<(), T>, _>(
112 ClientMessageInputsPack {
113 step: self.current_step,
114 next_update_step: self.next_update_step,
115 inputs: inputs.into_iter(),
116 },
117 scope,
118 )
119 .await?;
120
121 Ok(())
122 }
123
124 pub fn advance<'a, U>(
126 &mut self,
127 scope: &'a Scope<'_>,
128 ) -> Result<Option<Updates<'a, U>>, ClientError<C::Error>>
129 where
130 U: Schema,
131 {
132 let updates = match self.channel.recv::<ServerMessage<(), U>>(scope) {
133 Ok(Some(ServerMessageUnpacked::Updates {
134 server_step,
135 updates,
136 })) => {
137 self.next_update_step = server_step + 1;
138 Some(Updates {
139 server_step,
140 updates,
141 })
142 }
143 Ok(Some(_)) => return Err(ClientError::UnexpectedMessage),
144 Ok(None) => None,
145 Err(err) => return Err(err.into()),
146 };
147
148 self.current_step += 1;
149 Ok(updates)
150 }
151}