diff --git a/client/src/main.rs b/client/src/main.rs index 4eb40ff..7b62623 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -8,7 +8,10 @@ use bevy::{ use thiserror::Error; use tungstenite::{WebSocket, http::Response, stream::MaybeTlsStream}; -use crate::ui::{despawn_main_menu, spawn_main_menu}; +use crate::ui::{ + despawn_connection_wait_screen, despawn_main_menu, spawn_connection_wait_screen, + spawn_main_menu, +}; mod ui; @@ -23,6 +26,24 @@ fn main() { .add_systems(OnExit(GameState::MainMenu), despawn_main_menu) .add_observer(ui::button_hover_start) .add_observer(ui::button_hover_stop) + .add_systems( + OnEnter(GameState::Connecting), + ( + spawn_connection_wait_screen, + // Closure to immediately dispatch a setup-connection request. + |mut messages: MessageWriter| { + messages.write(WebSocketConnectionMessage::SetupConnection); + }, + ), + ) + .add_systems( + OnExit(GameState::Connecting), + despawn_connection_wait_screen, + ) + .add_systems( + Update, + (setup_connection, handle_tasks).run_if(in_state(GameState::Connecting)), + ) .add_systems(OnEnter(GameState::Playing), setup_game) .add_systems( Update, @@ -46,6 +67,7 @@ fn main() { #[derive(Clone, Debug, Eq, Hash, PartialEq, States)] enum GameState { MainMenu, + Connecting, Playing, ConnectionDemo, // TODO: Remove this state. } @@ -102,7 +124,7 @@ fn setup_game( struct Ball; /// Marker component for player paddles -/// +/// /// Maybe one for each player? /// Maybe it can hold the WebSocket, too. /// *Maybe* I can have one struct with an Option to know which @@ -216,12 +238,17 @@ fn setup_connection( /// /// The task is self-removing, so we don't need to delete the [`WsSetupTask`] /// component here. -fn handle_tasks(mut commands: Commands, mut transform_tasks: Query<&mut WsSetupTask>) { +fn handle_tasks( + mut commands: Commands, + mut transform_tasks: Query<&mut WsSetupTask>, + mut states: ResMut>, +) { for mut task in &mut transform_tasks { if let Some(result) = block_on(future::poll_once(&mut task.0)) { match result { Ok(mut commands_queue) => { commands.append(&mut commands_queue); + states.set(GameState::Playing); } Err(e) => info!("Connection failed. Err: {e:?}"), } diff --git a/client/src/ui.rs b/client/src/ui.rs index d569111..c3c0d78 100644 --- a/client/src/ui.rs +++ b/client/src/ui.rs @@ -33,7 +33,7 @@ pub fn spawn_main_menu(mut commands: Commands) { let mut start_button = cmds.spawn(button_bundle("Start game")); start_button.observe( |_trigger: On>, mut game_state: ResMut>| { - game_state.set(GameState::Playing); + game_state.set(GameState::Connecting); }, ); let mut quit_button = cmds.spawn(button_bundle("Quit Game")); @@ -58,6 +58,29 @@ pub fn despawn_main_menu( commands.entity(top_node.into_inner()).despawn(); } +pub fn spawn_connection_wait_screen(mut commands: Commands) { + info!("Spawning connecting notice."); + commands.spawn(( + Node { + width: Val::Percent(100.0), + height: Val::Percent(100.0), + align_items: AlignItems::Center, + justify_content: JustifyContent::Center, + flex_direction: FlexDirection::Column, + ..Default::default() + }, + children![Text::new("Connecting...")], + )); +} + +pub fn despawn_connection_wait_screen( + mut commands: Commands, + text_nodes: Single, With)>, +) { + info!("Despawning connecting notice."); + commands.entity(text_nodes.into_inner()).despawn(); +} + /// The basic bundle for generic buttons. /// /// It's mostly so I don't have to copy & paste this everywhere I want to use it.