diff --git a/Cargo.toml b/Cargo.toml index fa94c80..8ba3c20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,9 +25,6 @@ tracing = "0.1.44" tracing-subscriber = "0.3.22" tui-logger = { version = "0.18.0", features = ["tracing-support", "crossterm"] } -[dev-dependencies] -bevy = { version = "0.17.3", features = ["track_location"] } - [profile.dev] opt-level = 1 diff --git a/src/game.rs b/src/game.rs index 4626473..09b4e82 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,10 +1,10 @@ -use bevy::{ecs::query::QueryData, prelude::*}; +use bevy::prelude::*; use crate::{ game::{ hand::Hand, - player::MainPlayer, - round::{CurrentPlayer, TurnState, Wind}, + player::{CurrentPlayer, MainPlayer}, + round::{TurnState, Wind}, wall::Wall, }, tile::{self}, @@ -60,7 +60,6 @@ pub(crate) fn setup( matchsettings: Res, // mut compass: ResMut // tiles: Query>, - curr_gamestate: Res>, mut next_gamestate: ResMut>, ) { for i in 1..=matchsettings.player_count { @@ -77,8 +76,8 @@ pub(crate) fn setup( ); if i == 1 { - let player = commands.spawn((bundle, MainPlayer)).id(); - commands.insert_resource(CurrentPlayer(player)); + let player = commands.spawn((bundle, MainPlayer, CurrentPlayer)).id(); + // commands.insert_resource(CurrentPlayer(player)); } else { commands.spawn(bundle); } diff --git a/src/game/hand.rs b/src/game/hand.rs index 67f9108..1ccef15 100644 --- a/src/game/hand.rs +++ b/src/game/hand.rs @@ -10,11 +10,11 @@ use crate::{ #[derive(Component)] pub struct Hand; -#[derive(Component, Debug)] -pub struct DrawnTile(pub Entity); +#[derive(Component)] +pub struct Drawn; #[derive(Component)] -pub struct DiscardedTile(pub Entity); +pub struct Discarded; // #[derive(Component, Default)] // enum SortHand { @@ -48,19 +48,16 @@ pub(crate) fn shuffle_deal( let mut walltiles: Vec<_> = tiles.iter().collect(); walltiles.shuffle(&mut rng); - // commands.get_entity(*wall_ent)?.replace_children(&walltiles); - for player_ent in players { - debug!("deal to player_ent {player_ent:?}"); let handtiles = walltiles.split_off(walltiles.len() - 13); - // commands.get_entity(*wall_ent)?.remove_children(&handtiles); - let hand_ent = commands.spawn(Hand).add_children(&handtiles).id(); - debug!("hand_ent: {hand_ent:?}"); - - commands.entity(player_ent).replace_children(&[hand_ent]); + commands.entity(player_ent).add_child(hand_ent); + debug!("deal to player_ent {player_ent:?} {hand_ent:?}"); } + // don't need to remove hands from wall if we don't insert to wall to begin with + // TODO probably do this later on when animating the draw + debug!("shuffled: {walltiles:?}"); commands.entity(*wall_ent).replace_children(&walltiles); next_gamestate.set(GameState::Play); diff --git a/src/game/player.rs b/src/game/player.rs index d241ba6..32a531f 100644 --- a/src/game/player.rs +++ b/src/game/player.rs @@ -11,8 +11,11 @@ pub struct Points(pub isize); #[derive(Component)] pub struct MainPlayer; +#[derive(Component)] +pub struct CurrentPlayer; + #[derive(Component)] pub struct Dealer; #[derive(Component)] -pub struct Tsumo(pub Entity); +pub struct Tsumo; diff --git a/src/game/round.rs b/src/game/round.rs index ec284eb..b33bb53 100644 --- a/src/game/round.rs +++ b/src/game/round.rs @@ -5,14 +5,14 @@ use crate::{ EnumNextCycle, game::{ GameMessage, GameState, - hand::{DiscardedTile, DrawnTile, Hand}, - player::Player, + hand::{Discarded, Drawn, Hand}, + player::{CurrentPlayer, Player}, wall::Wall, }, }; -#[derive(Resource)] -pub struct CurrentPlayer(pub Entity); +// #[derive(Resource)] +// pub struct CurrentPlayer(pub Entity); #[derive(Resource)] pub(crate) struct MatchSettings { @@ -58,9 +58,6 @@ pub(crate) enum TurnState { End, } -#[derive(EntityEvent)] -pub struct Discard(pub Entity); - impl Default for MatchSettings { fn default() -> Self { Self { @@ -116,22 +113,22 @@ impl EnumNextCycle for TurnState { pub(crate) fn tsumo( mut commands: Commands, - curr_player: Res, - // players: Populated>, - wall_ent: Single>, + + // curr_player: Res, + curr_player: Single>, + wall: Single>, walltiles: Single<&Children, With>, + curr_turnstate: Res>, mut next_turnstate: ResMut>, ) { - debug!("tsumo for: {:?}", curr_player.0); - let drawn = walltiles.last().unwrap(); - commands.entity(*wall_ent).remove_child(*drawn); - let drawn_ent = commands.spawn(DrawnTile(*drawn)).id(); - commands.entity(curr_player.0).add_child(drawn_ent); + commands.entity(*wall).remove_child(*drawn); - debug!("drew: ent: {drawn_ent:?} tile_ent: {:?}", drawn); + let drawn = commands.entity(*drawn).insert(Drawn).id(); + commands.entity(*curr_player).add_child(drawn); + debug!("tsumo for: {:?}, tile: {:?}", *curr_player, drawn); next_turnstate.set(curr_turnstate.next()); } @@ -156,39 +153,43 @@ pub(crate) fn discard( mut commands: Commands, mut reader: MessageReader, - currplayer: Res, - drawntile: Single<(&DrawnTile, Entity), With>, - player_hands: Populated<(&Player, &Children), With>, - hands: Populated<&Children, (With, Without)>, + curr_player: Single>, + players: Query<&Children, With>, + mut hands: Query<(&Children, Entity), (With, Without)>, + drawn: Single>, curr_turnstate: Res>, mut next_turnstate: ResMut>, -) { - let curr = currplayer.0; - let hand = player_hands.get(curr).unwrap().1.iter().next().unwrap(); - let handtiles = hands.get(hand).unwrap(); - let (drawntile, drawn_ent) = *drawntile; - - // debug!("discard turn for: {curr:?}"); +) -> Result { + // trace!("discard"); + let curr_hand = hands.get_mut(players.get(*curr_player)?.iter().next().unwrap())?; + let mut done = false; while let Some(message) = reader.read().next() { - if let GameMessage::Discarded(entity) = message { - debug!("{curr:?} discarded: {entity:?}"); - // commands.entity(drawn_ent).despawn(); - if *entity == drawntile.0 { - } else if handtiles.contains(entity) { + if let GameMessage::Discarded(discarded) = message { + if *discarded == *drawn { + } else if curr_hand.0.contains(discarded) { commands - .entity(hand) - .remove_child(*entity) - .add_child(drawntile.0); + .entity(curr_hand.1) + .remove_child(*discarded) + .add_child(*drawn); } else { - panic!("discarded illegal player tile?") + panic!("current hand nor drawn tile contains discarded tile") } - commands.spawn(DiscardedTile(*entity)); - next_turnstate.set(curr_turnstate.next()); + commands + .entity(*discarded) + .remove::() + .insert(Discarded); + + done = true; break; } } + + if done { + next_turnstate.set(curr_turnstate.next()); + } + Ok(()) } pub(crate) fn ron_chi_pon_kan( diff --git a/src/tui.rs b/src/tui.rs index d6b6c22..1244401 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -1,13 +1,13 @@ use std::time::Duration; -use bevy::{app::ScheduleRunnerPlugin, prelude::*, state::app::StatesPlugin}; +use bevy::{app::ScheduleRunnerPlugin, prelude::*, state::app::StatesPlugin, time::TimePlugin}; use bevy_ratatui::RatatuiPlugins; use jong::game::{ GameMessage, GameState, - hand::{DrawnTile, Hand}, - player::{MainPlayer, Player}, - round::{CurrentPlayer, Discard}, + hand::{Drawn, Hand}, + player::{CurrentPlayer, Player}, }; +use tracing::instrument; use tui_logger::TuiWidgetState; use crate::tui::{input::ConfirmSelect, states::ConsoleWidget}; @@ -72,17 +72,25 @@ impl Plugin for TuiPlugin { fn discard_tile( mut writer: MessageWriter, mut selected: MessageReader, - drawntile: Single>, - currplayer: Res, + + drawn: Single>, + curr_player: Single>, player_hands: Populated<(&Player, &Children), With>, hands: Populated<&Children, (With, Without)>, ) { - let curr = currplayer.0; - let hand_ent = player_hands.get(curr).unwrap().1.iter().next().unwrap(); + // trace!("discard_tile"); + + let hand_ent = player_hands + .get(*curr_player) + .unwrap() + .1 + .iter() + .next() + .unwrap(); let hand = hands.get(hand_ent).unwrap(); while let Some(message) = selected.read().next() - && (message.0 == *drawntile || hand.contains(&message.0)) + && (message.0 == *drawn || hand.contains(&message.0)) { writer.write(GameMessage::Discarded(message.0)); } diff --git a/src/tui/input.rs b/src/tui/input.rs index 317e04e..9ef831d 100644 --- a/src/tui/input.rs +++ b/src/tui/input.rs @@ -12,5 +12,5 @@ pub(crate) struct Hovered; #[derive(Component)] pub(crate) struct StartSelect; -#[derive(Message)] +#[derive(Message, Debug)] pub(crate) struct ConfirmSelect(pub(crate) Entity); diff --git a/src/tui/render.rs b/src/tui/render.rs index 734920c..5c63bba 100644 --- a/src/tui/render.rs +++ b/src/tui/render.rs @@ -1,15 +1,13 @@ use std::io::Write as _; -use std::ops::Sub; -use bevy::platform::collections::HashSet; use bevy::prelude::*; use bevy_ratatui::RatatuiContext; use ratatui::layout::{Constraint, Flex, Layout, Offset, Rect, Size}; -use ratatui::style::{Modifier, Style, Stylize}; +use ratatui::style::{Modifier, Stylize}; use ratatui::widgets::{Block, Borders, Clear, Paragraph}; -use jong::game::hand::{DrawnTile, Hand}; -use jong::game::player::{MainPlayer, Player}; +use jong::game::hand::{Drawn, Hand}; +use jong::game::player::{CurrentPlayer, MainPlayer, Player}; use jong::game::round::Wind; use jong::tile::Tile; @@ -22,7 +20,7 @@ pub(crate) struct PickRegion { pub(crate) area: Rect, } -fn render_tile(tile: &Tile, hovered: bool) -> (Paragraph<'_>) { +fn render_tile(tile: &Tile, hovered: bool) -> Paragraph<'_> { let block = ratatui::widgets::Block::bordered(); let mut widget = Paragraph::new(match &tile.suit { jong::tile::Suit::Pin(rank) => format!("{}\np", rank.0), @@ -99,32 +97,35 @@ pub(crate) fn render( pub(crate) fn render_hands( mut commands: Commands, mut tui: ResMut, + hovered: Query>, layouts: Res, - mainplayer: Single<(&Player, &Wind), With>, - players: Populated<(&Player, /* &Wind, */ &Children)>, - hands: Populated<&Children, (With, Without)>, - tiles: Populated<&Tile>, - drawn_tile: Option>, + + tiles: Query<&Tile>, + main_player: Single<(&Player, &Wind), With>, + curr_player: Single>, + players: Query<(&Player, &Children)>, + hands: Query<(&Children, Entity), (With, Without)>, + drawn_tile: Option>>, ) -> Result { let mut frame = tui.get_frame(); debug_blocks(*layouts, &mut frame); - for (player, /* wind, */ hand_ent) in players { - let hand = hand_ent.iter().next().unwrap(); - let hand: Vec<_> = hands - .get(hand)? + for (hand, hand_ent) in hands { + // debug!("{hand:?}"); + let (player, _) = players.iter().find(|(_, c)| c.contains(&hand_ent)).unwrap(); + let hand: Vec<_> = hand .iter() .map(|entity| -> Result<_> { - let tile = tiles.get(entity)?; - // let paragraph = render_tile(tile,); + let tile = tiles.get(entity).unwrap_or_else(|_| panic!("{entity:?}")); let hovered = hovered.contains(entity); let widget = render_tile(tile, hovered); + Ok((entity, widget, hovered)) }) .collect::>()?; - if player == mainplayer.0 { + if player == main_player.0 { // split main box into thirds let mut this_hand = layouts.this_hand; let this_drawer = drawn_tile.as_ref().is_some_and(|dt| dt.0 == player); @@ -169,14 +170,14 @@ pub(crate) fn render_hands( // tsumo tile if this_drawer { - let (_, tile, entity) = **drawn_tile.as_ref().unwrap(); + let (_, entity) = **drawn_tile.as_ref().unwrap(); let mut area = drawn_area.resize(Size { width: 5, height: 4, }); area = area.offset(Offset { x: 2, y: 0 }); let hovered = hovered.contains(entity); - let widget = render_tile(tiles.get(tile.0)?, hovered); + let widget = render_tile(tiles.get(entity)?, hovered); if hovered { area = area.offset(Offset { x: 0, y: -1 }); let mut hitbox = area.as_size();