M sdbclient/src/api/game/mod.rs => sdbclient/src/api/game/mod.rs +1 -1
@@ 11,7 11,7 @@ use serde::{Deserialize, Serialize};
use super::APIErrorWrapper;
-mod types;
+pub mod types;
#[derive(Debug, Serialize, Deserialize)]
pub struct ResultCreateGame {
M sdbclient/src/api/game/types.rs => sdbclient/src/api/game/types.rs +0 -1
@@ 16,4 16,3 @@ pub struct Game {
pub state: u8,
pub ended_at: String,
}
-
A => +84 -0
@@ 0,0 1,84 @@
/*
* This file is part of sdbclient
* Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
*
* 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::ResponseAllForming},
cfg::{CfgDev, CfgUser},
runtime::menu::RTDMenu,
};
use super::AllFormingEvent;
struct AllFormingCallResponse {
all_forming: ResponseAllForming,
}
#[derive(Component)]
pub(super) struct AllFormingCall(Task<AllFormingCallResponse>);
pub(super) fn start(
mut events: EventReader<AllFormingEvent>,
mut commands: Commands,
cfg_dev: Res<CfgDev>,
cfg_user: Res<CfgUser>,
mut rtdmenu: ResMut<RTDMenu>,
) {
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 all_forming_response = api::game::all_forming(api_address, token);
AllFormingCallResponse {
all_forming: all_forming_response,
}
});
commands.spawn(AllFormingCall(task));
rtdmenu.waiting_for_all_forming_call = true;
}
}
pub(super) fn handle(
mut commands: Commands,
mut all_forming_call_tasks: Query<(Entity, &mut AllFormingCall)>,
mut rtdmenu: ResMut<RTDMenu>,
mut console: EventWriter<PrintConsoleLine>,
) {
if all_forming_call_tasks.is_empty() {
return;
}
let (entity, mut task) = all_forming_call_tasks.single_mut();
if let Some(all_forming_call_response) = future::block_on(future::poll_once(&mut task.0)) {
rtdmenu.waiting_for_all_forming_call = false;
match all_forming_call_response.all_forming {
ResponseAllForming::Valid(res) => {
rtdmenu.all_forming_games = res.games;
}
ResponseAllForming::Error(error) => {
console.send(PrintConsoleLine::new(
format!("Fetching all forming games faield, got error: '{}'", error).into(),
));
}
}
// Remove the task, since it's done now
commands.entity(entity).remove::<AllFormingCall>();
commands.entity(entity).despawn_recursive();
}
}
M => +9 -0
@@ 15,9 15,11 @@ use super::MenuState;
mod ui;
mod allformingcall;
mod creategamecall;
struct CreateGameEvent;
struct AllFormingEvent;
pub(super) struct PlayMenuPlugin;
@@ 25,6 27,7 @@ impl Plugin for PlayMenuPlugin {
fn build(&self, app: &mut App) {
app.add_loopless_state(PlayMenuState::None)
.add_event::<CreateGameEvent>()
.add_event::<AllFormingEvent>()
.add_enter_system(MenuState::Play, play_menu_setup)
.add_system_set(
ConditionSet::new()
@@ 32,6 35,8 @@ impl Plugin for PlayMenuPlugin {
.with_system(ui::show)
.with_system(creategamecall::start.run_on_event::<CreateGameEvent>())
.with_system(creategamecall::handle.run_if(waiting_for_create_game_call))
.with_system(allformingcall::start.run_on_event::<AllFormingEvent>())
.with_system(allformingcall::handle.run_if(waiting_for_all_forming_call))
.into(),
);
}
@@ 51,3 56,7 @@ fn play_menu_setup(mut commands: Commands) {
fn waiting_for_create_game_call(rtdmenu: Res<RTDMenu>) -> bool {
rtdmenu.waiting_for_create_game_call
}
fn waiting_for_all_forming_call(rtdmenu: Res<RTDMenu>) -> bool {
rtdmenu.waiting_for_all_forming_call
}
M => +67 -26
@@ 15,15 15,16 @@ use crate::{
runtime::menu::{PlayMenuUIState, RTDMenu},
};
use super::{CreateGameEvent, PlayMenuState};
use super::{AllFormingEvent, CreateGameEvent, PlayMenuState};
pub(super) fn show(
mut commands: Commands,
mut egui_context: ResMut<EguiContext>,
mut rtdmenu: ResMut<RTDMenu>,
mut creategame_ev_w: EventWriter<CreateGameEvent>,
mut allforming_ev_w: EventWriter<AllFormingEvent>,
) {
egui::Window::new(egui::RichText::new(rtdmenu.play_menu_ui_state.display()).size(42.))
egui::Window::new(egui::RichText::new(rtdmenu.play_menu_ui_state.display()).size(32.))
.resizable(false)
.collapsible(false)
.anchor(egui::Align2::CENTER_CENTER, egui::Vec2::ZERO)
@@ 31,30 32,77 @@ pub(super) fn show(
// Override egui style for this scope.
let mut egui_style = (*ui.style_mut()).clone();
egui_style.text_styles = [
(egui::TextStyle::Heading, egui::FontId::new(30.0, egui::FontFamily::Proportional)),
(egui::TextStyle::Body, egui::FontId::new(18.0, egui::FontFamily::Proportional)),
(egui::TextStyle::Monospace, egui::FontId::new(14.0, egui::FontFamily::Proportional)),
(egui::TextStyle::Button, egui::FontId::new(32.0, egui::FontFamily::Proportional)),
(egui::TextStyle::Small, egui::FontId::new(10.0, egui::FontFamily::Proportional)),
].into();
(
egui::TextStyle::Heading,
egui::FontId::new(30.0, egui::FontFamily::Proportional),
),
(
egui::TextStyle::Body,
egui::FontId::new(18.0, egui::FontFamily::Proportional),
),
(
egui::TextStyle::Monospace,
egui::FontId::new(14.0, egui::FontFamily::Proportional),
),
(
egui::TextStyle::Button,
egui::FontId::new(24.0, egui::FontFamily::Proportional),
),
(
egui::TextStyle::Small,
egui::FontId::new(10.0, egui::FontFamily::Proportional),
),
]
.into();
ui.set_style(egui_style);
match rtdmenu.play_menu_ui_state {
PlayMenuUIState::Main => {
ui.vertical_centered(|ui| {
if ui.button("Create").clicked() {
rtdmenu.play_menu_ui_state = PlayMenuUIState::CreateGame
}
egui::SidePanel::left("play_side_panel").show_inside(ui, |ui| {
ui.vertical_centered(|ui| {
if ui.button("Create").clicked() {
rtdmenu.play_menu_ui_state = PlayMenuUIState::CreateGame
}
if ui.button("Browse").clicked() {
rtdmenu.play_menu_ui_state = PlayMenuUIState::BrowseGames
}
if ui.button("Refresh Browse").clicked() {
allforming_ev_w.send(AllFormingEvent);
}
if ui.button("Back").clicked() {
commands.insert_resource(NextState(PlayMenuState::None));
commands.insert_resource(NextState(MenuState::Main));
}
if ui.button("Back").clicked() {
commands.insert_resource(NextState(PlayMenuState::None));
commands.insert_resource(NextState(MenuState::Main));
}
});
});
match rtdmenu.waiting_for_all_forming_call {
true => {
ui.horizontal(|ui| {
ui.spinner();
ui.label("loading...");
});
}
false => {
ui.vertical_centered(|ui| {
egui::ScrollArea::vertical()
.max_height(200.)
.show(ui, |ui| match rtdmenu.all_forming_games.is_empty() {
true => {
ui.label("No games found.");
}
false => {
for game in &rtdmenu.all_forming_games {
egui::Frame::none().show(ui, |ui| {
ui.horizontal(|ui| {
ui.label(format!("Host: {}", game.p1));
});
});
}
}
});
});
}
}
}
PlayMenuUIState::CreateGame => {
ui.vertical_centered(|ui| {
@@ 69,13 117,6 @@ pub(super) fn show(
});
});
}
PlayMenuUIState::BrowseGames => {
ui.vertical_centered(|ui| {
if ui.button("Back").clicked() {
rtdmenu.play_menu_ui_state = PlayMenuUIState::Main
}
});
}
PlayMenuUIState::InLobbyHost => {
if ui.button("Back").clicked() {
rtdmenu.play_menu_ui_state = PlayMenuUIState::Main
M => +7 -2
@@ 8,6 8,8 @@
use bevy::prelude::Resource;
use crate::api::game::types::Game;
/// Runtime data for use in the menu
#[derive(Resource)]
pub(crate) struct RTDMenu {
@@ 15,6 17,9 @@ pub(crate) struct RTDMenu {
pub waiting_for_create_game_call: bool,
/// Current game ID, for showing lobby data etc
pub cur_game_id: String,
/// List of all forming games
pub all_forming_games: Vec<Game>,
pub waiting_for_all_forming_call: bool,
}
impl Default for RTDMenu {
@@ 23,6 28,8 @@ impl Default for RTDMenu {
play_menu_ui_state: PlayMenuUIState::Main,
waiting_for_create_game_call: false,
cur_game_id: String::from(""),
all_forming_games: vec![],
waiting_for_all_forming_call: false,
}
}
}
@@ 30,7 37,6 @@ impl Default for RTDMenu {
pub(crate) enum PlayMenuUIState {
Main,
CreateGame,
BrowseGames,
InLobbyHost,
InLobbyGuest,
}
@@ 40,7 46,6 @@ impl PlayMenuUIState {
match self {
PlayMenuUIState::Main => "Play",
PlayMenuUIState::CreateGame => "Create",
PlayMenuUIState::BrowseGames => "Browse",
PlayMenuUIState::InLobbyHost => "Lobby (Host)",
PlayMenuUIState::InLobbyGuest => "Lobby (Guest)",
}