From 1461b8e380ee93d2a6947edd9812c210a4cbd956 Mon Sep 17 00:00:00 2001 From: Jonni Liljamo Date: Tue, 14 Feb 2023 14:22:23 +0200 Subject: [PATCH] feat(sdbclient): browse own games --- sdbclient/src/plugins/menu/play/mod.rs | 9 + .../src/plugins/menu/play/mygamescall.rs | 82 +++++ sdbclient/src/plugins/menu/play/ui.rs | 284 ++++++++++++------ 3 files changed, 290 insertions(+), 85 deletions(-) create mode 100644 sdbclient/src/plugins/menu/play/mygamescall.rs diff --git a/sdbclient/src/plugins/menu/play/mod.rs b/sdbclient/src/plugins/menu/play/mod.rs index 187aede..ae2799e 100644 --- a/sdbclient/src/plugins/menu/play/mod.rs +++ b/sdbclient/src/plugins/menu/play/mod.rs @@ -18,10 +18,12 @@ mod ui; mod allformingcall; mod creategamecall; mod joingamecall; +mod mygamescall; struct CreateGameEvent; struct AllFormingEvent; struct JoinGameEvent; +struct MyGamesEvent; pub(super) struct PlayMenuPlugin; @@ -31,6 +33,7 @@ impl Plugin for PlayMenuPlugin { .add_event::() .add_event::() .add_event::() + .add_event::() .add_enter_system(MenuState::Play, play_menu_setup) .add_system_set( ConditionSet::new() @@ -42,6 +45,8 @@ impl Plugin for PlayMenuPlugin { .with_system(allformingcall::handle.run_if(waiting_for_all_forming_call)) .with_system(joingamecall::start.run_on_event::()) .with_system(joingamecall::handle.run_if(waiting_for_join_game_call)) + .with_system(mygamescall::start.run_on_event::()) + .with_system(mygamescall::handle.run_if(waiting_for_my_games_call)) .into(), ); } @@ -69,3 +74,7 @@ fn waiting_for_all_forming_call(rtdmenu: Res) -> bool { fn waiting_for_join_game_call(rtdmenu: Res) -> bool { rtdmenu.waiting_for_join_game_call } + +fn waiting_for_my_games_call(rtdmenu: Res) -> bool { + rtdmenu.waiting_for_my_games_call +} diff --git a/sdbclient/src/plugins/menu/play/mygamescall.rs b/sdbclient/src/plugins/menu/play/mygamescall.rs new file mode 100644 index 0000000..3086608 --- /dev/null +++ b/sdbclient/src/plugins/menu/play/mygamescall.rs @@ -0,0 +1,82 @@ +/* + * This file is part of sdbclient + * Copyright (C) 2023 Jonni Liljamo + * + * Licensed under GPL-3.0-only. + * See LICENSE for licensing information. + */ + +use bevy::{ + prelude::*, + tasks::{AsyncComputeTaskPool, Task}, +}; +use bevy_console::PrintConsoleLine; + +use futures_lite::future; + +use crate::{ + api::{self, game::ResponseMyGames}, + cfg::{CfgDev, CfgUser}, + runtime::menu::RTDMenu, +}; + +use super::MyGamesEvent; + +struct MyGamesCallResponse { + my_games: ResponseMyGames, +} + +#[derive(Component)] +pub(super) struct MyGamesCall(Task); + +pub(super) fn start( + mut events: EventReader, + mut commands: Commands, + cfg_dev: Res, + cfg_user: Res, + mut rtdmenu: ResMut, +) { + for _event in events.iter() { + let api_address = cfg_dev.api_server.clone(); + let token = cfg_user.user_token.clone(); + + let thread_pool = AsyncComputeTaskPool::get(); + let task = thread_pool.spawn(async move { + let my_games_response = api::game::my_games(api_address, token); + + MyGamesCallResponse { + my_games: my_games_response, + } + }); + commands.spawn(MyGamesCall(task)); + rtdmenu.waiting_for_my_games_call = true; + } +} + +pub(super) fn handle( + mut commands: Commands, + mut my_games_call_tasks: Query<(Entity, &mut MyGamesCall)>, + mut rtdmenu: ResMut, + mut console: EventWriter, +) { + if my_games_call_tasks.is_empty() { + return; + } + + let (entity, mut task) = my_games_call_tasks.single_mut(); + if let Some(my_games_call_response) = future::block_on(future::poll_once(&mut task.0)) { + rtdmenu.waiting_for_my_games_call = false; + match my_games_call_response.my_games { + ResponseMyGames::Valid(res) => rtdmenu.my_games = res, + ResponseMyGames::Error(error) => { + console.send(PrintConsoleLine::new( + format!("Fetching own games failed, got error: '{}'", error).into(), + )); + } + } + + // Remove the task, since it's done now + commands.entity(entity).remove::(); + commands.entity(entity).despawn_recursive(); + } +} diff --git a/sdbclient/src/plugins/menu/play/ui.rs b/sdbclient/src/plugins/menu/play/ui.rs index f9223ae..6338469 100644 --- a/sdbclient/src/plugins/menu/play/ui.rs +++ b/sdbclient/src/plugins/menu/play/ui.rs @@ -11,12 +11,13 @@ use bevy_inspector_egui::bevy_egui::{egui, EguiContext}; use iyes_loopless::prelude::*; use crate::{ + api::game::types::GameState, cfg::CfgUser, plugins::menu::MenuState, runtime::menu::{BrowseMenuTab, PlayMenuUIState, RTDMenu}, }; -use super::{AllFormingEvent, CreateGameEvent, JoinGameEvent, PlayMenuState}; +use super::{AllFormingEvent, CreateGameEvent, JoinGameEvent, MyGamesEvent, PlayMenuState}; pub(super) fn show( mut commands: Commands, @@ -26,6 +27,7 @@ pub(super) fn show( mut creategame_ev_w: EventWriter, mut allforming_ev_w: EventWriter, mut joingame_ev_w: EventWriter, + mut mygames_ev_w: EventWriter, ) { egui::Window::new(egui::RichText::new(rtdmenu.play_menu_ui_state.display()).size(32.)) .resizable(false) @@ -77,95 +79,73 @@ pub(super) fn show( }); }); - egui::TopBottomPanel::top("play_top_panel").resizable(false).show_inside(ui, |ui| { - ui.horizontal(|ui| { - ui.label(egui::RichText::new("Browse: ").size(24.)); - - ui.selectable_value(&mut rtdmenu.browse_tab, BrowseMenuTab::Forming, "Forming"); - ui.selectable_value(&mut rtdmenu.browse_tab, BrowseMenuTab::InProgress, "In Progress"); - ui.selectable_value(&mut rtdmenu.browse_tab, BrowseMenuTab::Finished, "Finished"); - - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - if ui.button("Refresh").clicked() { - // refresh the current tab - // oh and also, if the tab content in rtdmenu is empty, should - // fetch when switching to it - match rtdmenu.browse_tab { - BrowseMenuTab::Forming => { - if !rtdmenu.waiting_for_all_forming_call { - allforming_ev_w.send(AllFormingEvent); + egui::TopBottomPanel::top("play_top_panel") + .resizable(false) + .show_inside(ui, |ui| { + ui.horizontal(|ui| { + ui.label(egui::RichText::new("Browse: ").size(24.)); + + ui.selectable_value( + &mut rtdmenu.browse_tab, + BrowseMenuTab::Forming, + "Forming", + ); + ui.selectable_value( + &mut rtdmenu.browse_tab, + BrowseMenuTab::InProgress, + "In Progress", + ); + ui.selectable_value( + &mut rtdmenu.browse_tab, + BrowseMenuTab::Finished, + "Finished", + ); + + ui.with_layout( + egui::Layout::right_to_left(egui::Align::Center), + |ui| { + if ui.button("Refresh").clicked() { + // refresh the current tab + // oh and also, if the tab content in rtdmenu is empty, should + // fetch when switching to it + match rtdmenu.browse_tab { + BrowseMenuTab::Forming => { + if !rtdmenu.waiting_for_all_forming_call { + allforming_ev_w.send(AllFormingEvent); + } + } + BrowseMenuTab::InProgress => { + if !rtdmenu.waiting_for_my_games_call { + mygames_ev_w.send(MyGamesEvent); + } + } + BrowseMenuTab::Finished => { + if !rtdmenu.waiting_for_my_games_call { + mygames_ev_w.send(MyGamesEvent); + } + } } } - BrowseMenuTab::InProgress => todo!(), - BrowseMenuTab::Finished => todo!(), - } - } + }, + ); }); }); - }); ui.vertical_centered(|ui| { - egui::ScrollArea::vertical().show(ui, |ui| { - match rtdmenu.browse_tab { - BrowseMenuTab::Forming => { - if rtdmenu.waiting_for_all_forming_call { - ui.horizontal(|ui| { - ui.spinner(); - ui.label("loading..."); - }); - } else { - if rtdmenu.all_forming_games.is_empty() { - ui.label("No forming games found."); - } else { - for game in rtdmenu.all_forming_games.clone() { - egui::Frame::none() - .fill(egui::Color32::BLACK) - .rounding(4.) - .outer_margin(4.) - .inner_margin(4.) - .show(ui, |ui| { - ui.horizontal(|ui| { - ui.label(format!( - "Host: {}", - game.host.username - )); - ui.with_layout( - egui::Layout::right_to_left( - egui::Align::Center, - ), - |ui| { - if game.guest_id == cfg_user.id { - ui.add_enabled(false, egui::Button::new("Joined")); - if ui.button("Inspect").clicked() { - rtdmenu.cur_game = Some(game.clone()); - rtdmenu.play_menu_ui_state = PlayMenuUIState::InLobbyGuest; - } - } else if game.host_id == cfg_user.id { - ui.add_enabled(false, egui::Button::new("Host")); - if ui.button("Inspect").clicked() { - rtdmenu.cur_game = Some(game.clone()); - rtdmenu.play_menu_ui_state = PlayMenuUIState::InLobbyHost; - } - } else { - if ui.button("Join").clicked() { - rtdmenu.cur_game = Some(game.clone()); - joingame_ev_w.send(JoinGameEvent); - } - } - }, - ); - }); - }); - } - } - } - } - BrowseMenuTab::InProgress => { - - } - BrowseMenuTab::Finished => { - - } + egui::ScrollArea::vertical().show(ui, |mut ui| match rtdmenu.browse_tab { + BrowseMenuTab::Forming => { + browse_forming( + &mut ui, + &mut rtdmenu, + &cfg_user, + &mut joingame_ev_w, + ); + } + BrowseMenuTab::InProgress => { + browse_inprogress(&mut ui, &mut rtdmenu); + } + BrowseMenuTab::Finished => { + browse_finished(&mut ui, &mut rtdmenu); } }); }); @@ -194,7 +174,10 @@ pub(super) fn show( } } PlayMenuUIState::InLobbyGuest => { - ui.label(egui::RichText::new(format!("Host: {}", rtdmenu.cur_game.as_ref().unwrap().host.username))); + ui.label(egui::RichText::new(format!( + "Host: {}", + rtdmenu.cur_game.as_ref().unwrap().host.username + ))); if ui.button("Back").clicked() { rtdmenu.play_menu_ui_state = PlayMenuUIState::Main @@ -203,3 +186,134 @@ pub(super) fn show( } }); } + +fn browse_forming( + ui: &mut egui::Ui, + rtdmenu: &mut RTDMenu, + cfg_user: &CfgUser, + joingame_ev_w: &mut EventWriter, +) { + if rtdmenu.waiting_for_all_forming_call { + ui.horizontal(|ui| { + ui.spinner(); + ui.label("loading..."); + }); + } else { + if rtdmenu.all_forming_games.is_empty() { + ui.label("No forming games found."); + } else { + for game in rtdmenu.all_forming_games.clone() { + egui::Frame::none() + .fill(egui::Color32::BLACK) + .rounding(4.) + .outer_margin(4.) + .inner_margin(4.) + .show(ui, |ui| { + ui.horizontal(|ui| { + ui.label(format!("Host: {}", game.host.username)); + ui.with_layout( + egui::Layout::right_to_left(egui::Align::Center), + |ui| { + if game.guest_id == cfg_user.id { + ui.add_enabled(false, egui::Button::new("Joined")); + if ui.button("Inspect").clicked() { + rtdmenu.cur_game = Some(game.clone()); + rtdmenu.play_menu_ui_state = + PlayMenuUIState::InLobbyGuest; + } + } else if game.host_id == cfg_user.id { + ui.add_enabled(false, egui::Button::new("Host")); + if ui.button("Inspect").clicked() { + rtdmenu.cur_game = Some(game.clone()); + rtdmenu.play_menu_ui_state = + PlayMenuUIState::InLobbyHost; + } + } else { + if ui.button("Join").clicked() { + rtdmenu.cur_game = Some(game.clone()); + joingame_ev_w.send(JoinGameEvent); + } + } + }, + ); + }); + }); + } + } + } +} + +fn browse_inprogress( + ui: &mut egui::Ui, + rtdmenu: &mut RTDMenu, + /*resumegame_ev_w: &mut EventWriter*/ +) { + if rtdmenu.waiting_for_my_games_call { + ui.horizontal(|ui| { + ui.spinner(); + ui.label("loading..."); + }); + } else { + if rtdmenu.my_games.is_empty() { + ui.label("No games found."); + } else { + let mut games = rtdmenu.my_games.clone(); + games.retain(|g| g.state == GameState::InProgress); + + for game in games { + egui::Frame::none() + .fill(egui::Color32::BLACK) + .rounding(4.) + .outer_margin(4.) + .inner_margin(4.) + .show(ui, |ui| { + ui.horizontal(|ui| { + ui.label(format!("Host: {}", game.host.username)); + ui.with_layout( + egui::Layout::right_to_left(egui::Align::Center), + |ui| { + if ui.button("Resume").clicked() { + rtdmenu.cur_game = Some(game.clone()); + //resumegame_ev_w.send(ResumeGameEvent); + } + }, + ); + }); + }); + } + } + } +} + +fn browse_finished( + ui: &mut egui::Ui, + rtdmenu: &mut RTDMenu, + /*resumegame_ev_w: &mut EventWriter*/ +) { + if rtdmenu.waiting_for_my_games_call { + ui.horizontal(|ui| { + ui.spinner(); + ui.label("loading..."); + }); + } else { + if rtdmenu.my_games.is_empty() { + ui.label("No games found."); + } else { + let mut games = rtdmenu.my_games.clone(); + games.retain(|g| g.state == GameState::Finished); + + for game in games { + egui::Frame::none() + .fill(egui::Color32::BLACK) + .rounding(4.) + .outer_margin(4.) + .inner_margin(4.) + .show(ui, |ui| { + ui.horizontal(|ui| { + ui.label(format!("Host: {}", game.host.username)); + }); + }); + } + } + } +} -- 2.44.1