DEVELOPMENT ENVIRONMENT

~liljamo/deck-builder

7a4f6e5f3fc21b3ebee255d6ceb849fc31cbdf2a — Jonni Liljamo 1 year, 8 months ago 5f0740c
WIP(sdbclient): browse games from play screen
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 sdbclient/src/plugins/menu/play/allformingcall.rs => sdbclient/src/plugins/menu/play/allformingcall.rs +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 sdbclient/src/plugins/menu/play/mod.rs => sdbclient/src/plugins/menu/play/mod.rs +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 sdbclient/src/plugins/menu/play/ui.rs => sdbclient/src/plugins/menu/play/ui.rs +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 sdbclient/src/runtime/menu/mod.rs => sdbclient/src/runtime/menu/mod.rs +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)",
        }