geng_net_simple/
lobby.rs

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}