diff --git a/docs/states b/docs/states new file mode 100644 index 0000000..13e0595 --- /dev/null +++ b/docs/states @@ -0,0 +1,18 @@ +gamestate + + none + join_or_create_lobby() + + lobby + set_ready() + add_bot() + start_game() + + setup + shuffle_deal() + + deal + animations?? + + play + discards?? diff --git a/jong-db/src/db/advance_state_timer_table.rs b/jong-db/src/db/advance_state_timer_table.rs deleted file mode 100644 index a6096e0..0000000 --- a/jong-db/src/db/advance_state_timer_table.rs +++ /dev/null @@ -1,144 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#![allow(unused, clippy::all)] -use super::advance_state_timer_type::AdvanceStateTimer; -use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; - -/// Table handle for the table `advance_state_timer`. -/// -/// Obtain a handle from the [`AdvanceStateTimerTableAccess::advance_state_timer`] method on [`super::RemoteTables`], -/// like `ctx.db.advance_state_timer()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.advance_state_timer().on_insert(...)`. -pub struct AdvanceStateTimerTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `advance_state_timer`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait AdvanceStateTimerTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`AdvanceStateTimerTableHandle`], which mediates access to the table `advance_state_timer`. - fn advance_state_timer(&self) -> AdvanceStateTimerTableHandle<'_>; -} - -impl AdvanceStateTimerTableAccess for super::RemoteTables { - fn advance_state_timer(&self) -> AdvanceStateTimerTableHandle<'_> { - AdvanceStateTimerTableHandle { - imp: self - .imp - .get_table::("advance_state_timer"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct AdvanceStateTimerInsertCallbackId(__sdk::CallbackId); -pub struct AdvanceStateTimerDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for AdvanceStateTimerTableHandle<'ctx> { - type Row = AdvanceStateTimer; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { - self.imp.count() - } - fn iter(&self) -> impl Iterator + '_ { - self.imp.iter() - } - - type InsertCallbackId = AdvanceStateTimerInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> AdvanceStateTimerInsertCallbackId { - AdvanceStateTimerInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: AdvanceStateTimerInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = AdvanceStateTimerDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> AdvanceStateTimerDeleteCallbackId { - AdvanceStateTimerDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: AdvanceStateTimerDeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("advance_state_timer"); - _table.add_unique_constraint::("scheduled_id", |row| &row.scheduled_id); -} -pub struct AdvanceStateTimerUpdateCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::TableWithPrimaryKey for AdvanceStateTimerTableHandle<'ctx> { - type UpdateCallbackId = AdvanceStateTimerUpdateCallbackId; - - fn on_update( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, - ) -> AdvanceStateTimerUpdateCallbackId { - AdvanceStateTimerUpdateCallbackId(self.imp.on_update(Box::new(callback))) - } - - fn remove_on_update(&self, callback: AdvanceStateTimerUpdateCallbackId) { - self.imp.remove_on_update(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - -/// Access to the `scheduled_id` unique index on the table `advance_state_timer`, -/// which allows point queries on the field of the same name -/// via the [`AdvanceStateTimerScheduledIdUnique::find`] method. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.advance_state_timer().scheduled_id().find(...)`. -pub struct AdvanceStateTimerScheduledIdUnique<'ctx> { - imp: __sdk::UniqueConstraintHandle, - phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -impl<'ctx> AdvanceStateTimerTableHandle<'ctx> { - /// Get a handle on the `scheduled_id` unique index on the table `advance_state_timer`. - pub fn scheduled_id(&self) -> AdvanceStateTimerScheduledIdUnique<'ctx> { - AdvanceStateTimerScheduledIdUnique { - imp: self.imp.get_unique_constraint::("scheduled_id"), - phantom: std::marker::PhantomData, - } - } -} - -impl<'ctx> AdvanceStateTimerScheduledIdUnique<'ctx> { - /// Find the subscribed row whose `scheduled_id` column value is equal to `col_val`, - /// if such a row is present in the client cache. - pub fn find(&self, col_val: &u64) -> Option { - self.imp.find(col_val) - } -} diff --git a/jong-db/src/db/advance_state_timer_type.rs b/jong-db/src/db/advance_state_timer_type.rs deleted file mode 100644 index 8411902..0000000 --- a/jong-db/src/db/advance_state_timer_type.rs +++ /dev/null @@ -1,17 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#![allow(unused, clippy::all)] -use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; - -#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] -#[sats(crate = __lib)] -pub struct AdvanceStateTimer { - pub scheduled_id: u64, - pub scheduled_at: __sdk::ScheduleAt, - pub lobby_id: u32, -} - -impl __sdk::InModule for AdvanceStateTimer { - type Module = super::RemoteModule; -} diff --git a/jong-db/src/db/mod.rs b/jong-db/src/db/mod.rs index 3eb7040..fcf6370 100644 --- a/jong-db/src/db/mod.rs +++ b/jong-db/src/db/mod.rs @@ -7,8 +7,6 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; pub mod add_bot_reducer; -pub mod advance_state_timer_table; -pub mod advance_state_timer_type; pub mod bot_table; pub mod bot_type; pub mod clear_all_reducer; @@ -38,8 +36,6 @@ pub mod wall_table; pub mod wind_type; pub use add_bot_reducer::{add_bot, set_flags_for_add_bot, AddBotCallbackId}; -pub use advance_state_timer_table::*; -pub use advance_state_timer_type::AdvanceStateTimer; pub use bot_table::*; pub use bot_type::Bot; pub use clear_all_reducer::{clear_all, set_flags_for_clear_all, ClearAllCallbackId}; @@ -193,7 +189,6 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer { #[allow(non_snake_case)] #[doc(hidden)] pub struct DbUpdate { - advance_state_timer: __sdk::TableUpdate, bot: __sdk::TableUpdate, lobby: __sdk::TableUpdate, player: __sdk::TableUpdate, @@ -207,9 +202,6 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { let mut db_update = DbUpdate::default(); for table_update in raw.tables { match &table_update.table_name[..] { - "advance_state_timer" => db_update - .advance_state_timer - .append(advance_state_timer_table::parse_table_update(table_update)?), "bot" => db_update .bot .append(bot_table::parse_table_update(table_update)?), @@ -251,12 +243,6 @@ impl __sdk::DbUpdate for DbUpdate { ) -> AppliedDiff<'_> { let mut diff = AppliedDiff::default(); - diff.advance_state_timer = cache - .apply_diff_to_table::( - "advance_state_timer", - &self.advance_state_timer, - ) - .with_updates_by_pk(|row| &row.scheduled_id); diff.bot = cache .apply_diff_to_table::("bot", &self.bot) .with_updates_by_pk(|row| &row.id); @@ -281,7 +267,6 @@ impl __sdk::DbUpdate for DbUpdate { #[allow(non_snake_case)] #[doc(hidden)] pub struct AppliedDiff<'r> { - advance_state_timer: __sdk::TableAppliedDiff<'r, AdvanceStateTimer>, bot: __sdk::TableAppliedDiff<'r, Bot>, lobby: __sdk::TableAppliedDiff<'r, Lobby>, player: __sdk::TableAppliedDiff<'r, Player>, @@ -300,11 +285,6 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> { event: &EventContext, callbacks: &mut __sdk::DbCallbacks, ) { - callbacks.invoke_table_row_callbacks::( - "advance_state_timer", - &self.advance_state_timer, - event, - ); callbacks.invoke_table_row_callbacks::("bot", &self.bot, event); callbacks.invoke_table_row_callbacks::("lobby", &self.lobby, event); callbacks.invoke_table_row_callbacks::("player", &self.player, event); @@ -1029,7 +1009,6 @@ impl __sdk::SpacetimeModule for RemoteModule { type SubscriptionHandle = SubscriptionHandle; fn register_tables(client_cache: &mut __sdk::ClientCache) { - advance_state_timer_table::register_table(client_cache); bot_table::register_table(client_cache); lobby_table::register_table(client_cache); player_table::register_table(client_cache); diff --git a/jong-line/src/lib.rs b/jong-line/src/lib.rs index 28bf92a..b626822 100644 --- a/jong-line/src/lib.rs +++ b/jong-line/src/lib.rs @@ -1,9 +1,7 @@ use log::debug; use spacetimedb::{ReducerContext, Table, reducer}; -use jong_types::TurnState; - -use crate::tables::*; +use crate::tables::{player::player, *}; mod reducers { mod deal; @@ -46,7 +44,6 @@ pub fn login_or_add_player(ctx: &ReducerContext) { hand: vec![], pond: vec![], drawn_tile: None, - turn_state: TurnState::None, }) { debug!("added player: {:?}", player); } else { diff --git a/jong-line/src/reducers/hand.rs b/jong-line/src/reducers/hand.rs index 842926a..1e3f18a 100644 --- a/jong-line/src/reducers/hand.rs +++ b/jong-line/src/reducers/hand.rs @@ -49,7 +49,6 @@ pub fn discard_tile(ctx: &ReducerContext, tile_id: u32) -> Result<(), String> { let dealt_tile = if let Some(dealt) = ctx.db.tile().id().find(tile_id) { if let Some(drawn) = player.drawn_tile { if drawn.id == dealt.id { - // dealt from drawn tile dealt } else if let Some((i, _)) = player .hand @@ -57,7 +56,6 @@ pub fn discard_tile(ctx: &ReducerContext, tile_id: u32) -> Result<(), String> { .enumerate() .find(|(_, t)| t.id == tile_id) { - // dealt from hand let dealt = player.hand.remove(i); player.hand.push(drawn); player.hand.sort_by_key(|t| t.tile); diff --git a/jong-line/src/reducers/lobby.rs b/jong-line/src/reducers/lobby.rs index f169dfc..1a4df28 100644 --- a/jong-line/src/reducers/lobby.rs +++ b/jong-line/src/reducers/lobby.rs @@ -1,7 +1,7 @@ use log::info; use spacetimedb::{ReducerContext, Table, rand::seq::SliceRandom, reducer}; -use crate::tables::*; +use crate::tables::{player::player, *}; #[reducer] pub fn join_or_create_lobby(ctx: &ReducerContext, mut lobby_id: u32) -> Result<(), String> { @@ -19,6 +19,7 @@ pub fn join_or_create_lobby(ctx: &ReducerContext, mut lobby_id: u32) -> Result<( host_player_id: player.id, players: vec![PlayerOrBot::Player { id: player.id }], game_state: jong_types::states::GameState::Lobby, + turn_state: jong_types::states::TurnState::None, dealer_idx: 0, current_idx: 0, }); diff --git a/jong-line/src/tables.rs b/jong-line/src/tables.rs index 5939c67..17ec267 100644 --- a/jong-line/src/tables.rs +++ b/jong-line/src/tables.rs @@ -1,10 +1,13 @@ use spacetimedb::{SpacetimeType, table}; use jong_types::{ - states::{GameState, TurnState}, tiles::Tile, + states::{GameState, TurnState}, }; +pub mod player; +pub use player::*; + #[derive(Debug, Clone)] #[table(name = lobby, public)] pub struct Lobby { @@ -19,6 +22,7 @@ pub struct Lobby { pub current_idx: u8, pub game_state: GameState, + pub turn_state: TurnState, } #[table(name = wall)] @@ -44,55 +48,3 @@ pub enum PlayerOrBot { Player { id: u32 }, Bot { id: u32 }, } - -#[table(name = advance_state_timer)] -pub struct AdvanceStateTimer { - #[primary_key] - #[auto_inc] - scheduled_id: u64, - scheduled_at: spacetimedb::ScheduleAt, - - lobby_id: u32, -} - -// FIXME this shant be public, use views -#[table(name = player, public)] -#[derive(Debug)] -pub struct Player { - #[primary_key] - pub identity: spacetimedb::Identity, - - #[unique] - #[auto_inc] - pub id: u32, - - pub name: Option, - - #[index(btree)] - pub lobby_id: u32, - pub ready: bool, - - pub turn_state: TurnState, - - pub sort: bool, - - pub hand: Vec, - pub pond: Vec, - - pub drawn_tile: Option, -} - -#[table(name = bot)] -pub struct Bot { - #[primary_key] - #[auto_inc] - pub id: u32, - - #[index(btree)] - pub lobby_id: u32, - - pub hand: Vec, - pub pond: Vec, - - pub drawn_tile: Option, -} diff --git a/jong-line/src/tables/player.rs b/jong-line/src/tables/player.rs new file mode 100644 index 0000000..c3bf342 --- /dev/null +++ b/jong-line/src/tables/player.rs @@ -0,0 +1,44 @@ +use spacetimedb::Identity; +use spacetimedb::{SpacetimeType, table}; + +use super::DbTile; + +// FIXME this shant be public, use views +#[table(name = player, public)] +#[derive(Debug)] +pub struct Player { + #[primary_key] + pub identity: Identity, + + #[unique] + #[auto_inc] + pub id: u32, + + pub name: Option, + + #[index(btree)] + pub lobby_id: u32, + pub ready: bool, + + pub sort: bool, + + pub hand: Vec, + pub pond: Vec, + + pub drawn_tile: Option, +} + +#[table(name = bot)] +pub struct Bot { + #[primary_key] + #[auto_inc] + pub id: u32, + + #[index(btree)] + pub lobby_id: u32, + + pub hand: Vec, + pub pond: Vec, + + pub drawn_tile: Option, +} diff --git a/jong/src/riichi.rs b/jong/src/riichi.rs index 38afe95..0cd9eb9 100644 --- a/jong/src/riichi.rs +++ b/jong/src/riichi.rs @@ -101,38 +101,17 @@ fn on_player_insert_update( mut messages: ReadInsertUpdateMessage, mut commands: Commands, - pond: Option>>, hand: Option>>, tiles: Query<(Entity, &TileId)>, ) { let hand = if hand.is_none() { let hand = commands.spawn(Hand).id(); - commands.spawn(Pond); hand } else { *hand.unwrap() }; - let pond = if pond.is_none() { - let pond = commands.spawn(Pond).id(); - commands.spawn(Pond); - pond - } else { - *pond.unwrap() - }; for msg in messages.read() { - match msg.new.turn_state { - jong_db::TurnState::None => {} - jong_db::TurnState::Tsumo => { - stdb.reducers().draw_tile().unwrap(); - } - jong_db::TurnState::Menzen => todo!(), - jong_db::TurnState::RiichiKan => todo!(), - jong_db::TurnState::RonChiiPonKan => { - stdb.reducers().skip_call().unwrap(); - } - jong_db::TurnState::End => todo!(), - } let hand_tiles: Vec<_> = msg .new .hand @@ -146,30 +125,11 @@ fn on_player_insert_update( }) .collect(); - let pond_tiles: Vec<_> = msg - .new - .pond - .iter() - .map(|dbt| { - tiles - .iter() - .find_map(|(e, t)| if *t == TileId(dbt.id) { Some(e) } else { None }) - .expect(&format!( - "dealt tiles should still be around, couldn't find {:?}. Tiles: {:?}", - dbt, - tiles.iter().map(|(_, t)| t).collect::>() - )) - }) - .collect(); - debug!("hand_tiles: {hand_tiles:?}"); commands.entity(hand).replace_children(&hand_tiles); - commands.entity(pond).replace_children(&pond_tiles); - // drawn tile is always a new tile to us until wall isn't fake if let Some(dbt) = &msg.new.drawn_tile { - debug!("drew tile with id: {}", dbt.id); commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id), Drawn)); } } @@ -217,6 +177,19 @@ fn on_lobby_insert_update( } jong_db::GameState::Play => { trace!("game entered play"); + match msg.new.turn_state { + jong_db::TurnState::None => {} + jong_db::TurnState::Tsumo => { + stdb.reducers().draw_tile().unwrap(); + } + jong_db::TurnState::Menzen => todo!(), + jong_db::TurnState::RiichiKan => todo!(), + jong_db::TurnState::RonChiiPonKan => { + stdb.reducers().skip_call().unwrap(); + } + jong_db::TurnState::End => todo!(), + } + next_turnstate.set(msg.new.turn_state.into()); } jong_db::GameState::Exit => { trace!("game enetered exit"); diff --git a/jong/src/riichi/player.rs b/jong/src/riichi/player.rs index 1622423..8c7ee4c 100644 --- a/jong/src/riichi/player.rs +++ b/jong/src/riichi/player.rs @@ -9,7 +9,7 @@ pub struct MainPlayer; #[derive(Component)] pub struct CurrentPlayer; -#[derive(Component, PartialEq, Eq, Debug)] +#[derive(Component, PartialEq, Eq)] pub struct TileId(pub u32); #[derive(Component)] diff --git a/jong/src/tui.rs b/jong/src/tui.rs index 9198051..18b994c 100644 --- a/jong/src/tui.rs +++ b/jong/src/tui.rs @@ -85,7 +85,7 @@ impl Plugin for TuiPlugin { .add_systems( Update, ( - (render::render_hand, render::render_pond).run_if(in_state(GameState::Play)), + render::render_hand.run_if(in_state(GameState::Play)), render::render, ) .chain() @@ -106,7 +106,7 @@ fn discard_tile( while let Some(message) = selected.read().next() { if let Ok(tile_id) = tiles.get(message.0) { stdb.reducers().discard_tile(tile_id.0).unwrap(); - commands.entity(drawn.0).remove::(); + commands.get_entity(drawn.0).unwrap().despawn(); } } } diff --git a/jong/src/tui/render.rs b/jong/src/tui/render.rs index 409f7e2..f1a243c 100644 --- a/jong/src/tui/render.rs +++ b/jong/src/tui/render.rs @@ -6,8 +6,10 @@ use ratatui::layout::{Constraint, Flex, Layout, Offset, Rect, Size}; use ratatui::style::{Modifier, Stylize}; use ratatui::widgets::{Block, Borders, Clear, Paragraph}; -use jong::riichi::player::*; -use jong_types::*; +use jong::riichi::player::{CurrentPlayer, MainPlayer, Player}; +use jong::riichi::player::{Drawn, Hand}; +// use jong::riichi::round::Wind; +// use jong_types::*; use crate::tui::input::Hovered; use crate::tui::layout::*; @@ -195,44 +197,3 @@ pub(crate) fn render_hand( Ok(()) } - -pub(crate) fn render_pond( - mut commands: Commands, - mut tui: ResMut, - - hovered: Query>, - layouts: Res, - - pond: Single<(&Children, Entity), With>, - tiles: Query<&Tile>, -) -> Result { - let mut frame = tui.get_frame(); - - let pond: Vec<_> = pond - .0 - .iter() - .map(|entity| -> Result<_> { - let tile = tiles.get(entity).unwrap(); - let widget = render_tile(tile, false); - - Ok((entity, widget)) - }) - .collect::>()?; - - let mut this_pond = layouts.this_pond; - let row_constraints = [Constraint::Max(4); 3]; - let col_constraints = [Constraint::Max(5); 6]; - let row_layouts = Layout::vertical(row_constraints).flex(Flex::Start); - let col_layouts = Layout::horizontal(col_constraints).flex(Flex::Start); - let mut rows = row_layouts.areas::<3>(this_pond); - - for (rect, (_, tile)) in rows - .iter() - .flat_map(|row| col_layouts.areas::<6>(*row)) - .zip(pond) - { - frame.render_widget(tile, rect); - } - - Ok(()) -}