diff --git a/.gitignore b/.gitignore index cbec1d4..07132f1 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ devenv.local.yaml # pre-commit .pre-commit-config.yaml + +mprocs.log diff --git a/devenv.lock b/devenv.lock index dfdab03..9711b70 100644 --- a/devenv.lock +++ b/devenv.lock @@ -3,10 +3,10 @@ "devenv": { "locked": { "dir": "src/modules", - "lastModified": 1770399425, + "lastModified": 1770666213, "owner": "cachix", "repo": "devenv", - "rev": "0f006b2e9f591cc44cf219048b5e33793530403b", + "rev": "d4ffee46c9088df6e000470b998a2d2c16517f62", "type": "github" }, "original": { @@ -125,10 +125,10 @@ ] }, "locked": { - "lastModified": 1770520253, + "lastModified": 1770606655, "owner": "oxalica", "repo": "rust-overlay", - "rev": "ebb8a141f60bb0ec33836333e0ca7928a072217f", + "rev": "11a396520bf911e4ed01e78e11633d3fc63b350e", "type": "github" }, "original": { diff --git a/devenv.nix b/devenv.nix index 57c530b..89cd3ec 100644 --- a/devenv.nix +++ b/devenv.nix @@ -1,17 +1,29 @@ { pkgs, lib, - config, - inputs, ... }: rec { + # https://devenv.sh/processes/ + processes.spacetimedb_start.exec = "spacetime start"; + processes.spacetimedb_generate_bindings = { + exec = "spacetime dev --module-bindings-path jong/src/stdb jongline --delete-data=always"; + # notify.enable = true; + # TODO features not yet supp??? + # restart = "always"; + # watch = { + # paths = [./jong]; + # }; + }; + # https://devenv.sh/packages/ packages = with pkgs; [ + # process-compose pkg-config # spacetimedb openssl binaryen + spacetimedb # bevy Linux # Audio (Linux only) @@ -41,10 +53,9 @@ components = ["rust-src" "rust-docs" "rustc-codegen-cranelift" "rust-analyzer" "rustfmt"]; }; - # https://devenv.sh/processes/ - processes.spacetimedb_start.exec = "spacetime start"; - processes.spacetimedb_generate_bindings = { - exec = "spacetime dev --module-bindings-path jong/src/stdb jongline --delete-data=always"; + process.manager.implementation = "mprocs"; + process.managers.mprocs.settings = { + server = "127.0.0.1:4050"; }; # https://devenv.sh/services/ diff --git a/devenv.yaml b/devenv.yaml index 37e8589..48e1844 100644 --- a/devenv.yaml +++ b/devenv.yaml @@ -1,3 +1,4 @@ +allowUnfree: true inputs: nixpkgs: url: github:cachix/devenv-nixpkgs/rolling diff --git a/jong/src/game.rs b/jong/src/game.rs index d00e50c..c45ee3b 100644 --- a/jong/src/game.rs +++ b/jong/src/game.rs @@ -6,13 +6,14 @@ use bevy_spacetimedb::{ TableMessages, }; use spacetimedb::Identity; -use spacetimedb_sdk::{DbContext, credentials}; +use spacetimedb_sdk::{DbContext, Table, credentials}; use crate::{ - SpacetimeDB, creds_store, + SpacetimeDB, creds_store, game, stdb::{ self, DbConnection, HandTableAccess, LobbyTableAccess, PlayerTableAccess, RemoteTables, - add_bot, join_or_create_lobby, login_or_add_player, setup_game, + ViewPlayerHandTableAccess, add_bot, join_or_create_lobby, login_or_add_player, + shuffle_deal, }, }; use crate::{ @@ -24,7 +25,7 @@ use crate::{ }, tile::{self}, }; -use jong_types::GameState; +use jong_types::*; pub mod hand; pub mod player; @@ -68,8 +69,6 @@ impl Plugin for Riichi { // .init_resource::() .add_message::() .add_systems(Startup, tile::init_tiles) - // .add_systems(OnEnter(GameState::Setup), setup) - // .add_systems(OnEnter(GameState::Deal), hand::shuffle_deal) // .add_systems(Update, hand::sort_hands.run_if(in_state(GameState::Play))) // .add_systems(OnEnter(TurnState::Tsumo), round::tsumo) // .add_systems(OnEnter(TurnState::Menzen), round::menzen) @@ -79,22 +78,27 @@ impl Plugin for Riichi { // .add_systems(Update, round::ron_chi_pon_kan.run_if(in_state(TurnState::RonChiiPonKan)).after(round::notify_callable)) // .add_systems(OnEnter(TurnState::End), round::end) // stdb - .add_systems(Startup, sub_to_all) + .add_systems(Startup, subscriptions) .add_systems(Update, on_connect) .add_systems(Update, on_disconnect) - .add_systems(Update, (on_player_insert_update, on_lobby_insert_update).chain()) + .add_systems(Update, on_player_insert_update) + .add_systems(Update, on_lobby_insert_update) .add_systems(OnEnter(GameState::Setup), join_or_create_lobby) - // .add_systems(Update, (view_hand).run_if(in_state(GameState::Play))) + .add_systems(Update, view_hand.run_if(in_state(GameState::Play))) + .add_systems(Update, (view_hand).run_if(in_state(GameState::Play))) // semicolon stopper ; } } -fn sub_to_all(stdb: SpacetimeDB) { - stdb.subscription_builder() - .on_applied(|_| trace!("made all subs!")) - .on_error(|_, err| error!("sub failed: {err}")) - .subscribe_to_all_tables(); +fn view_hand( + stdb: SpacetimeDB, + mut commands: Commands, + // hand: Populated<&mut Children, With>, +) { + if let Some(view) = stdb.db().view_player_hand().iter().next() { + // hand.get_mut(entity) + } } fn on_connect(stdb: SpacetimeDB, mut messages: ReadStdbConnectedMessage, mut commands: Commands) { @@ -114,8 +118,20 @@ fn on_disconnect(stdb: SpacetimeDB, mut messages: ReadStdbDisconnectedMessage) { } } -#[derive(Resource, Deref)] -struct Player(stdb::Player); +fn subscriptions(stdb: SpacetimeDB) { + stdb.subscription_builder() + .on_applied(|_| trace!("made all subs!")) + .on_error(|_, err| error!("sub failed: {err}")) + .subscribe([ + format!( + "SELECT * FROM player p WHERE p.identity = '{}'", + stdb.identity() + ), + "SELECT l.* FROM lobby l JOIN player p ON l.host_player_id = p.id".to_string(), + "SELECT * FROM view_player_hand vph".to_string(), + ]); + // .subscribe_to_all_tables(); +} fn on_player_insert_update( stdb: SpacetimeDB, @@ -124,26 +140,17 @@ fn on_player_insert_update( mut commands: Commands, ) { for msg in messages.read() { - debug!( - "player_insert_update msg:\n{:#?} -> \n{:#?}", - msg.old, msg.new - ); - - if msg.new.identity == stdb.identity() { - commands.insert_resource(Player(msg.new.clone())); - // TODO add bots elsewhere - if msg.new.lobby_id != 0 { - info!("joined lobby {}", msg.new.lobby_id); - for _ in 0..3 { - stdb.reducers().add_bot(msg.new.lobby_id).unwrap() - } - } - } + debug!("player_insert_update msg:\n{:#?}", msg.new); } } -fn join_or_create_lobby(stdb: SpacetimeDB, player: Res) { - let mut player = player.clone(); +fn join_or_create_lobby(stdb: SpacetimeDB) { + let player = stdb + .db() + .player() + .identity() + .find(&stdb.identity()) + .unwrap(); if player.lobby_id == 0 { stdb.reducers().join_or_create_lobby(0).unwrap(); @@ -152,52 +159,63 @@ fn join_or_create_lobby(stdb: SpacetimeDB, player: Res) { } } -impl From for GameState { - fn from(value: stdb::GameState) -> Self { - match value { - stdb::GameState::None => Self::None, - stdb::GameState::Setup => Self::Setup, - stdb::GameState::Deal => Self::Deal, - stdb::GameState::Play => Self::Play, - stdb::GameState::Exit => Self::Exit, - } - } -} - fn on_lobby_insert_update( stdb: SpacetimeDB, mut messages: ReadInsertUpdateMessage, - player: Option>, - mut commands: Commands, mut next_gamestate: ResMut>, ) { for msg in messages.read() { - if let Some(player) = player.as_ref() - && player.lobby_id == msg.new.id - { - debug!("on_lobby_insert_update: {:#?}", msg.new); - next_gamestate.set(msg.new.game_state.into()); + trace!("on_lobby_insert_update msg:\n{:#?}", msg.new); - match msg.new.game_state { - stdb::GameState::None => { - trace!("setup game"); - stdb.reducers().setup_game(player.lobby_id).unwrap(); + next_gamestate.set(msg.new.game_state.into()); + match msg.new.game_state { + stdb::GameState::None => { + trace!("game entered none"); + } + stdb::GameState::Setup => { + trace!("game entered setup"); + + let player = stdb + .db() + .player() + .identity() + .find(&stdb.identity()) + .unwrap(); + + if player.lobby_id == msg.new.id { + stdb.reducers().shuffle_deal(player.lobby_id).unwrap(); + for _ in 0..3 { + stdb.reducers().add_bot(player.lobby_id).unwrap(); + } + } else { + error!("no player but game in setup") } - stdb::GameState::Setup => { - trace!("game entered setup"); - } - stdb::GameState::Deal => { - trace!("game entered deal") - } - stdb::GameState::Play => { - trace!("game entered play") - } - stdb::GameState::Exit => { - trace!("game enetered exit") + } + stdb::GameState::Deal => { + trace!("game entered deal"); + } + stdb::GameState::Play => { + trace!("game entered play"); + + // TODO this should run once to spawn the hand? or do elsewhere + if let Some(hand) = stdb.db().view_player_hand().iter().next() { + debug!("hand: {hand:?}"); + let tiles = hand + .tiles + .iter() + .map(Into::into) + .map(|t: Tile| commands.spawn(t).id()) + .collect::>(); + commands.spawn(Hand).add_children(&tiles); + } else { + error!("entered play without a hand") } } + stdb::GameState::Exit => { + trace!("game enetered exit"); + } } } } diff --git a/jong/src/game/hand.rs b/jong/src/game/hand.rs index 26f81c1..4e89c13 100644 --- a/jong/src/game/hand.rs +++ b/jong/src/game/hand.rs @@ -25,45 +25,6 @@ pub struct Discarded; // Manual, // } -pub(crate) fn sort_hands( - tiles: Query<&Tile>, - hands: Query<&mut Children, (Changed, With, Without)>, -) -> Result { - for mut hand in hands { - hand.sort_unstable_by_key(|e| tiles.get(*e).unwrap().suit); - debug!("sorted: {hand:?}"); - } - Ok(()) -} - -pub(crate) fn shuffle_deal( - mut commands: Commands, - tiles: Populated>, - players: Populated>, - wall_ent: Single>, - mut next_gamestate: ResMut>, -) { - use rand::seq::SliceRandom; - - let mut rng = rand::rng(); - let mut walltiles: Vec<_> = tiles.iter().collect(); - walltiles.shuffle(&mut rng); - - for player_ent in players { - let handtiles = walltiles.split_off(walltiles.len() - 13); - let hand_ent = commands.spawn(Hand).add_children(&handtiles).id(); - 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); -} - /// assumes hand is sorted pub(crate) fn check_wincon(hand: &[Tile; 14], melds: &[&[Tile]]) -> bool { // 4x3 + pair diff --git a/jong/src/lib.rs b/jong/src/lib.rs index 8981acd..ac78c87 100644 --- a/jong/src/lib.rs +++ b/jong/src/lib.rs @@ -19,3 +19,55 @@ pub type SpacetimeDB<'a> = Res<'a, StdbConnection>; fn creds_store() -> credentials::File { credentials::File::new("jongline") } + +impl From for jong_types::GameState { + fn from(value: stdb::GameState) -> Self { + match value { + stdb::GameState::None => Self::None, + stdb::GameState::Setup => Self::Setup, + stdb::GameState::Deal => Self::Deal, + stdb::GameState::Play => Self::Play, + stdb::GameState::Exit => Self::Exit, + } + } +} + +impl From<&stdb::Tile> for jong_types::Tile { + fn from(value: &stdb::tile_type::Tile) -> Self { + Self { + suit: value.suit.clone().into(), + } + } +} + +impl From for jong_types::Suit { + fn from(value: stdb::Suit) -> Self { + match value { + stdb::Suit::Man(rank) => Self::Man(rank.into()), + stdb::Suit::Pin(rank) => Self::Pin(rank.into()), + stdb::Suit::Sou(rank) => Self::Sou(rank.into()), + stdb::Suit::Wind(wind) => Self::Wind(wind.into()), + stdb::Suit::Dragon(dragon) => Self::Dragon(dragon.into()), + } + } +} + +impl From for jong_types::Rank { + fn from(value: stdb::Rank) -> Self { + Self { + number: value.number, + } + } +} + +impl From for jong_types::Wind { + fn from(value: stdb::Wind) -> Self { + Self::from_repr(value as usize).unwrap() + } +} + +impl From for jong_types::Dragon { + fn from(value: stdb::Dragon) -> Self { + Self::from_repr(value as usize).unwrap() + } +} diff --git a/jong/src/stdb/add_player_reducer.rs b/jong/src/stdb/add_player_reducer.rs deleted file mode 100644 index 757a0b6..0000000 --- a/jong/src/stdb/add_player_reducer.rs +++ /dev/null @@ -1,102 +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(super) struct AddPlayerArgs { - pub name: Option, -} - -impl From for super::Reducer { - fn from(args: AddPlayerArgs) -> Self { - Self::AddPlayer { name: args.name } - } -} - -impl __sdk::InModule for AddPlayerArgs { - type Module = super::RemoteModule; -} - -pub struct AddPlayerCallbackId(__sdk::CallbackId); - -#[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `add_player`. -/// -/// Implemented for [`super::RemoteReducers`]. -pub trait add_player { - /// Request that the remote module invoke the reducer `add_player` to run as soon as possible. - /// - /// This method returns immediately, and errors only if we are unable to send the request. - /// The reducer will run asynchronously in the future, - /// and its status can be observed by listening for [`Self::on_add_player`] callbacks. - fn add_player(&self, name: Option) -> __sdk::Result<()>; - /// Register a callback to run whenever we are notified of an invocation of the reducer `add_player`. - /// - /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] - /// to determine the reducer's status. - /// - /// The returned [`AddPlayerCallbackId`] can be passed to [`Self::remove_on_add_player`] - /// to cancel the callback. - fn on_add_player( - &self, - callback: impl FnMut(&super::ReducerEventContext, &Option) + Send + 'static, - ) -> AddPlayerCallbackId; - /// Cancel a callback previously registered by [`Self::on_add_player`], - /// causing it not to run in the future. - fn remove_on_add_player(&self, callback: AddPlayerCallbackId); -} - -impl add_player for super::RemoteReducers { - fn add_player(&self, name: Option) -> __sdk::Result<()> { - self.imp.call_reducer("add_player", AddPlayerArgs { name }) - } - fn on_add_player( - &self, - mut callback: impl FnMut(&super::ReducerEventContext, &Option) + Send + 'static, - ) -> AddPlayerCallbackId { - AddPlayerCallbackId(self.imp.on_reducer( - "add_player", - Box::new(move |ctx: &super::ReducerEventContext| { - #[allow(irrefutable_let_patterns)] - let super::ReducerEventContext { - event: - __sdk::ReducerEvent { - reducer: super::Reducer::AddPlayer { name }, - .. - }, - .. - } = ctx - else { - unreachable!() - }; - callback(ctx, name) - }), - )) - } - fn remove_on_add_player(&self, callback: AddPlayerCallbackId) { - self.imp.remove_on_reducer("add_player", callback.0) - } -} - -#[allow(non_camel_case_types)] -#[doc(hidden)] -/// Extension trait for setting the call-flags for the reducer `add_player`. -/// -/// Implemented for [`super::SetReducerFlags`]. -/// -/// This type is currently unstable and may be removed without a major version bump. -pub trait set_flags_for_add_player { - /// Set the call-reducer flags for the reducer `add_player` to `flags`. - /// - /// This type is currently unstable and may be removed without a major version bump. - fn add_player(&self, flags: __ws::CallReducerFlags); -} - -impl set_flags_for_add_player for super::SetReducerFlags { - fn add_player(&self, flags: __ws::CallReducerFlags) { - self.imp.set_call_reducer_flags("add_player", flags); - } -} diff --git a/jong/src/stdb/bot_type.rs b/jong/src/stdb/bot_type.rs index ba15e53..0d4fd2c 100644 --- a/jong/src/stdb/bot_type.rs +++ b/jong/src/stdb/bot_type.rs @@ -9,6 +9,8 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; pub struct Bot { pub id: u32, pub lobby_id: u32, + pub hand_id: u32, + pub pond_id: u32, } impl __sdk::InModule for Bot { diff --git a/jong/src/stdb/bothand_table.rs b/jong/src/stdb/bothand_table.rs deleted file mode 100644 index b2307c4..0000000 --- a/jong/src/stdb/bothand_table.rs +++ /dev/null @@ -1,143 +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::bot_hand_type::BotHand; -use super::tile_type::Tile; -use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; - -/// Table handle for the table `bothand`. -/// -/// Obtain a handle from the [`BothandTableAccess::bothand`] method on [`super::RemoteTables`], -/// like `ctx.db.bothand()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.bothand().on_insert(...)`. -pub struct BothandTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `bothand`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait BothandTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`BothandTableHandle`], which mediates access to the table `bothand`. - fn bothand(&self) -> BothandTableHandle<'_>; -} - -impl BothandTableAccess for super::RemoteTables { - fn bothand(&self) -> BothandTableHandle<'_> { - BothandTableHandle { - imp: self.imp.get_table::("bothand"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct BothandInsertCallbackId(__sdk::CallbackId); -pub struct BothandDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for BothandTableHandle<'ctx> { - type Row = BotHand; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { - self.imp.count() - } - fn iter(&self) -> impl Iterator + '_ { - self.imp.iter() - } - - type InsertCallbackId = BothandInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> BothandInsertCallbackId { - BothandInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: BothandInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = BothandDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> BothandDeleteCallbackId { - BothandDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: BothandDeleteCallbackId) { - 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::("bothand"); - _table.add_unique_constraint::("bot_id", |row| &row.bot_id); -} -pub struct BothandUpdateCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::TableWithPrimaryKey for BothandTableHandle<'ctx> { - type UpdateCallbackId = BothandUpdateCallbackId; - - fn on_update( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, - ) -> BothandUpdateCallbackId { - BothandUpdateCallbackId(self.imp.on_update(Box::new(callback))) - } - - fn remove_on_update(&self, callback: BothandUpdateCallbackId) { - 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 `bot_id` unique index on the table `bothand`, -/// which allows point queries on the field of the same name -/// via the [`BothandBotIdUnique::find`] method. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.bothand().bot_id().find(...)`. -pub struct BothandBotIdUnique<'ctx> { - imp: __sdk::UniqueConstraintHandle, - phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -impl<'ctx> BothandTableHandle<'ctx> { - /// Get a handle on the `bot_id` unique index on the table `bothand`. - pub fn bot_id(&self) -> BothandBotIdUnique<'ctx> { - BothandBotIdUnique { - imp: self.imp.get_unique_constraint::("bot_id"), - phantom: std::marker::PhantomData, - } - } -} - -impl<'ctx> BothandBotIdUnique<'ctx> { - /// Find the subscribed row whose `bot_id` column value is equal to `col_val`, - /// if such a row is present in the client cache. - pub fn find(&self, col_val: &u32) -> Option { - self.imp.find(col_val) - } -} diff --git a/jong/src/stdb/deal_hands_reducer.rs b/jong/src/stdb/deal_hands_reducer.rs deleted file mode 100644 index cb67ec4..0000000 --- a/jong/src/stdb/deal_hands_reducer.rs +++ /dev/null @@ -1,100 +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(super) struct DealHandsArgs {} - -impl From for super::Reducer { - fn from(args: DealHandsArgs) -> Self { - Self::DealHands - } -} - -impl __sdk::InModule for DealHandsArgs { - type Module = super::RemoteModule; -} - -pub struct DealHandsCallbackId(__sdk::CallbackId); - -#[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `deal_hands`. -/// -/// Implemented for [`super::RemoteReducers`]. -pub trait deal_hands { - /// Request that the remote module invoke the reducer `deal_hands` to run as soon as possible. - /// - /// This method returns immediately, and errors only if we are unable to send the request. - /// The reducer will run asynchronously in the future, - /// and its status can be observed by listening for [`Self::on_deal_hands`] callbacks. - fn deal_hands(&self) -> __sdk::Result<()>; - /// Register a callback to run whenever we are notified of an invocation of the reducer `deal_hands`. - /// - /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] - /// to determine the reducer's status. - /// - /// The returned [`DealHandsCallbackId`] can be passed to [`Self::remove_on_deal_hands`] - /// to cancel the callback. - fn on_deal_hands( - &self, - callback: impl FnMut(&super::ReducerEventContext) + Send + 'static, - ) -> DealHandsCallbackId; - /// Cancel a callback previously registered by [`Self::on_deal_hands`], - /// causing it not to run in the future. - fn remove_on_deal_hands(&self, callback: DealHandsCallbackId); -} - -impl deal_hands for super::RemoteReducers { - fn deal_hands(&self) -> __sdk::Result<()> { - self.imp.call_reducer("deal_hands", DealHandsArgs {}) - } - fn on_deal_hands( - &self, - mut callback: impl FnMut(&super::ReducerEventContext) + Send + 'static, - ) -> DealHandsCallbackId { - DealHandsCallbackId(self.imp.on_reducer( - "deal_hands", - Box::new(move |ctx: &super::ReducerEventContext| { - #[allow(irrefutable_let_patterns)] - let super::ReducerEventContext { - event: - __sdk::ReducerEvent { - reducer: super::Reducer::DealHands {}, - .. - }, - .. - } = ctx - else { - unreachable!() - }; - callback(ctx) - }), - )) - } - fn remove_on_deal_hands(&self, callback: DealHandsCallbackId) { - self.imp.remove_on_reducer("deal_hands", callback.0) - } -} - -#[allow(non_camel_case_types)] -#[doc(hidden)] -/// Extension trait for setting the call-flags for the reducer `deal_hands`. -/// -/// Implemented for [`super::SetReducerFlags`]. -/// -/// This type is currently unstable and may be removed without a major version bump. -pub trait set_flags_for_deal_hands { - /// Set the call-reducer flags for the reducer `deal_hands` to `flags`. - /// - /// This type is currently unstable and may be removed without a major version bump. - fn deal_hands(&self, flags: __ws::CallReducerFlags); -} - -impl set_flags_for_deal_hands for super::SetReducerFlags { - fn deal_hands(&self, flags: __ws::CallReducerFlags) { - self.imp.set_call_reducer_flags("deal_hands", flags); - } -} diff --git a/jong/src/stdb/hand_table.rs b/jong/src/stdb/hand_table.rs index e72e3a0..d967559 100644 --- a/jong/src/stdb/hand_table.rs +++ b/jong/src/stdb/hand_table.rs @@ -3,6 +3,7 @@ #![allow(unused, clippy::all)] use super::hand_type::Hand; +use super::player_or_bot_type::PlayerOrBot; use super::tile_type::Tile; use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; @@ -82,7 +83,7 @@ impl<'ctx> __sdk::Table for HandTableHandle<'ctx> { #[doc(hidden)] pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { let _table = client_cache.get_or_make_table::("hand"); - _table.add_unique_constraint::<__sdk::Identity>("player_identity", |row| &row.player_identity); + _table.add_unique_constraint::("id", |row| &row.id); } pub struct HandUpdateCallbackId(__sdk::CallbackId); @@ -112,34 +113,32 @@ pub(super) fn parse_table_update( }) } -/// Access to the `player_identity` unique index on the table `hand`, +/// Access to the `id` unique index on the table `hand`, /// which allows point queries on the field of the same name -/// via the [`HandPlayerIdentityUnique::find`] method. +/// via the [`HandIdUnique::find`] method. /// /// Users are encouraged not to explicitly reference this type, /// but to directly chain method calls, -/// like `ctx.db.hand().player_identity().find(...)`. -pub struct HandPlayerIdentityUnique<'ctx> { - imp: __sdk::UniqueConstraintHandle, +/// like `ctx.db.hand().id().find(...)`. +pub struct HandIdUnique<'ctx> { + imp: __sdk::UniqueConstraintHandle, phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, } impl<'ctx> HandTableHandle<'ctx> { - /// Get a handle on the `player_identity` unique index on the table `hand`. - pub fn player_identity(&self) -> HandPlayerIdentityUnique<'ctx> { - HandPlayerIdentityUnique { - imp: self - .imp - .get_unique_constraint::<__sdk::Identity>("player_identity"), + /// Get a handle on the `id` unique index on the table `hand`. + pub fn id(&self) -> HandIdUnique<'ctx> { + HandIdUnique { + imp: self.imp.get_unique_constraint::("id"), phantom: std::marker::PhantomData, } } } -impl<'ctx> HandPlayerIdentityUnique<'ctx> { - /// Find the subscribed row whose `player_identity` column value is equal to `col_val`, +impl<'ctx> HandIdUnique<'ctx> { + /// Find the subscribed row whose `id` column value is equal to `col_val`, /// if such a row is present in the client cache. - pub fn find(&self, col_val: &__sdk::Identity) -> Option { + pub fn find(&self, col_val: &u32) -> Option { self.imp.find(col_val) } } diff --git a/jong/src/stdb/hand_type.rs b/jong/src/stdb/hand_type.rs index 427b7c6..2c4f86b 100644 --- a/jong/src/stdb/hand_type.rs +++ b/jong/src/stdb/hand_type.rs @@ -4,12 +4,15 @@ #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; +use super::player_or_bot_type::PlayerOrBot; use super::tile_type::Tile; #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] #[sats(crate = __lib)] pub struct Hand { - pub player_identity: __sdk::Identity, + pub id: u32, + pub owner: PlayerOrBot, + pub sort: bool, pub tiles: Vec, } diff --git a/jong/src/stdb/insert_wall_reducer.rs b/jong/src/stdb/insert_wall_reducer.rs deleted file mode 100644 index 2189dae..0000000 --- a/jong/src/stdb/insert_wall_reducer.rs +++ /dev/null @@ -1,105 +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(super) struct InsertWallArgs { - pub player_ids: Vec, -} - -impl From for super::Reducer { - fn from(args: InsertWallArgs) -> Self { - Self::InsertWall { - player_ids: args.player_ids, - } - } -} - -impl __sdk::InModule for InsertWallArgs { - type Module = super::RemoteModule; -} - -pub struct InsertWallCallbackId(__sdk::CallbackId); - -#[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `insert_wall`. -/// -/// Implemented for [`super::RemoteReducers`]. -pub trait insert_wall { - /// Request that the remote module invoke the reducer `insert_wall` to run as soon as possible. - /// - /// This method returns immediately, and errors only if we are unable to send the request. - /// The reducer will run asynchronously in the future, - /// and its status can be observed by listening for [`Self::on_insert_wall`] callbacks. - fn insert_wall(&self, player_ids: Vec) -> __sdk::Result<()>; - /// Register a callback to run whenever we are notified of an invocation of the reducer `insert_wall`. - /// - /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] - /// to determine the reducer's status. - /// - /// The returned [`InsertWallCallbackId`] can be passed to [`Self::remove_on_insert_wall`] - /// to cancel the callback. - fn on_insert_wall( - &self, - callback: impl FnMut(&super::ReducerEventContext, &Vec) + Send + 'static, - ) -> InsertWallCallbackId; - /// Cancel a callback previously registered by [`Self::on_insert_wall`], - /// causing it not to run in the future. - fn remove_on_insert_wall(&self, callback: InsertWallCallbackId); -} - -impl insert_wall for super::RemoteReducers { - fn insert_wall(&self, player_ids: Vec) -> __sdk::Result<()> { - self.imp - .call_reducer("insert_wall", InsertWallArgs { player_ids }) - } - fn on_insert_wall( - &self, - mut callback: impl FnMut(&super::ReducerEventContext, &Vec) + Send + 'static, - ) -> InsertWallCallbackId { - InsertWallCallbackId(self.imp.on_reducer( - "insert_wall", - Box::new(move |ctx: &super::ReducerEventContext| { - #[allow(irrefutable_let_patterns)] - let super::ReducerEventContext { - event: - __sdk::ReducerEvent { - reducer: super::Reducer::InsertWall { player_ids }, - .. - }, - .. - } = ctx - else { - unreachable!() - }; - callback(ctx, player_ids) - }), - )) - } - fn remove_on_insert_wall(&self, callback: InsertWallCallbackId) { - self.imp.remove_on_reducer("insert_wall", callback.0) - } -} - -#[allow(non_camel_case_types)] -#[doc(hidden)] -/// Extension trait for setting the call-flags for the reducer `insert_wall`. -/// -/// Implemented for [`super::SetReducerFlags`]. -/// -/// This type is currently unstable and may be removed without a major version bump. -pub trait set_flags_for_insert_wall { - /// Set the call-reducer flags for the reducer `insert_wall` to `flags`. - /// - /// This type is currently unstable and may be removed without a major version bump. - fn insert_wall(&self, flags: __ws::CallReducerFlags); -} - -impl set_flags_for_insert_wall for super::SetReducerFlags { - fn insert_wall(&self, flags: __ws::CallReducerFlags) { - self.imp.set_call_reducer_flags("insert_wall", flags); - } -} diff --git a/jong/src/stdb/lobby_setup_reducer.rs b/jong/src/stdb/lobby_setup_reducer.rs deleted file mode 100644 index c54de7d..0000000 --- a/jong/src/stdb/lobby_setup_reducer.rs +++ /dev/null @@ -1,100 +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(super) struct LobbySetupArgs {} - -impl From for super::Reducer { - fn from(args: LobbySetupArgs) -> Self { - Self::LobbySetup - } -} - -impl __sdk::InModule for LobbySetupArgs { - type Module = super::RemoteModule; -} - -pub struct LobbySetupCallbackId(__sdk::CallbackId); - -#[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `lobby_setup`. -/// -/// Implemented for [`super::RemoteReducers`]. -pub trait lobby_setup { - /// Request that the remote module invoke the reducer `lobby_setup` to run as soon as possible. - /// - /// This method returns immediately, and errors only if we are unable to send the request. - /// The reducer will run asynchronously in the future, - /// and its status can be observed by listening for [`Self::on_lobby_setup`] callbacks. - fn lobby_setup(&self) -> __sdk::Result<()>; - /// Register a callback to run whenever we are notified of an invocation of the reducer `lobby_setup`. - /// - /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] - /// to determine the reducer's status. - /// - /// The returned [`LobbySetupCallbackId`] can be passed to [`Self::remove_on_lobby_setup`] - /// to cancel the callback. - fn on_lobby_setup( - &self, - callback: impl FnMut(&super::ReducerEventContext) + Send + 'static, - ) -> LobbySetupCallbackId; - /// Cancel a callback previously registered by [`Self::on_lobby_setup`], - /// causing it not to run in the future. - fn remove_on_lobby_setup(&self, callback: LobbySetupCallbackId); -} - -impl lobby_setup for super::RemoteReducers { - fn lobby_setup(&self) -> __sdk::Result<()> { - self.imp.call_reducer("lobby_setup", LobbySetupArgs {}) - } - fn on_lobby_setup( - &self, - mut callback: impl FnMut(&super::ReducerEventContext) + Send + 'static, - ) -> LobbySetupCallbackId { - LobbySetupCallbackId(self.imp.on_reducer( - "lobby_setup", - Box::new(move |ctx: &super::ReducerEventContext| { - #[allow(irrefutable_let_patterns)] - let super::ReducerEventContext { - event: - __sdk::ReducerEvent { - reducer: super::Reducer::LobbySetup {}, - .. - }, - .. - } = ctx - else { - unreachable!() - }; - callback(ctx) - }), - )) - } - fn remove_on_lobby_setup(&self, callback: LobbySetupCallbackId) { - self.imp.remove_on_reducer("lobby_setup", callback.0) - } -} - -#[allow(non_camel_case_types)] -#[doc(hidden)] -/// Extension trait for setting the call-flags for the reducer `lobby_setup`. -/// -/// Implemented for [`super::SetReducerFlags`]. -/// -/// This type is currently unstable and may be removed without a major version bump. -pub trait set_flags_for_lobby_setup { - /// Set the call-reducer flags for the reducer `lobby_setup` to `flags`. - /// - /// This type is currently unstable and may be removed without a major version bump. - fn lobby_setup(&self, flags: __ws::CallReducerFlags); -} - -impl set_flags_for_lobby_setup for super::SetReducerFlags { - fn lobby_setup(&self, flags: __ws::CallReducerFlags) { - self.imp.set_call_reducer_flags("lobby_setup", flags); - } -} diff --git a/jong/src/stdb/lobby_table.rs b/jong/src/stdb/lobby_table.rs index 4249c91..ab1d881 100644 --- a/jong/src/stdb/lobby_table.rs +++ b/jong/src/stdb/lobby_table.rs @@ -4,6 +4,7 @@ #![allow(unused, clippy::all)] use super::game_state_type::GameState; use super::lobby_type::Lobby; +use super::player_or_bot_type::PlayerOrBot; use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; /// Table handle for the table `lobby`. diff --git a/jong/src/stdb/lobby_type.rs b/jong/src/stdb/lobby_type.rs index 8d7b094..110a274 100644 --- a/jong/src/stdb/lobby_type.rs +++ b/jong/src/stdb/lobby_type.rs @@ -5,12 +5,14 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; use super::game_state_type::GameState; +use super::player_or_bot_type::PlayerOrBot; #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] #[sats(crate = __lib)] pub struct Lobby { pub id: u32, pub host_player_id: u32, + pub players: Vec, pub game_state: GameState, } diff --git a/jong/src/stdb/mod.rs b/jong/src/stdb/mod.rs index 888635d..6c87060 100644 --- a/jong/src/stdb/mod.rs +++ b/jong/src/stdb/mod.rs @@ -7,10 +7,8 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; pub mod add_bot_reducer; -pub mod bot_hand_type; pub mod bot_table; pub mod bot_type; -pub mod bothand_table; pub mod dragon_type; pub mod game_state_type; pub mod hand_table; @@ -19,13 +17,13 @@ pub mod join_or_create_lobby_reducer; pub mod lobby_table; pub mod lobby_type; pub mod login_or_add_player_reducer; +pub mod player_or_bot_type; pub mod player_table; pub mod player_type; pub mod pond_table; pub mod pond_type; pub mod rank_type; -pub mod setup_game_reducer; -pub mod sort_hand_reducer; +pub mod shuffle_deal_reducer; pub mod suit_type; pub mod tile_type; pub mod view_player_hand_table; @@ -34,10 +32,8 @@ pub mod wall_type; pub mod wind_type; pub use add_bot_reducer::{add_bot, set_flags_for_add_bot, AddBotCallbackId}; -pub use bot_hand_type::BotHand; pub use bot_table::*; pub use bot_type::Bot; -pub use bothand_table::*; pub use dragon_type::Dragon; pub use game_state_type::GameState; pub use hand_table::*; @@ -50,13 +46,13 @@ pub use lobby_type::Lobby; pub use login_or_add_player_reducer::{ login_or_add_player, set_flags_for_login_or_add_player, LoginOrAddPlayerCallbackId, }; +pub use player_or_bot_type::PlayerOrBot; pub use player_table::*; pub use player_type::Player; pub use pond_table::*; pub use pond_type::Pond; pub use rank_type::Rank; -pub use setup_game_reducer::{set_flags_for_setup_game, setup_game, SetupGameCallbackId}; -pub use sort_hand_reducer::{set_flags_for_sort_hand, sort_hand, SortHandCallbackId}; +pub use shuffle_deal_reducer::{set_flags_for_shuffle_deal, shuffle_deal, ShuffleDealCallbackId}; pub use suit_type::Suit; pub use tile_type::Tile; pub use view_player_hand_table::*; @@ -75,8 +71,7 @@ pub enum Reducer { AddBot { lobby_id: u32 }, JoinOrCreateLobby { lobby_id: u32 }, LoginOrAddPlayer, - SetupGame { lobby_id: u32 }, - SortHand, + ShuffleDeal { lobby_id: u32 }, } impl __sdk::InModule for Reducer { @@ -89,8 +84,7 @@ impl __sdk::Reducer for Reducer { Reducer::AddBot { .. } => "add_bot", Reducer::JoinOrCreateLobby { .. } => "join_or_create_lobby", Reducer::LoginOrAddPlayer => "login_or_add_player", - Reducer::SetupGame { .. } => "setup_game", - Reducer::SortHand => "sort_hand", + Reducer::ShuffleDeal { .. } => "shuffle_deal", _ => unreachable!(), } } @@ -112,16 +106,9 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer { login_or_add_player_reducer::LoginOrAddPlayerArgs, >("login_or_add_player", &value.args)? .into()), - "setup_game" => Ok( - __sdk::parse_reducer_args::( - "setup_game", - &value.args, - )? - .into(), - ), - "sort_hand" => Ok( - __sdk::parse_reducer_args::( - "sort_hand", + "shuffle_deal" => Ok( + __sdk::parse_reducer_args::( + "shuffle_deal", &value.args, )? .into(), @@ -141,7 +128,6 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer { #[doc(hidden)] pub struct DbUpdate { bot: __sdk::TableUpdate, - bothand: __sdk::TableUpdate, hand: __sdk::TableUpdate, lobby: __sdk::TableUpdate, player: __sdk::TableUpdate, @@ -159,9 +145,6 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { "bot" => db_update .bot .append(bot_table::parse_table_update(table_update)?), - "bothand" => db_update - .bothand - .append(bothand_table::parse_table_update(table_update)?), "hand" => db_update .hand .append(hand_table::parse_table_update(table_update)?), @@ -209,19 +192,18 @@ impl __sdk::DbUpdate for DbUpdate { diff.bot = cache .apply_diff_to_table::("bot", &self.bot) .with_updates_by_pk(|row| &row.id); - diff.bothand = cache - .apply_diff_to_table::("bothand", &self.bothand) - .with_updates_by_pk(|row| &row.bot_id); diff.hand = cache .apply_diff_to_table::("hand", &self.hand) - .with_updates_by_pk(|row| &row.player_identity); + .with_updates_by_pk(|row| &row.id); diff.lobby = cache .apply_diff_to_table::("lobby", &self.lobby) .with_updates_by_pk(|row| &row.id); diff.player = cache .apply_diff_to_table::("player", &self.player) .with_updates_by_pk(|row| &row.identity); - diff.pond = cache.apply_diff_to_table::("pond", &self.pond); + diff.pond = cache + .apply_diff_to_table::("pond", &self.pond) + .with_updates_by_pk(|row| &row.id); diff.wall = cache .apply_diff_to_table::("wall", &self.wall) .with_updates_by_pk(|row| &row.lobby_id); @@ -237,7 +219,6 @@ impl __sdk::DbUpdate for DbUpdate { #[doc(hidden)] pub struct AppliedDiff<'r> { bot: __sdk::TableAppliedDiff<'r, Bot>, - bothand: __sdk::TableAppliedDiff<'r, BotHand>, hand: __sdk::TableAppliedDiff<'r, Hand>, lobby: __sdk::TableAppliedDiff<'r, Lobby>, player: __sdk::TableAppliedDiff<'r, Player>, @@ -258,7 +239,6 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> { callbacks: &mut __sdk::DbCallbacks, ) { callbacks.invoke_table_row_callbacks::("bot", &self.bot, event); - callbacks.invoke_table_row_callbacks::("bothand", &self.bothand, event); callbacks.invoke_table_row_callbacks::("hand", &self.hand, event); callbacks.invoke_table_row_callbacks::("lobby", &self.lobby, event); callbacks.invoke_table_row_callbacks::("player", &self.player, event); @@ -989,7 +969,6 @@ impl __sdk::SpacetimeModule for RemoteModule { fn register_tables(client_cache: &mut __sdk::ClientCache) { bot_table::register_table(client_cache); - bothand_table::register_table(client_cache); hand_table::register_table(client_cache); lobby_table::register_table(client_cache); player_table::register_table(client_cache); diff --git a/jong/src/stdb/bot_hand_type.rs b/jong/src/stdb/player_or_bot_type.rs similarity index 75% rename from jong/src/stdb/bot_hand_type.rs rename to jong/src/stdb/player_or_bot_type.rs index d2aeefb..538d940 100644 --- a/jong/src/stdb/bot_hand_type.rs +++ b/jong/src/stdb/player_or_bot_type.rs @@ -4,15 +4,14 @@ #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; -use super::tile_type::Tile; - #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] #[sats(crate = __lib)] -pub struct BotHand { - pub bot_id: u32, - pub tiles: Vec, +pub enum PlayerOrBot { + Player(u32), + + Bot(u32), } -impl __sdk::InModule for BotHand { +impl __sdk::InModule for PlayerOrBot { type Module = super::RemoteModule; } diff --git a/jong/src/stdb/player_type.rs b/jong/src/stdb/player_type.rs index 278ed9e..0e651ec 100644 --- a/jong/src/stdb/player_type.rs +++ b/jong/src/stdb/player_type.rs @@ -11,6 +11,8 @@ pub struct Player { pub id: u32, pub name: Option, pub lobby_id: u32, + pub hand_id: u32, + pub pond_id: u32, } impl __sdk::InModule for Player { diff --git a/jong/src/stdb/pond_table.rs b/jong/src/stdb/pond_table.rs index 0230d77..9f079c2 100644 --- a/jong/src/stdb/pond_table.rs +++ b/jong/src/stdb/pond_table.rs @@ -2,6 +2,7 @@ // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. #![allow(unused, clippy::all)] +use super::player_or_bot_type::PlayerOrBot; use super::pond_type::Pond; use super::tile_type::Tile; use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; @@ -82,6 +83,23 @@ impl<'ctx> __sdk::Table for PondTableHandle<'ctx> { #[doc(hidden)] pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { let _table = client_cache.get_or_make_table::("pond"); + _table.add_unique_constraint::("id", |row| &row.id); +} +pub struct PondUpdateCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::TableWithPrimaryKey for PondTableHandle<'ctx> { + type UpdateCallbackId = PondUpdateCallbackId; + + fn on_update( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, + ) -> PondUpdateCallbackId { + PondUpdateCallbackId(self.imp.on_update(Box::new(callback))) + } + + fn remove_on_update(&self, callback: PondUpdateCallbackId) { + self.imp.remove_on_update(callback.0) + } } #[doc(hidden)] @@ -94,3 +112,33 @@ pub(super) fn parse_table_update( .into() }) } + +/// Access to the `id` unique index on the table `pond`, +/// which allows point queries on the field of the same name +/// via the [`PondIdUnique::find`] method. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.pond().id().find(...)`. +pub struct PondIdUnique<'ctx> { + imp: __sdk::UniqueConstraintHandle, + phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +impl<'ctx> PondTableHandle<'ctx> { + /// Get a handle on the `id` unique index on the table `pond`. + pub fn id(&self) -> PondIdUnique<'ctx> { + PondIdUnique { + imp: self.imp.get_unique_constraint::("id"), + phantom: std::marker::PhantomData, + } + } +} + +impl<'ctx> PondIdUnique<'ctx> { + /// Find the subscribed row whose `id` column value is equal to `col_val`, + /// if such a row is present in the client cache. + pub fn find(&self, col_val: &u32) -> Option { + self.imp.find(col_val) + } +} diff --git a/jong/src/stdb/pond_type.rs b/jong/src/stdb/pond_type.rs index 3cfbd3e..bf08228 100644 --- a/jong/src/stdb/pond_type.rs +++ b/jong/src/stdb/pond_type.rs @@ -4,11 +4,14 @@ #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; +use super::player_or_bot_type::PlayerOrBot; use super::tile_type::Tile; #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] #[sats(crate = __lib)] pub struct Pond { + pub id: u32, + pub owner: PlayerOrBot, pub tiles: Vec, } diff --git a/jong/src/stdb/set_name_reducer.rs b/jong/src/stdb/set_name_reducer.rs deleted file mode 100644 index cc9905d..0000000 --- a/jong/src/stdb/set_name_reducer.rs +++ /dev/null @@ -1,102 +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(super) struct SetNameArgs { - pub name: String, -} - -impl From for super::Reducer { - fn from(args: SetNameArgs) -> Self { - Self::SetName { name: args.name } - } -} - -impl __sdk::InModule for SetNameArgs { - type Module = super::RemoteModule; -} - -pub struct SetNameCallbackId(__sdk::CallbackId); - -#[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `set_name`. -/// -/// Implemented for [`super::RemoteReducers`]. -pub trait set_name { - /// Request that the remote module invoke the reducer `set_name` to run as soon as possible. - /// - /// This method returns immediately, and errors only if we are unable to send the request. - /// The reducer will run asynchronously in the future, - /// and its status can be observed by listening for [`Self::on_set_name`] callbacks. - fn set_name(&self, name: String) -> __sdk::Result<()>; - /// Register a callback to run whenever we are notified of an invocation of the reducer `set_name`. - /// - /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] - /// to determine the reducer's status. - /// - /// The returned [`SetNameCallbackId`] can be passed to [`Self::remove_on_set_name`] - /// to cancel the callback. - fn on_set_name( - &self, - callback: impl FnMut(&super::ReducerEventContext, &String) + Send + 'static, - ) -> SetNameCallbackId; - /// Cancel a callback previously registered by [`Self::on_set_name`], - /// causing it not to run in the future. - fn remove_on_set_name(&self, callback: SetNameCallbackId); -} - -impl set_name for super::RemoteReducers { - fn set_name(&self, name: String) -> __sdk::Result<()> { - self.imp.call_reducer("set_name", SetNameArgs { name }) - } - fn on_set_name( - &self, - mut callback: impl FnMut(&super::ReducerEventContext, &String) + Send + 'static, - ) -> SetNameCallbackId { - SetNameCallbackId(self.imp.on_reducer( - "set_name", - Box::new(move |ctx: &super::ReducerEventContext| { - #[allow(irrefutable_let_patterns)] - let super::ReducerEventContext { - event: - __sdk::ReducerEvent { - reducer: super::Reducer::SetName { name }, - .. - }, - .. - } = ctx - else { - unreachable!() - }; - callback(ctx, name) - }), - )) - } - fn remove_on_set_name(&self, callback: SetNameCallbackId) { - self.imp.remove_on_reducer("set_name", callback.0) - } -} - -#[allow(non_camel_case_types)] -#[doc(hidden)] -/// Extension trait for setting the call-flags for the reducer `set_name`. -/// -/// Implemented for [`super::SetReducerFlags`]. -/// -/// This type is currently unstable and may be removed without a major version bump. -pub trait set_flags_for_set_name { - /// Set the call-reducer flags for the reducer `set_name` to `flags`. - /// - /// This type is currently unstable and may be removed without a major version bump. - fn set_name(&self, flags: __ws::CallReducerFlags); -} - -impl set_flags_for_set_name for super::SetReducerFlags { - fn set_name(&self, flags: __ws::CallReducerFlags) { - self.imp.set_call_reducer_flags("set_name", flags); - } -} diff --git a/jong/src/stdb/setup_game_reducer.rs b/jong/src/stdb/shuffle_deal_reducer.rs similarity index 54% rename from jong/src/stdb/setup_game_reducer.rs rename to jong/src/stdb/shuffle_deal_reducer.rs index 3380b89..06b1b23 100644 --- a/jong/src/stdb/setup_game_reducer.rs +++ b/jong/src/stdb/shuffle_deal_reducer.rs @@ -6,68 +6,68 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] #[sats(crate = __lib)] -pub(super) struct SetupGameArgs { +pub(super) struct ShuffleDealArgs { pub lobby_id: u32, } -impl From for super::Reducer { - fn from(args: SetupGameArgs) -> Self { - Self::SetupGame { +impl From for super::Reducer { + fn from(args: ShuffleDealArgs) -> Self { + Self::ShuffleDeal { lobby_id: args.lobby_id, } } } -impl __sdk::InModule for SetupGameArgs { +impl __sdk::InModule for ShuffleDealArgs { type Module = super::RemoteModule; } -pub struct SetupGameCallbackId(__sdk::CallbackId); +pub struct ShuffleDealCallbackId(__sdk::CallbackId); #[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `setup_game`. +/// Extension trait for access to the reducer `shuffle_deal`. /// /// Implemented for [`super::RemoteReducers`]. -pub trait setup_game { - /// Request that the remote module invoke the reducer `setup_game` to run as soon as possible. +pub trait shuffle_deal { + /// Request that the remote module invoke the reducer `shuffle_deal` to run as soon as possible. /// /// This method returns immediately, and errors only if we are unable to send the request. /// The reducer will run asynchronously in the future, - /// and its status can be observed by listening for [`Self::on_setup_game`] callbacks. - fn setup_game(&self, lobby_id: u32) -> __sdk::Result<()>; - /// Register a callback to run whenever we are notified of an invocation of the reducer `setup_game`. + /// and its status can be observed by listening for [`Self::on_shuffle_deal`] callbacks. + fn shuffle_deal(&self, lobby_id: u32) -> __sdk::Result<()>; + /// Register a callback to run whenever we are notified of an invocation of the reducer `shuffle_deal`. /// /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] /// to determine the reducer's status. /// - /// The returned [`SetupGameCallbackId`] can be passed to [`Self::remove_on_setup_game`] + /// The returned [`ShuffleDealCallbackId`] can be passed to [`Self::remove_on_shuffle_deal`] /// to cancel the callback. - fn on_setup_game( + fn on_shuffle_deal( &self, callback: impl FnMut(&super::ReducerEventContext, &u32) + Send + 'static, - ) -> SetupGameCallbackId; - /// Cancel a callback previously registered by [`Self::on_setup_game`], + ) -> ShuffleDealCallbackId; + /// Cancel a callback previously registered by [`Self::on_shuffle_deal`], /// causing it not to run in the future. - fn remove_on_setup_game(&self, callback: SetupGameCallbackId); + fn remove_on_shuffle_deal(&self, callback: ShuffleDealCallbackId); } -impl setup_game for super::RemoteReducers { - fn setup_game(&self, lobby_id: u32) -> __sdk::Result<()> { +impl shuffle_deal for super::RemoteReducers { + fn shuffle_deal(&self, lobby_id: u32) -> __sdk::Result<()> { self.imp - .call_reducer("setup_game", SetupGameArgs { lobby_id }) + .call_reducer("shuffle_deal", ShuffleDealArgs { lobby_id }) } - fn on_setup_game( + fn on_shuffle_deal( &self, mut callback: impl FnMut(&super::ReducerEventContext, &u32) + Send + 'static, - ) -> SetupGameCallbackId { - SetupGameCallbackId(self.imp.on_reducer( - "setup_game", + ) -> ShuffleDealCallbackId { + ShuffleDealCallbackId(self.imp.on_reducer( + "shuffle_deal", Box::new(move |ctx: &super::ReducerEventContext| { #[allow(irrefutable_let_patterns)] let super::ReducerEventContext { event: __sdk::ReducerEvent { - reducer: super::Reducer::SetupGame { lobby_id }, + reducer: super::Reducer::ShuffleDeal { lobby_id }, .. }, .. @@ -79,27 +79,27 @@ impl setup_game for super::RemoteReducers { }), )) } - fn remove_on_setup_game(&self, callback: SetupGameCallbackId) { - self.imp.remove_on_reducer("setup_game", callback.0) + fn remove_on_shuffle_deal(&self, callback: ShuffleDealCallbackId) { + self.imp.remove_on_reducer("shuffle_deal", callback.0) } } #[allow(non_camel_case_types)] #[doc(hidden)] -/// Extension trait for setting the call-flags for the reducer `setup_game`. +/// Extension trait for setting the call-flags for the reducer `shuffle_deal`. /// /// Implemented for [`super::SetReducerFlags`]. /// /// This type is currently unstable and may be removed without a major version bump. -pub trait set_flags_for_setup_game { - /// Set the call-reducer flags for the reducer `setup_game` to `flags`. +pub trait set_flags_for_shuffle_deal { + /// Set the call-reducer flags for the reducer `shuffle_deal` to `flags`. /// /// This type is currently unstable and may be removed without a major version bump. - fn setup_game(&self, flags: __ws::CallReducerFlags); + fn shuffle_deal(&self, flags: __ws::CallReducerFlags); } -impl set_flags_for_setup_game for super::SetReducerFlags { - fn setup_game(&self, flags: __ws::CallReducerFlags) { - self.imp.set_call_reducer_flags("setup_game", flags); +impl set_flags_for_shuffle_deal for super::SetReducerFlags { + fn shuffle_deal(&self, flags: __ws::CallReducerFlags) { + self.imp.set_call_reducer_flags("shuffle_deal", flags); } } diff --git a/jong/src/stdb/shuffle_wall_reducer.rs b/jong/src/stdb/shuffle_wall_reducer.rs deleted file mode 100644 index 4f86c24..0000000 --- a/jong/src/stdb/shuffle_wall_reducer.rs +++ /dev/null @@ -1,100 +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(super) struct ShuffleWallArgs {} - -impl From for super::Reducer { - fn from(args: ShuffleWallArgs) -> Self { - Self::ShuffleWall - } -} - -impl __sdk::InModule for ShuffleWallArgs { - type Module = super::RemoteModule; -} - -pub struct ShuffleWallCallbackId(__sdk::CallbackId); - -#[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `shuffle_wall`. -/// -/// Implemented for [`super::RemoteReducers`]. -pub trait shuffle_wall { - /// Request that the remote module invoke the reducer `shuffle_wall` to run as soon as possible. - /// - /// This method returns immediately, and errors only if we are unable to send the request. - /// The reducer will run asynchronously in the future, - /// and its status can be observed by listening for [`Self::on_shuffle_wall`] callbacks. - fn shuffle_wall(&self) -> __sdk::Result<()>; - /// Register a callback to run whenever we are notified of an invocation of the reducer `shuffle_wall`. - /// - /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] - /// to determine the reducer's status. - /// - /// The returned [`ShuffleWallCallbackId`] can be passed to [`Self::remove_on_shuffle_wall`] - /// to cancel the callback. - fn on_shuffle_wall( - &self, - callback: impl FnMut(&super::ReducerEventContext) + Send + 'static, - ) -> ShuffleWallCallbackId; - /// Cancel a callback previously registered by [`Self::on_shuffle_wall`], - /// causing it not to run in the future. - fn remove_on_shuffle_wall(&self, callback: ShuffleWallCallbackId); -} - -impl shuffle_wall for super::RemoteReducers { - fn shuffle_wall(&self) -> __sdk::Result<()> { - self.imp.call_reducer("shuffle_wall", ShuffleWallArgs {}) - } - fn on_shuffle_wall( - &self, - mut callback: impl FnMut(&super::ReducerEventContext) + Send + 'static, - ) -> ShuffleWallCallbackId { - ShuffleWallCallbackId(self.imp.on_reducer( - "shuffle_wall", - Box::new(move |ctx: &super::ReducerEventContext| { - #[allow(irrefutable_let_patterns)] - let super::ReducerEventContext { - event: - __sdk::ReducerEvent { - reducer: super::Reducer::ShuffleWall {}, - .. - }, - .. - } = ctx - else { - unreachable!() - }; - callback(ctx) - }), - )) - } - fn remove_on_shuffle_wall(&self, callback: ShuffleWallCallbackId) { - self.imp.remove_on_reducer("shuffle_wall", callback.0) - } -} - -#[allow(non_camel_case_types)] -#[doc(hidden)] -/// Extension trait for setting the call-flags for the reducer `shuffle_wall`. -/// -/// Implemented for [`super::SetReducerFlags`]. -/// -/// This type is currently unstable and may be removed without a major version bump. -pub trait set_flags_for_shuffle_wall { - /// Set the call-reducer flags for the reducer `shuffle_wall` to `flags`. - /// - /// This type is currently unstable and may be removed without a major version bump. - fn shuffle_wall(&self, flags: __ws::CallReducerFlags); -} - -impl set_flags_for_shuffle_wall for super::SetReducerFlags { - fn shuffle_wall(&self, flags: __ws::CallReducerFlags) { - self.imp.set_call_reducer_flags("shuffle_wall", flags); - } -} diff --git a/jong/src/stdb/sort_hand_reducer.rs b/jong/src/stdb/sort_hand_reducer.rs deleted file mode 100644 index 5673374..0000000 --- a/jong/src/stdb/sort_hand_reducer.rs +++ /dev/null @@ -1,100 +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(super) struct SortHandArgs {} - -impl From for super::Reducer { - fn from(args: SortHandArgs) -> Self { - Self::SortHand - } -} - -impl __sdk::InModule for SortHandArgs { - type Module = super::RemoteModule; -} - -pub struct SortHandCallbackId(__sdk::CallbackId); - -#[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `sort_hand`. -/// -/// Implemented for [`super::RemoteReducers`]. -pub trait sort_hand { - /// Request that the remote module invoke the reducer `sort_hand` to run as soon as possible. - /// - /// This method returns immediately, and errors only if we are unable to send the request. - /// The reducer will run asynchronously in the future, - /// and its status can be observed by listening for [`Self::on_sort_hand`] callbacks. - fn sort_hand(&self) -> __sdk::Result<()>; - /// Register a callback to run whenever we are notified of an invocation of the reducer `sort_hand`. - /// - /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] - /// to determine the reducer's status. - /// - /// The returned [`SortHandCallbackId`] can be passed to [`Self::remove_on_sort_hand`] - /// to cancel the callback. - fn on_sort_hand( - &self, - callback: impl FnMut(&super::ReducerEventContext) + Send + 'static, - ) -> SortHandCallbackId; - /// Cancel a callback previously registered by [`Self::on_sort_hand`], - /// causing it not to run in the future. - fn remove_on_sort_hand(&self, callback: SortHandCallbackId); -} - -impl sort_hand for super::RemoteReducers { - fn sort_hand(&self) -> __sdk::Result<()> { - self.imp.call_reducer("sort_hand", SortHandArgs {}) - } - fn on_sort_hand( - &self, - mut callback: impl FnMut(&super::ReducerEventContext) + Send + 'static, - ) -> SortHandCallbackId { - SortHandCallbackId(self.imp.on_reducer( - "sort_hand", - Box::new(move |ctx: &super::ReducerEventContext| { - #[allow(irrefutable_let_patterns)] - let super::ReducerEventContext { - event: - __sdk::ReducerEvent { - reducer: super::Reducer::SortHand {}, - .. - }, - .. - } = ctx - else { - unreachable!() - }; - callback(ctx) - }), - )) - } - fn remove_on_sort_hand(&self, callback: SortHandCallbackId) { - self.imp.remove_on_reducer("sort_hand", callback.0) - } -} - -#[allow(non_camel_case_types)] -#[doc(hidden)] -/// Extension trait for setting the call-flags for the reducer `sort_hand`. -/// -/// Implemented for [`super::SetReducerFlags`]. -/// -/// This type is currently unstable and may be removed without a major version bump. -pub trait set_flags_for_sort_hand { - /// Set the call-reducer flags for the reducer `sort_hand` to `flags`. - /// - /// This type is currently unstable and may be removed without a major version bump. - fn sort_hand(&self, flags: __ws::CallReducerFlags); -} - -impl set_flags_for_sort_hand for super::SetReducerFlags { - fn sort_hand(&self, flags: __ws::CallReducerFlags) { - self.imp.set_call_reducer_flags("sort_hand", flags); - } -} diff --git a/jong/src/stdb/view_hand_table.rs b/jong/src/stdb/view_hand_table.rs deleted file mode 100644 index a9927c9..0000000 --- a/jong/src/stdb/view_hand_table.rs +++ /dev/null @@ -1,96 +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::hand_type::Hand; -use super::tile_type::Tile; -use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; - -/// Table handle for the table `view_hand`. -/// -/// Obtain a handle from the [`ViewHandTableAccess::view_hand`] method on [`super::RemoteTables`], -/// like `ctx.db.view_hand()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.view_hand().on_insert(...)`. -pub struct ViewHandTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `view_hand`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait ViewHandTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`ViewHandTableHandle`], which mediates access to the table `view_hand`. - fn view_hand(&self) -> ViewHandTableHandle<'_>; -} - -impl ViewHandTableAccess for super::RemoteTables { - fn view_hand(&self) -> ViewHandTableHandle<'_> { - ViewHandTableHandle { - imp: self.imp.get_table::("view_hand"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct ViewHandInsertCallbackId(__sdk::CallbackId); -pub struct ViewHandDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for ViewHandTableHandle<'ctx> { - type Row = Hand; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { - self.imp.count() - } - fn iter(&self) -> impl Iterator + '_ { - self.imp.iter() - } - - type InsertCallbackId = ViewHandInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> ViewHandInsertCallbackId { - ViewHandInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: ViewHandInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = ViewHandDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> ViewHandDeleteCallbackId { - ViewHandDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: ViewHandDeleteCallbackId) { - 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::("view_hand"); -} - -#[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() - }) -} diff --git a/jong/src/stdb/view_player_hand_table.rs b/jong/src/stdb/view_player_hand_table.rs index 37429bd..82cfb91 100644 --- a/jong/src/stdb/view_player_hand_table.rs +++ b/jong/src/stdb/view_player_hand_table.rs @@ -3,6 +3,7 @@ #![allow(unused, clippy::all)] use super::hand_type::Hand; +use super::player_or_bot_type::PlayerOrBot; use super::tile_type::Tile; use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; diff --git a/justfile b/justfile index c55cca1..0d4b9f7 100644 --- a/justfile +++ b/justfile @@ -2,11 +2,14 @@ set shell := ["nu", "-c"] alias rt := run-tui alias s := spacetime +alias g := spacetime_generate-bindings default: just --list run-tui: + mprocs -s localhost:4050 --ctl $"({c: restart-proc, name: spacetimedb_generate_bindings} | to yaml)" + sleep 3sec cargo run -- run-tui update: @@ -16,5 +19,8 @@ update: spacetime: devenv up -generate-bindings: +spacetime_dev: + spacetime dev --module-bindings-path jong/src/stdb jongline --delete-data=always + +spacetime_generate-bindings: spacetime generate --lang rust --out-dir jong/src/stdb --project-path spacetimedb diff --git a/spacetimedb/src/game.rs b/spacetimedb/src/game.rs new file mode 100644 index 0000000..1266e64 --- /dev/null +++ b/spacetimedb/src/game.rs @@ -0,0 +1,60 @@ +use log::info; +use spacetimedb::{ReducerContext, Table, rand::seq::SliceRandom, reducer}; + +use crate::tables::*; +use jong_types::*; + +mod hand; +mod wall; + +#[reducer] +pub fn join_or_create_lobby(ctx: &ReducerContext, mut lobby_id: u32) -> Result<(), String> { + let ok_or = ctx + .db + .player() + .identity() + .find(ctx.sender) + .ok_or(format!("cannot find player {}", ctx.sender))?; + let mut player = ok_or; + + if lobby_id == 0 { + let lobby = ctx.db.lobby().insert(Lobby { + id: 0, + host_player_id: player.id, + players: vec![PlayerOrBot::Player { id: player.id }], + game_state: GameState::Setup, + }); + info!("created lobby: {:?}", lobby); + + lobby_id = lobby.id; + } + + player.lobby_id = lobby_id; + + let player = ctx.db.player().identity().update(player); + + info!("player {} joined lobby {}", player.id, lobby_id); + Ok(()) +} + +#[reducer] +pub fn add_bot(ctx: &ReducerContext, lobby_id: u32) -> Result<(), String> { + if lobby_id == 0 { + Err("cannot add a bot without a lobby".into()) + } else if let Some(lobby) = ctx.db.lobby().id().find(lobby_id) + && (ctx.db.player().lobby_id().filter(lobby_id).count() + + ctx.db.bot().lobby_id().filter(lobby_id).count() + <= 4) + { + let bot = ctx.db.bot().insert(Bot { + id: 0, + lobby_id, + hand_id: 0, + pond_id: 0, + }); + info!("added bot {} to lobby {}", bot.id, lobby_id); + Ok(()) + } else { + Err("lobby doesn't exist".into()) + } +} diff --git a/spacetimedb/src/game/hand.rs b/spacetimedb/src/game/hand.rs new file mode 100644 index 0000000..546ad66 --- /dev/null +++ b/spacetimedb/src/game/hand.rs @@ -0,0 +1,53 @@ +use spacetimedb::{ReducerContext, Table, ViewContext, reducer, view}; + +use crate::tables::*; +use jong_types::*; + +pub fn deal_hands(ctx: &ReducerContext, lobby_id: u32) { + let players = ctx.db.player().lobby_id().filter(lobby_id); + let bots = ctx.db.bot().lobby_id().filter(lobby_id); + + let mut wall = ctx.db.wall().lobby_id().find(lobby_id).unwrap(); + + // FIXME rectify deal orders + for mut player in players { + let mut tiles = wall.tiles.split_off(wall.tiles.len() - 13); + tiles.sort(); + wall = ctx.db.wall().lobby_id().update(wall); + let hand = ctx.db.hand().insert(Hand { + id: 0, + owner: PlayerOrBot::Player { id: player.id }, + sort: true, + tiles, + }); + player.hand_id = hand.id; + ctx.db.player().id().update(player); + } + for mut bot in bots { + let mut tiles = wall.tiles.split_off(wall.tiles.len() - 13); + tiles.sort(); + wall = ctx.db.wall().lobby_id().update(wall); + let hand = ctx.db.hand().insert(Hand { + id: 0, + owner: PlayerOrBot::Bot { id: bot.id }, + sort: true, + tiles, + }); + bot.hand_id = hand.id; + ctx.db.bot().id().update(bot); + } +} + +#[view(name = view_player_hand, public)] +pub fn view_player_hand(ctx: &ViewContext) -> Option { + ctx.db + .player() + .identity() + .find(ctx.sender) + .map(|p| ctx.db.hand().id().find(p.hand_id))? +} + +// #[reducer] +// pub fn sort_hand(ctx: &ReducerContext) { +// todo!() +// } diff --git a/spacetimedb/src/game/wall.rs b/spacetimedb/src/game/wall.rs new file mode 100644 index 0000000..dca40d4 --- /dev/null +++ b/spacetimedb/src/game/wall.rs @@ -0,0 +1,36 @@ +use log::debug; +use spacetimedb::{ReducerContext, Table, rand::seq::SliceRandom, reducer}; + +use super::hand::deal_hands; +use crate::tables::*; +use jong_types::*; + +#[reducer] +pub fn shuffle_deal(ctx: &ReducerContext, lobby_id: u32) { + debug!("lobby_id: {lobby_id}"); + let mut lobby = ctx.db.lobby().id().find(lobby_id).unwrap(); + + lobby.game_state = GameState::Deal; + let mut lobby = ctx.db.lobby().id().update(lobby); + + + let tiles = new_shuffled_wall(ctx); + ctx.db.wall().insert(Wall { + // id: 0, + lobby_id, + tiles, + }); + + deal_hands(ctx, lobby_id); + + lobby.game_state = GameState::Play; + ctx.db.lobby().id().update(lobby); +} + +pub fn new_shuffled_wall(ctx: &ReducerContext) -> Vec { + let mut rng = ctx.rng(); + let mut wall = tiles(); + wall.shuffle(&mut rng); + + wall +} diff --git a/spacetimedb/src/lib.rs b/spacetimedb/src/lib.rs index efd08f2..e1669d6 100644 --- a/spacetimedb/src/lib.rs +++ b/spacetimedb/src/lib.rs @@ -1,83 +1,13 @@ use log::{debug, info}; use spacetimedb::{ - Identity, ReducerContext, Table, ViewContext, rand::seq::SliceRandom, reducer, table, view, + ReducerContext, Table, ViewContext, rand::seq::SliceRandom, reducer, table, view, }; +use crate::tables::*; use jong_types::*; -#[derive(Debug)] -#[table(name = player, public)] -pub struct Player { - #[primary_key] - identity: Identity, - - #[auto_inc] - #[index(direct)] - #[unique] - id: u32, - - name: Option, - - #[index(btree)] - lobby_id: u32, -} - -#[table(name = bot)] -pub struct Bot { - #[primary_key] - #[auto_inc] - id: u32, - - #[index(btree)] - lobby_id: u32, -} - -#[derive(Debug, Clone, Copy)] -#[table(name = lobby, public)] -pub struct Lobby { - #[primary_key] - #[auto_inc] - id: u32, - - #[index(direct)] - #[unique] - host_player_id: u32, - - game_state: GameState, -} - -#[table(name = wall)] -pub struct Wall { - // #[auto_inc] - // id: u32, - #[primary_key] - // #[index(direct)] - // #[unique] - lobby_id: u32, - - tiles: Vec, -} - -#[table(name = hand)] -pub struct Hand { - #[primary_key] - player_identity: Identity, - - tiles: Vec, -} - -#[table(name = bothand)] -pub struct BotHand { - #[primary_key] - bot_id: u32, - - tiles: Vec, -} - -#[table(name = pond, public)] -pub struct Pond { - tiles: Vec, -} +mod game; +mod tables; #[reducer(client_connected)] pub fn login_or_add_player(ctx: &ReducerContext) { @@ -89,6 +19,8 @@ pub fn login_or_add_player(ctx: &ReducerContext) { id: 0, name: None, lobby_id: 0, + hand_id: 0, + pond_id: 0, }) { info!("added player: {:?}", player); } else { @@ -97,117 +29,6 @@ pub fn login_or_add_player(ctx: &ReducerContext) { } } -#[reducer] -pub fn join_or_create_lobby(ctx: &ReducerContext, mut lobby_id: u32) -> Result<(), String> { - let mut player = ctx - .db - .player() - .identity() - .find(ctx.sender) - .ok_or(format!("cannot find player {}", ctx.sender))?; - - if lobby_id == 0 { - let lobby = ctx.db.lobby().insert(Lobby { - id: 0, - host_player_id: player.id, - game_state: GameState::None, - }); - info!("created lobby: {:?}", lobby); - - lobby_id = lobby.id; - } - - player.lobby_id = lobby_id; - - let player = ctx.db.player().identity().update(player); - - info!("player {} joined lobby {}", player.id, lobby_id); - Ok(()) -} - -#[reducer] -pub fn add_bot(ctx: &ReducerContext, lobby_id: u32) -> Result<(), String> { - if lobby_id == 0 { - Err("cannot add a bot without a lobby".into()) - } else if let Some(lobby) = ctx.db.lobby().id().find(lobby_id) - && (ctx.db.player().lobby_id().filter(lobby_id).count() - + ctx.db.bot().lobby_id().filter(lobby_id).count() - <= 4) - { - let bot = ctx.db.bot().insert(Bot { id: 0, lobby_id }); - info!("added bot {} to lobby {}", bot.id, lobby_id); - Ok(()) - } else { - Err("lobby doesn't exist".into()) - } -} - -#[reducer] -pub fn setup_game(ctx: &ReducerContext, lobby_id: u32) { - debug!("lobby_id: {lobby_id}"); - let mut lobby = ctx.db.lobby().id().find(lobby_id).unwrap(); - lobby.game_state = GameState::Setup; - - ctx.db.lobby().id().update(lobby); - - let tiles = new_shuffled_wall(ctx); - ctx.db.wall().insert(Wall { - // id: 0, - lobby_id, - tiles, - }); - - lobby.game_state = GameState::Deal; - ctx.db.lobby().id().update(lobby); - - deal_hands(ctx, lobby_id); - lobby.game_state = GameState::Play; - ctx.db.lobby().id().update(lobby); -} - -pub fn new_shuffled_wall(ctx: &ReducerContext) -> Vec { - let mut rng = ctx.rng(); - let mut wall = tiles(); - wall.shuffle(&mut rng); - - wall -} - -pub fn deal_hands(ctx: &ReducerContext, lobby_id: u32) { - let players = ctx.db.player().lobby_id().filter(lobby_id); - let bots = ctx.db.bot().lobby_id().filter(lobby_id); - - let mut wall = ctx.db.wall().lobby_id().find(lobby_id).unwrap(); - - // FIXME rectify deal orders - for player in players { - let tiles = wall.tiles.split_off(wall.tiles.len() - 13); - wall = ctx.db.wall().lobby_id().update(wall); - ctx.db.hand().insert(Hand { - player_identity: player.identity, - tiles, - }); - } - for bot in bots { - let tiles = wall.tiles.split_off(wall.tiles.len() - 13); - wall = ctx.db.wall().lobby_id().update(wall); - ctx.db.bothand().insert(BotHand { - bot_id: bot.id, - tiles, - }); - } -} - -#[view(name = view_player_hand, public)] -pub fn view_player_hand(ctx: &ViewContext) -> Option { - ctx.db.hand().player_identity().find(ctx.sender) -} - -#[reducer] -pub fn sort_hand(ctx: &ReducerContext) { - todo!() -} - // #[reducer(init)] // pub fn init(_ctx: &ReducerContext) { // // Called when the module is initially published diff --git a/spacetimedb/src/tables.rs b/spacetimedb/src/tables.rs new file mode 100644 index 0000000..c53daf7 --- /dev/null +++ b/spacetimedb/src/tables.rs @@ -0,0 +1,84 @@ +use spacetimedb::{Identity, SpacetimeType, table}; + +use jong_types::*; + +#[derive(Debug)] +#[table(name = player, public)] +pub struct Player { + #[primary_key] + pub identity: Identity, + + #[unique] + #[auto_inc] + pub id: u32, + + pub name: Option, + + #[index(btree)] + pub lobby_id: u32, + pub hand_id: u32, + pub pond_id: u32, +} + +#[table(name = bot)] +pub struct Bot { + #[primary_key] + #[auto_inc] + pub id: u32, + + #[index(btree)] + pub lobby_id: u32, + pub hand_id: u32, + pub pond_id: u32, +} + +#[derive(Debug, Clone, SpacetimeType)] +pub enum PlayerOrBot { + Player { id: u32 }, + Bot { id: u32 }, +} + +#[derive(Debug, Clone)] +#[table(name = lobby, public)] +pub struct Lobby { + #[primary_key] + #[auto_inc] + pub id: u32, + + #[unique] + pub host_player_id: u32, + pub players: Vec, + + pub game_state: GameState, +} + +#[table(name = wall)] +pub struct Wall { + #[primary_key] + pub lobby_id: u32, + + pub tiles: Vec, +} + +#[table(name = hand)] +pub struct Hand { + #[primary_key] + #[auto_inc] + pub id: u32, + + pub owner: PlayerOrBot, + + pub sort: bool, + pub tiles: Vec, +} + +#[table(name = pond, public)] +pub struct Pond { + #[primary_key] + #[auto_inc] + pub id: u32, + + pub owner: PlayerOrBot, + + pub tiles: Vec, +}