DEVELOPMENT ENVIRONMENT

~liljamo/deck-builder

1461b8e380ee93d2a6947edd9812c210a4cbd956 — Jonni Liljamo 1 year, 10 months ago a77b7b6
feat(sdbclient): browse own games
M sdbclient/src/plugins/menu/play/mod.rs => sdbclient/src/plugins/menu/play/mod.rs +9 -0
@@ 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::<CreateGameEvent>()
            .add_event::<AllFormingEvent>()
            .add_event::<JoinGameEvent>()
            .add_event::<MyGamesEvent>()
            .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::<JoinGameEvent>())
                    .with_system(joingamecall::handle.run_if(waiting_for_join_game_call))
                    .with_system(mygamescall::start.run_on_event::<MyGamesEvent>())
                    .with_system(mygamescall::handle.run_if(waiting_for_my_games_call))
                    .into(),
            );
    }


@@ 69,3 74,7 @@ fn waiting_for_all_forming_call(rtdmenu: Res<RTDMenu>) -> bool {
fn waiting_for_join_game_call(rtdmenu: Res<RTDMenu>) -> bool {
    rtdmenu.waiting_for_join_game_call
}

fn waiting_for_my_games_call(rtdmenu: Res<RTDMenu>) -> bool {
    rtdmenu.waiting_for_my_games_call
}

A sdbclient/src/plugins/menu/play/mygamescall.rs => sdbclient/src/plugins/menu/play/mygamescall.rs +82 -0
@@ 0,0 1,82 @@
/*
 * 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::ResponseMyGames},
    cfg::{CfgDev, CfgUser},
    runtime::menu::RTDMenu,
};

use super::MyGamesEvent;

struct MyGamesCallResponse {
    my_games: ResponseMyGames,
}

#[derive(Component)]
pub(super) struct MyGamesCall(Task<MyGamesCallResponse>);

pub(super) fn start(
    mut events: EventReader<MyGamesEvent>,
    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 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<RTDMenu>,
    mut console: EventWriter<PrintConsoleLine>,
) {
    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::<MyGamesCall>();
        commands.entity(entity).despawn_recursive();
    }
}

M sdbclient/src/plugins/menu/play/ui.rs => sdbclient/src/plugins/menu/play/ui.rs +199 -85
@@ 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<CreateGameEvent>,
    mut allforming_ev_w: EventWriter<AllFormingEvent>,
    mut joingame_ev_w: EventWriter<JoinGameEvent>,
    mut mygames_ev_w: EventWriter<MyGamesEvent>,
) {
    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<JoinGameEvent>,
) {
    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<ResumeGameEvent>*/
) {
    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<ResumeGameEvent>*/
) {
    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));
                        });
                    });
            }
        }
    }
}