diff --git a/src/game/hand.rs b/src/game/hand.rs index 4daa915..424d9b4 100644 --- a/src/game/hand.rs +++ b/src/game/hand.rs @@ -1,6 +1,9 @@ use bevy::prelude::*; -use crate::{game::wall::WallTiles, tiles::Tile}; +use crate::{ + game::{player::Player, wall::WallTiles}, + tiles::Tile, +}; #[derive(Component)] pub struct Hand; @@ -17,38 +20,39 @@ pub(crate) fn deal_hands( mut commands: Commands, walltiles: Single<&WallTiles>, walltiles_entity: Single>, + players: Populated>, ) -> Result { - let hand = walltiles.iter().collect::>(); + let mut wall = walltiles.iter().collect::>(); - commands - .get_entity(*walltiles_entity)? - .remove_children(hand.last_chunk::<13>().unwrap()); + for player_entity in players { + let hand = wall.split_off(13); - commands.spawn((Hand, HandTiles(hand))); + commands + .get_entity(*walltiles_entity)? + .remove_children(&hand); + + let handtiles = commands.spawn((Hand, HandTiles(hand))).id(); + + commands + .get_entity(player_entity)? + .add_children(&[handtiles]); + } trace!("dealt hands"); Ok(()) } -pub(crate) fn sort_hand( +#[allow(clippy::type_complexity)] +pub(crate) fn sort_hands( mut commands: Commands, tiles: Populated<&Tile>, - handtiles_entity: Single>, - handtiles: Single<&HandTiles, Changed>, + mut hands: Populated<&mut Children, Changed>, ) -> Result { - let mut hand: Vec<_> = handtiles - .iter() - .map(|e| -> Result<(_, _)> { Ok((tiles.get(e)?, e)) }) - .collect::>()?; + for (mut children) in hands { + children.sort_unstable_by_key(|e| tiles.get(*e).unwrap().suit); + trace!("sorted a hand") + } - hand.sort_by_key(|(t, _)| t.suit); - - let hand: Vec<_> = hand.iter().map(|(_, e)| *e).collect(); - - commands - .get_entity(*handtiles_entity)? - .replace_children(&hand); - - trace!("sort_hand"); + trace!("sort_hands"); Ok(()) } diff --git a/src/game/mod.rs b/src/game/mod.rs index b099460..6b3b83f 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -1,6 +1,9 @@ use bevy::prelude::*; -use crate::tiles::{self, *}; +use crate::{ + game::player::MainPlayer, + tiles::{self, *}, +}; pub mod hand; pub mod player; @@ -24,7 +27,7 @@ impl Plugin for Riichi { .add_systems(Startup, tiles::init_tiles) .init_state::() .add_systems(OnEnter(GameState::Setup), (wall::build_wall, hand::deal_hands, setup_done).chain()) - .add_systems(Update, (hand::sort_hand).run_if(in_state(GameState::Play))) + .add_systems(Update, (hand::sort_hands).run_if(in_state(GameState::Play))) // semicolon stopper ; } @@ -79,7 +82,7 @@ pub(crate) fn init_match( player_count, }); - let players = (1..=player_count) + let players = (2..=player_count) .map(|i| { ( player::Player { @@ -90,6 +93,13 @@ pub(crate) fn init_match( }) .collect::>(); commands.spawn_batch(players); + let main_player = ( + player::Player { + name: format!("Player {}", 1), + }, + player::Points(starting), + ); + commands.spawn((main_player, MainPlayer)); // *compass = Compass { // prevalent_wind: Wind::Ton, diff --git a/src/game/player.rs b/src/game/player.rs index e4e3323..a99e5cd 100644 --- a/src/game/player.rs +++ b/src/game/player.rs @@ -6,12 +6,12 @@ use crate::{ }; #[derive(Component)] -pub(crate) struct Player { - pub(crate) name: String, +pub struct Player { + pub name: String, } -fn spawn_players(mut commands: Commands) {} +#[derive(Component)] +pub struct Points(pub isize); #[derive(Component)] -pub(crate) struct Points(pub isize); - +pub struct MainPlayer; diff --git a/src/main.rs b/src/main.rs index 0481b30..1a8dd9a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,7 +43,7 @@ fn main() { tui_logger::init_logger(tui_logger::LevelFilter::Trace).unwrap(); tui_logger::set_env_filter_from_string(FILTERSTRING); - app.add_plugins(tui::RiichiTui::default()) + app.add_plugins(tui::RiichiTui) } }; diff --git a/src/tui/console.rs b/src/tui/console.rs index 0d4ac88..efdcd7a 100644 --- a/src/tui/console.rs +++ b/src/tui/console.rs @@ -1,15 +1,12 @@ -use bevy::input::keyboard::Key; use bevy::prelude::*; use bevy_ratatui::RatatuiContext; -use bevy_ratatui::event::KeyMessage; -use ratatui::crossterm::event::KeyCode; use ratatui::widgets::Block; use tui_logger::TuiLoggerWidget; #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)] pub(crate) enum ConsoleState { - #[default] Closed, + #[default] Open, } @@ -24,22 +21,6 @@ impl std::ops::Not for ConsoleState { } } -pub(crate) fn toggle_console( - // input: Res>, - mut messages: MessageReader, - curr_state: Res>, - mut next_state: ResMut>, -) { - // if input.just_pressed(Key::Character("`".into())) { - // next_state.set(!*curr_state.get()); - // } - for message in messages.read() { - if let KeyCode::Char('`') = message.code { - next_state.set(!*curr_state.get()); - } - } -} - pub(crate) fn draw_console(mut tui_ctx: ResMut) -> Result { tui_ctx.draw(|frame| { let block = Block::bordered().title("console"); diff --git a/src/tui/menu.rs b/src/tui/menu.rs index 65da70b..3ee27e5 100644 --- a/src/tui/menu.rs +++ b/src/tui/menu.rs @@ -27,24 +27,3 @@ pub(crate) fn draw_mainmenu( } }); } - -pub(crate) fn mainmenu_input( - // input: Res>, - mut messages: MessageReader, - mut next_tuistate: ResMut>, - mut next_gamestate: ResMut>, - mut exit: MessageWriter, -) { - for message in messages.read() { - match message.code { - KeyCode::Char('p') => { - next_tuistate.set(TuiState::InGame); - next_gamestate.set(GameState::Setup); - } - KeyCode::Char('q') => { - exit.write_default(); - } - _ => {} - } - } -} diff --git a/src/tui/mod.rs b/src/tui/mod.rs index 5ccd9bf..cde1cf2 100644 --- a/src/tui/mod.rs +++ b/src/tui/mod.rs @@ -2,17 +2,20 @@ use std::time::Duration; use bevy::{app::ScheduleRunnerPlugin, prelude::*, state::app::StatesPlugin}; use bevy_ratatui::RatatuiPlugins; +use bevy_ratatui::event::KeyMessage; use ratatui::{text::ToSpan, widgets::Paragraph}; use jong::game::GameState; use jong::game::wall::InWall; +use crate::tui::console::ConsoleState; + mod console; mod menu; mod render; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, States, Default)] -enum TuiState { +pub(crate) enum TuiState { #[default] MainMenu, InGame, @@ -56,9 +59,10 @@ impl Plugin for RiichiTui { // general setup .init_state::() .add_computed_state::() + .add_systems(Update, input_system) // main menu - .add_systems(Update, (menu::draw_mainmenu, menu::mainmenu_input).run_if(in_state(TuiState::MainMenu))) + .add_systems(Update, menu::draw_mainmenu.run_if(in_state(TuiState::MainMenu))) // gaming .init_resource::() @@ -70,3 +74,55 @@ impl Plugin for RiichiTui { } } +#[allow(clippy::too_many_arguments)] +pub(crate) fn input_system( + mut messages: MessageReader, + + curr_tuistate: Res>, + curr_consolestate: Res>, + curr_gamestate: Res>, + + mut next_tuistate: ResMut>, + mut next_consolestate: ResMut>, + mut next_gamestate: ResMut>, + + mut exit: MessageWriter, +) { + use bevy_ratatui::crossterm::event::KeyCode; + + let (ts, cs, gs) = (curr_tuistate.get(), curr_consolestate.get(), curr_gamestate.get()); + + for message in messages.read() { + if let KeyCode::Char('`') = message.code { + next_consolestate.set(!*curr_consolestate.get()); + continue + } + + match ts { + TuiState::MainMenu => match message.code { + KeyCode::Char('p') => { + next_tuistate.set(TuiState::InGame); + next_gamestate.set(GameState::Setup); + } + KeyCode::Char('q') => { + exit.write_default(); + } + _ => {} + }, + TuiState::InGame => match gs { + GameState::Setup => match message.code { + _ => {} + }, + GameState::Play => match message.code { + KeyCode::Char('q') => { + exit.write_default(); + } + _ => {} + }, + GameState::Score => todo!(), + _ => unreachable!("TuiState::InGame but GameState invalid") + }, + } + } +} + diff --git a/src/tui/render/hand.rs b/src/tui/render/hand.rs index 9c76106..d2fcc69 100644 --- a/src/tui/render/hand.rs +++ b/src/tui/render/hand.rs @@ -7,32 +7,26 @@ use jong::tiles::Tile; use crate::tui::render::tiles; #[derive(Resource, Default)] -pub(crate) struct RenderedHand(pub(crate) Vec>); +pub(crate) struct RenderedHand(pub(crate) Vec>>); pub(crate) fn render_changed_hand( - hand: Single<&HandTiles, Changed>, + hands: Populated<&Children, Changed>, tiles: Populated<&Tile>, mut target: ResMut, ) -> Result { + let mut rendered = vec![]; + + for hand in hands { + let tiles = hand + .iter() + .map(|inhand| tiles.get(inhand).map(tiles::draw_tile).unwrap()) + .collect(); + + rendered.push(tiles); + } + + target.0 = rendered; + trace!("render_changed_hand"); - - render_hand(hand, tiles, target)?; - - Ok(()) -} - -pub(crate) fn render_hand( - hand: Single<&HandTiles, Changed>, - tiles: Populated<&Tile>, - mut target: ResMut, -) -> Result { - trace!("render_hand"); - - let hand_tiles = hand - .iter() - .map(|inhand| -> Result<_> { Ok(tiles.get(inhand).map(tiles::draw_tile)?) }) - .collect::>>()?; - target.0 = hand_tiles; - Ok(()) } diff --git a/src/tui/render/ingame.rs b/src/tui/render/ingame.rs index 3d407f8..b8e01cc 100644 --- a/src/tui/render/ingame.rs +++ b/src/tui/render/ingame.rs @@ -11,14 +11,16 @@ pub(crate) fn draw_ingame( use ratatui::prelude::*; tui_ctx.draw(|frame| { - debug!("{}", frame.area()); + // debug!("{}", frame.area()); let layout = Layout::horizontal(vec![Constraint::Max(5); 13]).flex(Flex::Start); let mut area = frame.area(); area.height = 4; let areas = layout.areas::<13>(area); - for (tile, area) in rendered_hand.0.iter().zip(areas.iter()) { - frame.render_widget(tile, *area); + if let Some(tiles) = rendered_hand.0.first() { + for (tile, area) in tiles.iter().zip(areas.iter()) { + frame.render_widget(tile, *area); + } } })?;