diff --git a/.gitignore b/.gitignore index 07132f1..6076d82 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +*.log + target # Devenv @@ -10,5 +12,3 @@ devenv.local.yaml # pre-commit .pre-commit-config.yaml - -mprocs.log diff --git a/jong-line/src/lib.rs b/jong-line/src/lib.rs index 438880d..42ca574 100644 --- a/jong-line/src/lib.rs +++ b/jong-line/src/lib.rs @@ -1,6 +1,6 @@ #![feature(if_let_guard)] -use log::debug; +use log::{debug, trace}; use spacetimedb::{ReducerContext, Table, reducer}; use crate::tables::*; @@ -34,6 +34,7 @@ pub fn connect(ctx: &ReducerContext) -> Result<(), String> { ctx.db.logged_out_player().identity().delete(ctx.sender); player } else { + debug!("inserting new player with identity {:?}", ctx.sender); ctx.db.player().try_insert(Player { identity: ctx.sender, id: 0, @@ -56,10 +57,14 @@ pub fn disconnect(ctx: &ReducerContext) -> Result<(), String> { .player() .identity() .find(ctx.sender) - .ok_or_else(|| format!("can't find player {}", ctx.sender))?; + .ok_or_else(|| format!("can't find player {} to disconnect", ctx.sender))?; - ctx.db.logged_out_player().insert(player); - ctx.db.player().identity().delete(ctx.sender); + let player = ctx.db.logged_out_player().insert(player); + if !ctx.db.player().identity().delete(ctx.sender) { + Err("can't delete row")? + } + + debug!("player disconnected: {:?}", player); Ok(()) } diff --git a/jong/src/main.rs b/jong/src/main.rs index 137cbff..dcb9492 100644 --- a/jong/src/main.rs +++ b/jong/src/main.rs @@ -1,7 +1,14 @@ +use std::fs::File; + use bevy::{log::LogPlugin, prelude::*}; use clap::{Parser, Subcommand}; use tracing::Level; -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; +use tracing_subscriber::{ + Layer, + fmt::{self, layer}, + layer::SubscriberExt, + util::SubscriberInitExt, +}; // mod gui; mod tui; @@ -33,6 +40,7 @@ fn main() { Mode::RunTui => { tracing_subscriber::registry() .with(tui_logger::TuiTracingSubscriberLayer) + .with(fmt::layer().with_writer(File::create("jong.log").unwrap())) .init(); tui_logger::init_logger(tui_logger::LevelFilter::Trace).unwrap(); tui_logger::set_env_filter_from_string(FILTERSTRING); diff --git a/jong/src/riichi.rs b/jong/src/riichi.rs index 0a2e319..de16274 100644 --- a/jong/src/riichi.rs +++ b/jong/src/riichi.rs @@ -1,15 +1,14 @@ -use bevy::platform::collections::HashMap; use bevy::prelude::*; use bevy_spacetimedb::{ ReadInsertUpdateMessage, ReadStdbConnectedMessage, ReadStdbDisconnectedMessage, ReadUpdateMessage, StdbPlugin, }; +use jong_db::{self, add_bot, set_ready}; use jong_db::{ - self, BotTableAccess, DbConnection, LobbyTableAccess, PlayerHand, PlayerTableAccess, - RemoteTables, ViewClosedHandsTableAccess, ViewHandTableAccess as _, + BotTableAccess, DbConnection, LobbyTableAccess, PlayerHand, PlayerTableAccess, RemoteTables, + ViewClosedHandsTableAccess, ViewHandTableAccess, }; -use jong_db::{add_bot, set_ready}; use jong_types::*; use spacetimedb_sdk::Table; @@ -46,8 +45,7 @@ impl Plugin for Riichi { .add_systems(Startup, subscriptions) .add_observer(on_subscribed) .add_systems(Update, (on_connect, on_disconnect)) - .add_systems(Update, on_lobby_insert_update) - .add_systems(Update, on_player_insert_update) + .add_systems(Update, (on_lobby_insert_update, on_player_insert_update)) .add_systems( Update, (on_view_hand_update) @@ -56,7 +54,7 @@ impl Plugin for Riichi { } } -fn on_connect(stdb: SpacetimeDB, mut messages: ReadStdbConnectedMessage, _commands: Commands) { +fn on_connect(stdb: SpacetimeDB, mut messages: ReadStdbConnectedMessage) { for msg in messages.read() { info!("you're now jongline"); @@ -139,10 +137,13 @@ fn on_subscribed( fn spawn_main_player( stdb: &SpacetimeDB, + commands: &mut Commands, next_turnstate: &mut ResMut>, + player: &jong_db::Player, ) { + trace!("spawn_main_player"); let main_player = commands .spawn(( Player { @@ -152,42 +153,55 @@ fn spawn_main_player( )) .id(); if let Some(player_hand) = stdb.db().view_hand().iter().next() { - let hand_tiles: Vec<_> = player_hand - .hand - .iter() - .map(|dbt| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id()) - .collect(); - let pond_tiles: Vec<_> = player_hand - .pond - .iter() - .map(|dbt| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id()) - .collect(); - let pond = commands.spawn(Hand).add_children(&pond_tiles).id(); - let hand = commands.spawn(Pond).add_children(&hand_tiles).id(); - commands.entity(main_player).add_children(&[pond, hand]); - - if player_hand.turn_state == jong_db::TurnState::Tsumo - && let Some(drawn_dbt) = player_hand.working_tile - { - let drawn = commands - .spawn((Drawn, Tile::from(&drawn_dbt.tile), TileId(drawn_dbt.id))) - .id(); - commands.entity(main_player).add_child(drawn); - } - next_turnstate.set(player_hand.turn_state.into()); + spawn_main_hand(commands, next_turnstate, main_player, &player_hand); } } +fn spawn_main_hand( + commands: &mut Commands, + next_turnstate: &mut ResMut>, + main_player: Entity, + + player_hand: &PlayerHand, +) { + let hand_tiles: Vec<_> = player_hand + .hand + .iter() + .map(|dbt| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id()) + .collect(); + let pond_tiles: Vec<_> = player_hand + .pond + .iter() + .map(|dbt| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id()) + .collect(); + let pond = commands.spawn(Hand).add_children(&pond_tiles).id(); + let hand = commands.spawn(Pond).add_children(&hand_tiles).id(); + let children = commands.entity(main_player).add_children(&[pond, hand]).id(); + + debug!("main_hand: {:?}\n main_pond: {:?}, children: {:?}", hand_tiles, pond_tiles, children); + + if player_hand.turn_state == jong_db::TurnState::Tsumo + && let Some(drawn_dbt) = &player_hand.working_tile + { + let drawn = commands + .spawn((Drawn, Tile::from(&drawn_dbt.tile), TileId(drawn_dbt.id))) + .id(); + commands.entity(main_player).add_child(drawn); + } + next_turnstate.set(player_hand.turn_state.into()); +} + fn spawn_other_player(stdb: &SpacetimeDB, commands: &mut Commands, player: &jong_db::Player) { let id = PlayerOrBot::Player { id: player.id }; - let hand_view = stdb + if let Some(hand_view) = stdb .db() .view_closed_hands() .iter() .find(|v| PlayerOrBot::from(&v.player) == id) - .unwrap(); - let hand_ent = commands.spawn((Hand, Closed(hand_view.hand_length))).id(); - commands.spawn(Player { id }).add_child(hand_ent); + { + let hand_ent = commands.spawn((Hand, Closed(hand_view.hand_length))).id(); + commands.spawn(Player { id }).add_child(hand_ent); + } } fn on_player_insert_update( @@ -203,6 +217,7 @@ fn on_player_insert_update( ) { for msg in messages.read() { if main_player.is_none() && msg.new.identity == stdb.identity() { + trace!("spawn_main_player"); spawn_main_player(&stdb, &mut commands, &mut next_turnstate, &msg.new); } else if other_players.iter().any(|p| { if let PlayerOrBot::Player { id } = &p.id { @@ -274,19 +289,23 @@ fn on_view_hand_update( mut commands: Commands, tiles: Query<(Entity, &TileId)>, - main_player: Single<&Children, With>, + main_player: Single<(Entity, Option<&Children>), With>, hand: Query>, pond: Query>, // drawn: Option>>, mut next_turnstate: ResMut>, ) { - trace!("on_view_hand_update"); - // TODO can this and similar run at startup or on play/reconnect? for msg in messages.read() { trace!("new hand: {:?}", msg.new); + if main_player.1.is_none() { + trace!("spawn_main_hand, {:?}", *main_player); + spawn_main_hand(&mut commands, &mut next_turnstate, main_player.0, &msg.new); + continue; + } + let hand_tiles: Vec<_> = msg .new .hand @@ -298,10 +317,6 @@ fn on_view_hand_update( .unwrap_or_else(|| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id()) }) .collect(); - commands - .entity(hand.iter().find(|e| main_player.contains(e)).unwrap()) - .replace_children(&hand_tiles); - let pond_tiles: Vec<_> = msg .new .pond @@ -313,8 +328,20 @@ fn on_view_hand_update( .unwrap_or_else(|| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id()) }) .collect(); + commands - .entity(pond.iter().find(|e| main_player.contains(e)).unwrap()) + .entity( + hand.iter() + .find(|e| main_player.1.is_some_and(|mp| mp.contains(e))) + .unwrap(), + ) + .replace_children(&hand_tiles); + commands + .entity( + pond.iter() + .find(|e| main_player.1.is_some_and(|mp| mp.contains(e))) + .unwrap(), + ) .replace_children(&pond_tiles); match msg.new.turn_state { diff --git a/jong/src/tui.rs b/jong/src/tui.rs index 9f35853..75df4b8 100644 --- a/jong/src/tui.rs +++ b/jong/src/tui.rs @@ -88,7 +88,6 @@ impl Plugin for TuiPlugin { (render::render_main_hand, render::render_main_pond) .run_if(in_state(GameState::Play)), render::render, - query_tester, ) .chain() .in_set(TuiSet::Render), @@ -96,24 +95,6 @@ impl Plugin for TuiPlugin { } } -fn query_tester( - main_player: Single<&Children, With>, - // hand: Query<(&Children, Entity), With>, -) { - trace!("owo"); - // let hand = hand - // .iter() - // .find_map(|(c, e)| { - // if main_player.contains(&e) { - // Some(c) - // } else { - // None - // } - // }) - // .unwrap(); - // debug!("{hand:?}"); -} - fn discard_tile( stdb: SpacetimeDB, diff --git a/jong/src/tui/render.rs b/jong/src/tui/render.rs index 0e573e0..2135fa9 100644 --- a/jong/src/tui/render.rs +++ b/jong/src/tui/render.rs @@ -115,6 +115,7 @@ pub(crate) fn render_main_hand( let hand: Vec<_> = hand .iter() .find_map(|(c, e)| { + debug!("main_player children: {:?}", *main_player); if main_player.contains(&e) { Some(c) } else {