From 7981ec061606d1d1fa65617ebc1173a7bc79c9eb Mon Sep 17 00:00:00 2001 From: Jonni Liljamo Date: Sun, 21 May 2023 23:11:36 +0300 Subject: [PATCH] feat(client): revamp log system --- client/src/game_status/mod.rs | 30 ++++++++++ client/src/game_status/parser.rs | 5 +- client/src/plugins/game/ui/log.rs | 28 +++++++-- client/src/util/action_to_log.rs | 94 ++++++++++++++++--------------- 4 files changed, 107 insertions(+), 50 deletions(-) diff --git a/client/src/game_status/mod.rs b/client/src/game_status/mod.rs index b93dff0..3badf6c 100644 --- a/client/src/game_status/mod.rs +++ b/client/src/game_status/mod.rs @@ -68,6 +68,8 @@ pub struct PlayerStatus { /// constructed from a vector of [`Action`]s #[derive(Clone)] pub struct GameStatus { + /// log entries, filled in one at a time when parsing actions + pub log: Vec, /// a modifiable Actions Vector, will be modified when parsing actions, /// used for showing the log pub actions: Vec, @@ -84,3 +86,31 @@ impl GameStatus { } } } + +#[derive(Clone)] +pub struct LogEntry { + pub sections: Vec, +} + +impl LogEntry { + pub fn from_sections(sections: impl IntoIterator) -> Self { + Self { + sections: sections.into_iter().collect(), + } + } +} + +#[derive(Clone)] +pub enum LogSection { + Normal(String), + Bold(String), +} + +impl LogSection { + pub fn normal(value: &str) -> LogSection { + LogSection::Normal(value.to_string()) + } + pub fn bold(value: &str) -> LogSection { + LogSection::Bold(value.to_string()) + } +} diff --git a/client/src/game_status/parser.rs b/client/src/game_status/parser.rs index 29705f1..cb65c3f 100644 --- a/client/src/game_status/parser.rs +++ b/client/src/game_status/parser.rs @@ -12,7 +12,7 @@ use fastrand::Rng; use crate::{ api::game::{Action, Command, Game}, - game_status::SupplyPile, + game_status::SupplyPile, util::action_to_log, }; use super::{GameStatus, PlayerState, PlayerStatus}; @@ -43,6 +43,7 @@ where pub fn parse(game: &Game) -> Result { let mut game_status = GameStatus { + log: vec![], actions: game.actions.as_ref().unwrap().to_vec(), supply_piles: vec![], players: HashMap::new(), @@ -94,6 +95,8 @@ macro_rules! current_seed { } fn parse_action(action: &Action, game: &Game, game_status: &mut GameStatus) { + game_status.log.push(action_to_log(action, game_status)); + // invoker: the one who invoked the action // target: the one who the action affects, may also be the invoker, e.g. draw let (invoker, target) = diff --git a/client/src/plugins/game/ui/log.rs b/client/src/plugins/game/ui/log.rs index db25584..6720d6c 100644 --- a/client/src/plugins/game/ui/log.rs +++ b/client/src/plugins/game/ui/log.rs @@ -8,7 +8,7 @@ use bevy::{prelude::*, input::mouse::{MouseScrollUnit, MouseWheel}, a11y::{AccessibilityNode, accesskit::NodeBuilder}}; -use crate::{AppState, plugins::GameData, util::action_to_log}; +use crate::{AppState, plugins::GameData, game_status::LogSection}; pub struct LogPlugin; @@ -222,7 +222,7 @@ fn update_log( let index_spaces = status.actions.len().to_string().len(); - for (i, action) in status.actions.iter().enumerate() { + for (i, _action) in status.actions.iter().enumerate() { let spaces = " ".repeat(index_spaces - i.to_string().len()); let index_text = TextSection { value: format!("{}{}. ", spaces, i), @@ -232,8 +232,28 @@ fn update_log( }, }; - let mut sections = action_to_log(action, (font.clone(), font_bold.clone()), style.clone()); - sections.insert(0, index_text); + let mut sections = vec![index_text]; + + let log = status.log.get(i).unwrap(); + for section in &log.sections { + match section { + LogSection::Normal(value) => { + sections.push(TextSection { + value: value.to_string(), + style: style.clone(), + }); + } + LogSection::Bold(value) => { + sections.push(TextSection { + value: value.to_string(), + style: TextStyle { + font: font_bold.clone(), + ..style.clone() + }, + }); + } + } + } commands.spawn(( TextBundle::from_sections(sections) diff --git a/client/src/util/action_to_log.rs b/client/src/util/action_to_log.rs index 974158c..e081b64 100644 --- a/client/src/util/action_to_log.rs +++ b/client/src/util/action_to_log.rs @@ -6,58 +6,62 @@ * See LICENSE for licensing information. */ -use bevy::prelude::*; - -use crate::api::game::{Action, Command}; - -macro_rules! section { - ($value:expr, $style:ident) => { - TextSection { - value: $value, - style: $style.clone(), - } - }; - - ($value:expr, $style:expr) => { - TextSection { - value: $value, - style: $style, - } - }; -} +use crate::{api::game::{Action, Command}, game_status::{GameStatus, LogEntry, LogSection}}; pub fn action_to_log( action: &Action, - (font, font_bold): (Handle, Handle), - style: TextStyle, -) -> Vec { + game_status: &GameStatus, +) -> LogEntry { + let invoker_name = &game_status.players.get(&action.invoker).unwrap().display_name; + match &action.command { Command::InitSupplyPile { card, amount } => { - vec![ - section!(format!("Created supply pile of "), style), - section!(format!("{}", card.name), TextStyle { - font: font_bold.clone(), - ..style.clone() - }), - section!(format!(" with "), style), - section!(format!("{}", amount), TextStyle { - font: font_bold.clone(), - ..style.clone() - }), - section!(format!(" cards."), TextStyle { - ..style.clone() - }), - ] + LogEntry::from_sections(vec![ + LogSection::normal("Created supply pile of "), + LogSection::bold(&card.name), + LogSection::normal(" with "), + LogSection::bold(&amount.to_string()), + LogSection::normal(" cards"), + ]) + } + Command::TakeFromPile { index, for_cost: _ } => { + let card_name = &game_status.supply_piles.get(*index).unwrap().card.name; + LogEntry::from_sections(vec![ + LogSection::bold(invoker_name), + LogSection::normal(" bought "), + LogSection::bold(card_name), + ]) + } + Command::PlayCard { index } => { + let card_name = &game_status.players.get(&action.invoker).unwrap().hand.get(*index).unwrap().name; + LogEntry::from_sections(vec![ + LogSection::bold(invoker_name), + LogSection::normal(" played "), + LogSection::bold(card_name), + ]) + } + Command::Draw { amount } => { + LogEntry::from_sections(vec![ + LogSection::bold(invoker_name), + LogSection::normal(" drew "), + LogSection::bold(&amount.to_string()), + LogSection::normal(" cards"), + ]) + } + Command::Discard { index } => { + let card_name = &game_status.players.get(&action.invoker).unwrap().hand.get(*index).unwrap().name; + LogEntry::from_sections(vec![ + LogSection::bold(invoker_name), + LogSection::normal(" discarded "), + LogSection::bold(card_name), + ]) } _ => { - vec![ - TextSection { - value: format!("No log configuration for this command"), - style: TextStyle { - ..style - }, - }, - ] + LogEntry { + sections: vec![ + LogSection::normal("No log configuration for this command"), + ] + } } } } -- 2.44.1