/*
* This file is part of laurelin_client
* Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
*
* Licensed under GPL-3.0-only.
* See LICENSE for licensing information.
*/
use bevy::prelude::*;
use bevy_egui::{egui, EguiContexts};
use crate::{
api::game::{Action, Command, Game},
game_status::{Card, PlayerState},
plugins::{GameActionCreateCallEvent, GameDetailsCallEvent},
AppState, Global,
};
use super::{supply::SpawnSupplyPilesEvent, GameData};
pub struct GameUIPlugin;
impl Plugin for GameUIPlugin {
fn build(&self, app: &mut App) {
app.add_system(dev_details_ui.run_if(in_state(AppState::InGame)));
}
}
pub fn dev_details_ui(
mut contexts: EguiContexts,
global: Res<Global>,
game_data: Res<GameData>,
mut details_ev_w: EventWriter<GameDetailsCallEvent>,
mut create_action_ev_w: EventWriter<GameActionCreateCallEvent>,
mut ssp_ev_w: EventWriter<SpawnSupplyPilesEvent>,
) {
egui::Window::new("Game Details").show(contexts.ctx_mut(), |ui| {
let Some(game) = &game_data.game else {
// early return if game is None
return;
};
let Some(status) = &game_data.game_status else {
if game_data.parsing_data {
// early return if game_status is None, and we're parsing it
return;
}
// game_status is None, but we're not parsing it...
// should be unreachable, I think?
return;
};
if ui.button("Refresh").clicked() {
details_ev_w.send(GameDetailsCallEvent {
game_id: game_data.game.as_ref().unwrap().id.clone(),
});
}
if status.actions.is_empty() && game.host_id == global.user.as_ref().unwrap().id {
if ui.button("Init Game").clicked() {
// NOTE/FIXME: hardcoded game init
hardcoded_init(game, &mut create_action_ev_w);
}
}
if ui.button("spawn things").clicked() {
ssp_ev_w.send(SpawnSupplyPilesEvent);
}
ui.separator();
egui::CollapsingHeader::new("Game")
.default_open(true)
.show(ui, |ui| {
ui.label(format!("Host: {}", game.host.as_ref().unwrap().username));
ui.label(format!("Guest: {}", game.guest.as_ref().unwrap().username));
ui.label(format!("State: {:?}", game.state));
});
egui::CollapsingHeader::new("Supply Piles")
.default_open(false)
.show(ui, |ui| {
for pile in &status.supply_piles {
egui::CollapsingHeader::new(&pile.card.name)
.default_open(true)
.show(ui, |ui| {
ui.label(format!("Amount: {}", pile.amount));
});
}
});
egui::CollapsingHeader::new("Log")
.default_open(false)
.show(ui, |ui| {
egui::ScrollArea::vertical()
.max_width(f32::INFINITY)
.show(ui, |ui| {
for (i, action) in status.actions.iter().enumerate() {
egui::CollapsingHeader::new(format!("{}", i))
.default_open(false)
.show(ui, |ui| {
ui.add(
egui::TextEdit::multiline(
&mut serde_json::to_string_pretty(action).unwrap(),
)
.code_editor()
.interactive(false)
.desired_width(f32::INFINITY),
);
});
}
});
});
});
}
fn hardcoded_init(game: &Game, create_action_ev_w: &mut EventWriter<GameActionCreateCallEvent>) {
// first, piles
create_action_ev_w.send(GameActionCreateCallEvent {
action: Action::new(
&game.id,
&game.host_id,
&game.host_id,
&Command::InitSupplyPile {
card: Card {
name: "Narcissistic Cannibal".to_string(),
short_details: vec![],
long_details: vec![],
cost: 4,
actions: vec![],
},
amount: 10,
},
fastrand::u64(u64::MIN..=u64::MAX),
),
});
create_action_ev_w.send(GameActionCreateCallEvent {
action: Action::new(
&game.id,
&game.host_id,
&game.host_id,
&Command::InitSupplyPile {
card: Card {
name: "Test Card 2".to_string(),
short_details: vec![],
long_details: vec![],
cost: 0,
actions: vec![],
},
amount: 10,
},
fastrand::u64(u64::MIN..=u64::MAX),
),
});
create_action_ev_w.send(GameActionCreateCallEvent {
action: Action::new(
&game.id,
&game.host_id,
&game.host_id,
&Command::InitSupplyPile {
card: Card {
name: "Test Card 3".to_string(),
short_details: vec![],
long_details: vec![],
cost: 4,
actions: vec![],
},
amount: 10,
},
fastrand::u64(u64::MIN..=u64::MAX),
),
});
create_action_ev_w.send(GameActionCreateCallEvent {
action: Action::new(
&game.id,
&game.host_id,
&game.host_id,
&Command::InitSupplyPile {
card: Card {
name: "Test Card 4".to_string(),
short_details: vec![],
long_details: vec![],
cost: 2,
actions: vec![],
},
amount: 10,
},
fastrand::u64(u64::MIN..=u64::MAX),
),
});
// second, set a player to the action phase, to start the game
create_action_ev_w.send(GameActionCreateCallEvent {
action: Action::new(
&game.id,
&game.host_id,
&game.host_id,
&Command::ChangePlayerState {
state: PlayerState::ActionPhase,
},
fastrand::u64(u64::MIN..=u64::MAX),
),
});
}