1use super::*;
2
3type Connection<T> = geng::net::client::Connection<ServerMessage<T>, <T as Model>::Message>;
4
5pub struct ConnectingState<T: Model, G: geng::State> {
6 geng: Geng,
7 #[allow(clippy::type_complexity)]
8 connection: Option<Pin<Box<dyn Future<Output = (T::PlayerId, T, Connection<T>)>>>>,
9 #[allow(clippy::type_complexity)]
10 f: Option<Box<dyn FnOnce(T::PlayerId, Remote<T>) -> G + 'static>>,
11 transition: Option<geng::state::Transition>,
12}
13
14impl<T: Model, G: geng::State> ConnectingState<T, G> {
15 pub fn new(
16 geng: &Geng,
17 addr: &str,
18 f: impl FnOnce(T::PlayerId, Remote<T>) -> G + 'static,
19 ) -> Self {
20 let connection = Box::pin(
21 geng::net::client::connect(addr).then(|connection| async move {
22 let connection = connection.unwrap();
23 let (message, connection) = connection.into_future().await;
24 let player_id = match message.unwrap().unwrap() {
25 ServerMessage::PlayerId(id) => id,
26 _ => unreachable!(),
27 };
28 let (message, connection) = connection.into_future().await;
29 let initial_state = match message.unwrap().unwrap() {
30 ServerMessage::Full(state) => state,
31 _ => unreachable!(),
32 };
33 (player_id, initial_state, connection)
34 }),
35 );
36 Self {
37 geng: geng.clone(),
38 f: Some(Box::new(f)),
39 connection: Some(connection),
40 transition: None,
41 }
42 }
43}
44
45impl<T: Model, G: geng::State> geng::State for ConnectingState<T, G> {
46 fn draw(&mut self, framebuffer: &mut ugli::Framebuffer) {
47 let framebuffer_size = framebuffer.size();
48 ugli::clear(framebuffer, Some(Rgba::WHITE), None, None);
49 self.geng.default_font().draw(
50 framebuffer,
51 &geng::PixelPerfectCamera,
52 "Connecting to the server...",
53 vec2::splat(geng::TextAlign::CENTER),
54 mat3::translate(framebuffer_size.map(|x| x as f32) / 2.0) * mat3::scale_uniform(40.0),
55 Rgba::BLACK,
56 );
57 }
58 fn handle_event(&mut self, event: geng::Event) {
59 if matches!(
60 event,
61 geng::Event::KeyPress {
62 key: geng::Key::Escape
63 }
64 ) {
65 self.transition = Some(geng::state::Transition::Pop);
66 }
67 }
68 fn transition(&mut self) -> Option<geng::state::Transition> {
69 if let Some(connection) = &mut self.connection {
70 if let std::task::Poll::Ready((player_id, initial_state, connection)) = connection
71 .as_mut()
72 .poll(&mut std::task::Context::from_waker(
73 futures::task::noop_waker_ref(),
74 ))
75 {
76 return Some(geng::state::Transition::Switch(Box::new(self
77 .f
78 .take()
79 .unwrap()(
80 player_id,
81 Remote {
82 connection: RefCell::new(connection),
83 model: RefCell::new(initial_state),
84 },
85 ))));
86 }
87 }
88 self.transition.take()
89 }
90}