order views after player anyways

This commit is contained in:
Tao Tien 2026-03-08 19:57:39 -07:00
parent 3457e0d024
commit 8f606543f5
5 changed files with 113 additions and 71 deletions

View file

@ -45,7 +45,7 @@
]; ];
env.LD_LIBRARY_PATH = lib.makeLibraryPath packages; env.LD_LIBRARY_PATH = lib.makeLibraryPath packages;
env.RUST_LOG = "jong=trace"; env.RUST_LOG = "jong=trace";
env.RUST_BACKTRACE = "full"; # env.RUST_BACKTRACE = "full";
# https://devenv.sh/languages/ # https://devenv.sh/languages/
languages.rust = { languages.rust = {

View file

@ -5,9 +5,9 @@ use bevy::render::render_resource::AsBindGroupShaderType;
use bevy_spacetimedb::{ReadInsertMessage, ReadInsertUpdateMessage, ReadUpdateMessage, StdbPlugin}; use bevy_spacetimedb::{ReadInsertMessage, ReadInsertUpdateMessage, ReadUpdateMessage, StdbPlugin};
use jong_db::{ use jong_db::{
self, PlayerClockTableAccess, PlayerConfigTableAccess, UserTableAccess, add_bot, advance_game, self, HandView, PlayerClockTableAccess, PlayerConfigTableAccess, UserTableAccess, add_bot,
join_or_create_lobby, lobbyQueryTableAccess, player_configQueryTableAccess, set_ready, advance_game, join_or_create_lobby, lobbyQueryTableAccess, player_configQueryTableAccess,
userQueryTableAccess, set_ready, userQueryTableAccess,
}; };
use jong_db::{ use jong_db::{
BotTableAccess, DbConnection, LobbyTableAccess, PlayerHand, RemoteTables, BotTableAccess, DbConnection, LobbyTableAccess, PlayerHand, RemoteTables,
@ -61,7 +61,13 @@ impl Plugin for Riichi {
) )
.add_systems( .add_systems(
Update, 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))), .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)>, players: Query<(Entity, &Player)>,
) { ) {
for msg in messages.read() { for msg in messages.read() {
trace!("on_player_insert_update"); trace!("on_player_config_insert_update");
let player = &msg.new; let player = &msg.new;
let player_ent = players let player_ent = players
.iter() .iter()
.find_map(|(e, p)| (p.id == player.id).then_some(e)) .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 if player.id
== stdb == stdb
@ -191,6 +200,7 @@ fn on_player_config_insert_update(
fn on_view_hand_insert( fn on_view_hand_insert(
mut messages: ReadInsertMessage<jong_db::PlayerHand>, mut messages: ReadInsertMessage<jong_db::PlayerHand>,
mut commands: Commands, mut commands: Commands,
players: Populated<(Entity, &Player, Option<&Children>)>,
tiles: Query<(Entity, &TileId)>, tiles: Query<(Entity, &TileId)>,
hands: Query<(Entity, &Hand)>, hands: Query<(Entity, &Hand)>,
ponds: Query<(Entity, &Pond)>, ponds: Query<(Entity, &Pond)>,
@ -200,6 +210,7 @@ fn on_view_hand_insert(
trace!("on_view_hand_insert"); trace!("on_view_hand_insert");
sync_open_hand( sync_open_hand(
&mut commands, &mut commands,
&players,
tiles, tiles,
hands, hands,
ponds, ponds,
@ -212,6 +223,7 @@ fn on_view_hand_insert(
fn on_view_hand_update( fn on_view_hand_update(
mut messages: ReadUpdateMessage<jong_db::PlayerHand>, mut messages: ReadUpdateMessage<jong_db::PlayerHand>,
mut commands: Commands, mut commands: Commands,
players: Populated<(Entity, &Player, Option<&Children>)>,
tiles: Query<(Entity, &TileId)>, tiles: Query<(Entity, &TileId)>,
hands: Query<(Entity, &Hand)>, hands: Query<(Entity, &Hand)>,
ponds: Query<(Entity, &Pond)>, ponds: Query<(Entity, &Pond)>,
@ -221,6 +233,7 @@ fn on_view_hand_update(
trace!("on_view_hand_update"); trace!("on_view_hand_update");
sync_open_hand( sync_open_hand(
&mut commands, &mut commands,
&players,
tiles, tiles,
hands, hands,
ponds, ponds,
@ -232,6 +245,7 @@ fn on_view_hand_update(
fn sync_open_hand( fn sync_open_hand(
commands: &mut Commands, commands: &mut Commands,
players: &Populated<(Entity, &Player, Option<&Children>)>,
tiles: Query<(Entity, &TileId)>, tiles: Query<(Entity, &TileId)>,
hands: Query<(Entity, &Hand)>, hands: Query<(Entity, &Hand)>,
ponds: Query<(Entity, &Pond)>, ponds: Query<(Entity, &Pond)>,
@ -239,14 +253,28 @@ fn sync_open_hand(
player_hand: &PlayerHand, player_hand: &PlayerHand,
) { ) {
let player_id = player_hand.player_id; 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 let hand_ent = hands
.iter() .iter()
.find_map(|(e, h)| (h.player_id == player_id).then_some(e)) .find_map(|(e, _)| player_children.is_some_and(|c| c.contains(&e)).then_some(e))
.unwrap_or_else(|| commands.spawn(Hand { player_id }).id()); .unwrap_or_else(|| {
let id = commands.spawn(Hand).id();
commands.entity(player_ent).add_child(id);
id
});
let pond_ent = ponds let pond_ent = ponds
.iter() .iter()
.find_map(|(e, p)| (p.player_id == player_id).then_some(e)) .find_map(|(e, _)| player_children.is_some_and(|c| c.contains(&e)).then_some(e))
.unwrap_or_else(|| commands.spawn(Pond { player_id }).id()); .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 // hand and pond both still need ability to spawn for the reconnect case
let hand: Vec<Entity> = player_hand let hand: Vec<Entity> = player_hand
@ -276,40 +304,57 @@ fn sync_open_hand(
if let Some(dbt) = &player_hand.working_tile if let Some(dbt) = &player_hand.working_tile
&& player_hand.turn_state == jong_db::TurnState::Tsumo && 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()); next_turnstate.set(player_hand.turn_state.into());
} }
// fn sync_closed_hand( // fn on_view_closed_insert(
// stdb: SpacetimeDB, // mut messages: ReadInsertMessage<jong_db::HandView>,
// mut messages: MessageReader<SyncClosedHand>,
// mut commands: Commands, // mut commands: Commands,
// tiles: Query<(Entity, &TileId)>, // tiles: Query<(Entity, &TileId)>,
// hands: Query<(Entity, &mut Closed, &Hand)>, // hands: Query<(Entity, &Hand)>,
// ponds: Query<(Entity, &Pond)>, // ponds: Query<(Entity, &Pond)>,
// ) { // ) {
// for SyncClosedHand(id) in messages.read() { // for msg in messages.read() {
// let Some(hand_view) = stdb // sync_closed_hand(&mut commands, tiles, hands, ponds, &msg.row);
// .db() // }
// .view_closed_hands() // }
// .iter()
// .find(|hand| PlayerOrBot::from(&hand.player) == *id)
// else {
// todo!()
// };
// fn on_view_closed_update(
// mut messages: ReadUpdateMessage<jong_db::HandView>,
// 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 // let hand_ent = hands
// .iter() // .iter()
// .find_map(|(e, c, h)| (h.owner == *id).then_some(e)) // .find_map(|(e, h)| (h.player_id == player_id).then_some(e))
// .unwrap_or_else(|| commands.spawn(Hand { owner: *id }).id()); // .unwrap_or_else(|| commands.spawn(Hand { player_id }).id());
// let pond_ent = ponds // let pond_ent = ponds
// .iter() // .iter()
// .find_map(|(e, p)| (p.owner == *id).then_some(e)) // .find_map(|(e, p)| (p.player_id == player_id).then_some(e))
// .unwrap_or_else(|| commands.spawn(Pond { owner: *id }).id()); // .unwrap_or_else(|| commands.spawn(Pond { player_id }).id());
// let pond: Vec<Entity> = hand_view // let pond: Vec<Entity> = hand_view
// .pond // .pond
@ -329,7 +374,7 @@ fn sync_open_hand(
// if hand_view.drawn { // if hand_view.drawn {
// commands.spawn(Drawn); // commands.spawn(Drawn);
// } else {
// // TODO clear Drawn from auto-discarded tile
// } // }
// } // }
// }

View file

@ -8,7 +8,7 @@ pub(crate) fn on_connect(stdb: SpacetimeDB, mut messages: ReadStdbConnectedMessa
for msg in messages.read() { for msg in messages.read() {
info!("you're now jongline"); info!("you're now jongline");
debug!("with identity: {}", stdb.identity()); // debug!("with identity: {}", stdb.identity());
creds_store() creds_store()
.save(&msg.access_token) .save(&msg.access_token)
.expect("i/o error saving token"); .expect("i/o error saving token");

View file

@ -22,20 +22,15 @@ pub struct LeftLord;
pub struct TileId(pub u32); pub struct TileId(pub u32);
#[derive(Component)] #[derive(Component)]
pub struct Hand { pub struct Hand;
pub player_id: u32,
}
#[derive(Component)] #[derive(Component)]
pub struct Closed { pub struct Closed {
pub player_id: u32,
pub(crate) length: u8, pub(crate) length: u8,
} }
#[derive(Component)] #[derive(Component)]
pub struct Pond { pub struct Pond;
pub player_id: u32,
}
#[derive(Component)] #[derive(Component)]
pub struct Drawn; pub struct Drawn;

View file

@ -150,9 +150,9 @@ pub(crate) fn render_main_hand(
tiles: Query<&jong_types::Tile>, tiles: Query<&jong_types::Tile>,
hovered: Query<Entity, With<Hovered>>, hovered: Query<Entity, With<Hovered>>,
main_player: Single<&Player, With<MainPlayer>>, main_player: Single<(&Player, &Children), With<MainPlayer>>,
hands: Query<(&Hand, &Children)>, hands: Query<(Entity, &Hand, &Children)>,
drawn_tile: Option<Single<Entity, With<Drawn>>>, drawn_tile: Option<Single<Entity, With<Drawn>>>,
) -> Result { ) -> Result {
let mut frame = tui.get_frame(); let mut frame = tui.get_frame();
@ -164,7 +164,7 @@ pub(crate) fn render_main_hand(
let hand: Vec<_> = hands let hand: Vec<_> = hands
.iter() .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() .unwrap()
.iter() .iter()
.map(|entity| -> Result<_> { .map(|entity| -> Result<_> {
@ -217,7 +217,9 @@ pub(crate) fn render_main_hand(
} }
// tsumo tile // 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 { let mut area = drawn_area.resize(Size {
width: 5, width: 5,
height: 4, height: 4,
@ -259,9 +261,9 @@ pub(crate) fn render_main_pond(
tiles: Query<&Tile>, tiles: Query<&Tile>,
hovered: Query<Entity, With<Hovered>>, hovered: Query<Entity, With<Hovered>>,
main_player: Single<&Player, With<MainPlayer>>, main_player: Single<(&Player, &Children), With<MainPlayer>>,
pond: Query<(&Pond, &Children)>, pond: Query<(Entity, &Pond, &Children)>,
) -> Result { ) -> Result {
let mut frame = tui.get_frame(); let mut frame = tui.get_frame();
@ -271,7 +273,7 @@ pub(crate) fn render_main_pond(
let pond: Vec<_> = pond let pond: Vec<_> = pond
.iter() .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() .unwrap()
.iter() .iter()
.map(|entity| -> Result<_> { .map(|entity| -> Result<_> {