From 8f606543f56b56f108cc6e7556fe80a9ee35c1ee Mon Sep 17 00:00:00 2001 From: Tao Tien <29749622+taotien@users.noreply.github.com> Date: Sun, 8 Mar 2026 19:57:39 -0700 Subject: [PATCH] order views after player anyways --- devenv.nix | 2 +- jong/src/riichi.rs | 155 ++++++++++++++++++++++------------ jong/src/riichi/connection.rs | 2 +- jong/src/riichi/player.rs | 9 +- jong/src/tui/render.rs | 16 ++-- 5 files changed, 113 insertions(+), 71 deletions(-) diff --git a/devenv.nix b/devenv.nix index 782205c..3e83f98 100644 --- a/devenv.nix +++ b/devenv.nix @@ -45,7 +45,7 @@ ]; env.LD_LIBRARY_PATH = lib.makeLibraryPath packages; env.RUST_LOG = "jong=trace"; - env.RUST_BACKTRACE = "full"; + # env.RUST_BACKTRACE = "full"; # https://devenv.sh/languages/ languages.rust = { diff --git a/jong/src/riichi.rs b/jong/src/riichi.rs index 7da69e4..c255b43 100644 --- a/jong/src/riichi.rs +++ b/jong/src/riichi.rs @@ -5,9 +5,9 @@ use bevy::render::render_resource::AsBindGroupShaderType; use bevy_spacetimedb::{ReadInsertMessage, ReadInsertUpdateMessage, ReadUpdateMessage, StdbPlugin}; use jong_db::{ - self, PlayerClockTableAccess, PlayerConfigTableAccess, UserTableAccess, add_bot, advance_game, - join_or_create_lobby, lobbyQueryTableAccess, player_configQueryTableAccess, set_ready, - userQueryTableAccess, + self, HandView, PlayerClockTableAccess, PlayerConfigTableAccess, UserTableAccess, add_bot, + advance_game, join_or_create_lobby, lobbyQueryTableAccess, player_configQueryTableAccess, + set_ready, userQueryTableAccess, }; use jong_db::{ BotTableAccess, DbConnection, LobbyTableAccess, PlayerHand, RemoteTables, @@ -61,7 +61,13 @@ impl Plugin for Riichi { ) .add_systems( Update, - (on_view_hand_insert, on_view_hand_update) + ( + on_view_hand_insert, + on_view_hand_update, + // on_view_closed_insert, + // on_view_closed_update, + ) + .after(on_player_config_insert_update) .run_if(in_state(GameState::Play).or(in_state(GameState::Deal))), ); } @@ -165,13 +171,16 @@ fn on_player_config_insert_update( players: Query<(Entity, &Player)>, ) { for msg in messages.read() { - trace!("on_player_insert_update"); + trace!("on_player_config_insert_update"); let player = &msg.new; let player_ent = players .iter() .find_map(|(e, p)| (p.id == player.id).then_some(e)) - .unwrap_or_else(|| commands.spawn(Player { id: player.id }).id()); + .unwrap_or_else(|| { + trace!("spawn_player"); + commands.spawn(Player { id: player.id }).id() + }); if player.id == stdb @@ -191,6 +200,7 @@ fn on_player_config_insert_update( fn on_view_hand_insert( mut messages: ReadInsertMessage, mut commands: Commands, + players: Populated<(Entity, &Player, Option<&Children>)>, tiles: Query<(Entity, &TileId)>, hands: Query<(Entity, &Hand)>, ponds: Query<(Entity, &Pond)>, @@ -200,6 +210,7 @@ fn on_view_hand_insert( trace!("on_view_hand_insert"); sync_open_hand( &mut commands, + &players, tiles, hands, ponds, @@ -212,6 +223,7 @@ fn on_view_hand_insert( fn on_view_hand_update( mut messages: ReadUpdateMessage, mut commands: Commands, + players: Populated<(Entity, &Player, Option<&Children>)>, tiles: Query<(Entity, &TileId)>, hands: Query<(Entity, &Hand)>, ponds: Query<(Entity, &Pond)>, @@ -221,6 +233,7 @@ fn on_view_hand_update( trace!("on_view_hand_update"); sync_open_hand( &mut commands, + &players, tiles, hands, ponds, @@ -232,6 +245,7 @@ fn on_view_hand_update( fn sync_open_hand( commands: &mut Commands, + players: &Populated<(Entity, &Player, Option<&Children>)>, tiles: Query<(Entity, &TileId)>, hands: Query<(Entity, &Hand)>, ponds: Query<(Entity, &Pond)>, @@ -239,14 +253,28 @@ fn sync_open_hand( player_hand: &PlayerHand, ) { let player_id = player_hand.player_id; + + let (player_ent, player_children) = players + .iter() + .find_map(|(e, p, c)| (p.id == player_id).then_some((e, c))) + .unwrap(); + let hand_ent = hands .iter() - .find_map(|(e, h)| (h.player_id == player_id).then_some(e)) - .unwrap_or_else(|| commands.spawn(Hand { player_id }).id()); + .find_map(|(e, _)| player_children.is_some_and(|c| c.contains(&e)).then_some(e)) + .unwrap_or_else(|| { + let id = commands.spawn(Hand).id(); + commands.entity(player_ent).add_child(id); + id + }); let pond_ent = ponds .iter() - .find_map(|(e, p)| (p.player_id == player_id).then_some(e)) - .unwrap_or_else(|| commands.spawn(Pond { player_id }).id()); + .find_map(|(e, _)| player_children.is_some_and(|c| c.contains(&e)).then_some(e)) + .unwrap_or_else(|| { + let id = commands.spawn(Pond).id(); + commands.entity(player_ent).add_child(id); + id + }); // hand and pond both still need ability to spawn for the reconnect case let hand: Vec = player_hand @@ -276,60 +304,77 @@ fn sync_open_hand( if let Some(dbt) = &player_hand.working_tile && player_hand.turn_state == jong_db::TurnState::Tsumo { - commands.spawn((Drawn, Tile::from(&dbt.tile), TileId(dbt.id))); + let id = commands + .spawn((Drawn, Tile::from(&dbt.tile), TileId(dbt.id))) + .id(); + commands.entity(player_ent).add_child(id); + } else { + // TODO clear Drawn from auto-discarded tile } next_turnstate.set(player_hand.turn_state.into()); } -// fn sync_closed_hand( -// stdb: SpacetimeDB, - -// mut messages: MessageReader, +// fn on_view_closed_insert( +// mut messages: ReadInsertMessage, // mut commands: Commands, - // tiles: Query<(Entity, &TileId)>, -// hands: Query<(Entity, &mut Closed, &Hand)>, +// hands: Query<(Entity, &Hand)>, // ponds: Query<(Entity, &Pond)>, // ) { -// for SyncClosedHand(id) in messages.read() { -// let Some(hand_view) = stdb -// .db() -// .view_closed_hands() -// .iter() -// .find(|hand| PlayerOrBot::from(&hand.player) == *id) -// else { -// todo!() -// }; - -// let hand_ent = hands -// .iter() -// .find_map(|(e, c, h)| (h.owner == *id).then_some(e)) -// .unwrap_or_else(|| commands.spawn(Hand { owner: *id }).id()); -// let pond_ent = ponds -// .iter() -// .find_map(|(e, p)| (p.owner == *id).then_some(e)) -// .unwrap_or_else(|| commands.spawn(Pond { owner: *id }).id()); - -// let pond: Vec = hand_view -// .pond -// .iter() -// .map(|dbt| { -// tiles -// .iter() -// .find_map(|(e, i)| (i.0 == dbt.id).then_some(e)) -// .unwrap_or_else(|| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id()) -// }) -// .collect(); - -// commands.entity(hand_ent).insert(Closed { -// length: hand_view.hand_length, -// }); -// commands.entity(pond_ent).replace_children(&pond); - -// if hand_view.drawn { -// commands.spawn(Drawn); -// } +// for msg in messages.read() { +// sync_closed_hand(&mut commands, tiles, hands, ponds, &msg.row); // } // } +// fn on_view_closed_update( +// mut messages: ReadUpdateMessage, +// mut commands: Commands, +// tiles: Query<(Entity, &TileId)>, +// hands: Query<(Entity, &Hand)>, +// ponds: Query<(Entity, &Pond)>, +// ) { +// for msg in messages.read() { +// sync_closed_hand(&mut commands, tiles, hands, ponds, &msg.new); +// } +// } + +// fn sync_closed_hand( +// commands: &mut Commands, +// tiles: Query<(Entity, &TileId)>, +// hands: Query<(Entity, &Hand)>, +// ponds: Query<(Entity, &Pond)>, +// hand_view: &HandView, +// ) { +// let player_id = hand_view.player_id; +// let hand_ent = hands +// .iter() +// .find_map(|(e, h)| (h.player_id == player_id).then_some(e)) +// .unwrap_or_else(|| commands.spawn(Hand { player_id }).id()); +// let pond_ent = ponds +// .iter() +// .find_map(|(e, p)| (p.player_id == player_id).then_some(e)) +// .unwrap_or_else(|| commands.spawn(Pond { player_id }).id()); + +// let pond: Vec = hand_view +// .pond +// .iter() +// .map(|dbt| { +// tiles +// .iter() +// .find_map(|(e, i)| (i.0 == dbt.id).then_some(e)) +// .unwrap_or_else(|| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id()) +// }) +// .collect(); + +// commands.entity(hand_ent).insert(Closed { +// length: hand_view.hand_length, +// }); +// commands.entity(pond_ent).replace_children(&pond); + +// if hand_view.drawn { +// commands.spawn(Drawn); +// } else { +// // TODO clear Drawn from auto-discarded tile +// } +// } diff --git a/jong/src/riichi/connection.rs b/jong/src/riichi/connection.rs index b869105..f33d96f 100644 --- a/jong/src/riichi/connection.rs +++ b/jong/src/riichi/connection.rs @@ -8,7 +8,7 @@ pub(crate) fn on_connect(stdb: SpacetimeDB, mut messages: ReadStdbConnectedMessa for msg in messages.read() { info!("you're now jongline"); - debug!("with identity: {}", stdb.identity()); + // debug!("with identity: {}", stdb.identity()); creds_store() .save(&msg.access_token) .expect("i/o error saving token"); diff --git a/jong/src/riichi/player.rs b/jong/src/riichi/player.rs index bb90d87..a489ad6 100644 --- a/jong/src/riichi/player.rs +++ b/jong/src/riichi/player.rs @@ -22,20 +22,15 @@ pub struct LeftLord; pub struct TileId(pub u32); #[derive(Component)] -pub struct Hand { - pub player_id: u32, -} +pub struct Hand; #[derive(Component)] pub struct Closed { - pub player_id: u32, pub(crate) length: u8, } #[derive(Component)] -pub struct Pond { - pub player_id: u32, -} +pub struct Pond; #[derive(Component)] pub struct Drawn; diff --git a/jong/src/tui/render.rs b/jong/src/tui/render.rs index 2d40ff6..d8a48f7 100644 --- a/jong/src/tui/render.rs +++ b/jong/src/tui/render.rs @@ -150,9 +150,9 @@ pub(crate) fn render_main_hand( tiles: Query<&jong_types::Tile>, hovered: Query>, - main_player: Single<&Player, With>, + main_player: Single<(&Player, &Children), With>, - hands: Query<(&Hand, &Children)>, + hands: Query<(Entity, &Hand, &Children)>, drawn_tile: Option>>, ) -> Result { let mut frame = tui.get_frame(); @@ -164,7 +164,7 @@ pub(crate) fn render_main_hand( let hand: Vec<_> = hands .iter() - .find_map(|(h, c)| (main_player.id == h.player_id).then_some(c)) + .find_map(|(e, h, c)| (main_player.1.contains(&e)).then_some(c)) .unwrap() .iter() .map(|entity| -> Result<_> { @@ -217,7 +217,9 @@ pub(crate) fn render_main_hand( } // tsumo tile - if let Some(drawn_tile) = drawn_tile { + if let Some(drawn_tile) = drawn_tile + && main_player.1.contains(&*drawn_tile) + { let mut area = drawn_area.resize(Size { width: 5, height: 4, @@ -259,9 +261,9 @@ pub(crate) fn render_main_pond( tiles: Query<&Tile>, hovered: Query>, - main_player: Single<&Player, With>, + main_player: Single<(&Player, &Children), With>, - pond: Query<(&Pond, &Children)>, + pond: Query<(Entity, &Pond, &Children)>, ) -> Result { let mut frame = tui.get_frame(); @@ -271,7 +273,7 @@ pub(crate) fn render_main_pond( let pond: Vec<_> = pond .iter() - .find_map(|(p, c)| (main_player.id == p.player_id).then_some(c)) + .find_map(|(e, p, c)| (main_player.1.contains(&e)).then_some(c)) .unwrap() .iter() .map(|entity| -> Result<_> {