From a1c72b2c488cdac8166d6c37d504096fdd0ae313 Mon Sep 17 00:00:00 2001 From: Tao Tien <29749622+taotien@users.noreply.github.com> Date: Thu, 12 Feb 2026 17:06:28 -0800 Subject: [PATCH] add a tile table --- Cargo.lock | 1 + jong/src/stdb/bot_table.rs | 2 +- jong/src/stdb/bot_type.rs | 6 +- .../stdb/{wall_type.rs => db_tile_type.rs} | 8 +- jong/src/stdb/db_wall_type.rs | 18 +++ jong/src/stdb/mod.rs | 26 +++- jong/src/stdb/player_table.rs | 2 +- jong/src/stdb/player_type.rs | 6 +- jong/src/stdb/tile_table.rs | 143 ++++++++++++++++++ jong/src/stdb/wall_table.rs | 22 +-- spacetimedb/src/game/hand.rs | 4 +- spacetimedb/src/game/wall.rs | 10 +- spacetimedb/src/tables.rs | 14 +- spacetimedb/src/tables/player.rs | 12 +- 14 files changed, 232 insertions(+), 42 deletions(-) rename jong/src/stdb/{wall_type.rs => db_tile_type.rs} (81%) create mode 100644 jong/src/stdb/db_wall_type.rs create mode 100644 jong/src/stdb/tile_table.rs diff --git a/Cargo.lock b/Cargo.lock index fa24bf0..0b0ffed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1229,6 +1229,7 @@ dependencies = [ "bitflags 2.10.0", "color-eyre", "ratatui", + "smol_str", "tracing", ] diff --git a/jong/src/stdb/bot_table.rs b/jong/src/stdb/bot_table.rs index 6d53305..7c9d250 100644 --- a/jong/src/stdb/bot_table.rs +++ b/jong/src/stdb/bot_table.rs @@ -3,7 +3,7 @@ #![allow(unused, clippy::all)] use super::bot_type::Bot; -use super::tile_type::Tile; +use super::db_tile_type::DbTile; use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; /// Table handle for the table `bot`. diff --git a/jong/src/stdb/bot_type.rs b/jong/src/stdb/bot_type.rs index deaeada..6e82cbf 100644 --- a/jong/src/stdb/bot_type.rs +++ b/jong/src/stdb/bot_type.rs @@ -4,15 +4,15 @@ #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; -use super::tile_type::Tile; +use super::db_tile_type::DbTile; #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] #[sats(crate = __lib)] pub struct Bot { pub id: u32, pub lobby_id: u32, - pub hand: Vec, - pub pond: Vec, + pub hand: Vec, + pub pond: Vec, } impl __sdk::InModule for Bot { diff --git a/jong/src/stdb/wall_type.rs b/jong/src/stdb/db_tile_type.rs similarity index 81% rename from jong/src/stdb/wall_type.rs rename to jong/src/stdb/db_tile_type.rs index 2398ef1..cf5c736 100644 --- a/jong/src/stdb/wall_type.rs +++ b/jong/src/stdb/db_tile_type.rs @@ -8,11 +8,11 @@ use super::tile_type::Tile; #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] #[sats(crate = __lib)] -pub struct Wall { - pub lobby_id: u32, - pub tiles: Vec, +pub struct DbTile { + pub id: u32, + pub tile: Tile, } -impl __sdk::InModule for Wall { +impl __sdk::InModule for DbTile { type Module = super::RemoteModule; } diff --git a/jong/src/stdb/db_wall_type.rs b/jong/src/stdb/db_wall_type.rs new file mode 100644 index 0000000..20688c7 --- /dev/null +++ b/jong/src/stdb/db_wall_type.rs @@ -0,0 +1,18 @@ +// 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}; + +use super::db_tile_type::DbTile; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct DbWall { + pub lobby_id: u32, + pub tiles: Vec, +} + +impl __sdk::InModule for DbWall { + type Module = super::RemoteModule; +} diff --git a/jong/src/stdb/mod.rs b/jong/src/stdb/mod.rs index 5c7e382..61267e0 100644 --- a/jong/src/stdb/mod.rs +++ b/jong/src/stdb/mod.rs @@ -9,6 +9,8 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; pub mod add_bot_reducer; pub mod bot_table; pub mod bot_type; +pub mod db_tile_type; +pub mod db_wall_type; pub mod dragon_type; pub mod game_state_type; pub mod join_or_create_lobby_reducer; @@ -23,15 +25,17 @@ pub mod set_ready_reducer; pub mod shuffle_deal_reducer; pub mod start_game_reducer; pub mod suit_type; +pub mod tile_table; pub mod tile_type; pub mod turn_state_type; pub mod wall_table; -pub mod wall_type; pub mod wind_type; pub use add_bot_reducer::{add_bot, set_flags_for_add_bot, AddBotCallbackId}; pub use bot_table::*; pub use bot_type::Bot; +pub use db_tile_type::DbTile; +pub use db_wall_type::DbWall; pub use dragon_type::Dragon; pub use game_state_type::GameState; pub use join_or_create_lobby_reducer::{ @@ -50,10 +54,10 @@ pub use set_ready_reducer::{set_flags_for_set_ready, set_ready, SetReadyCallback pub use shuffle_deal_reducer::{set_flags_for_shuffle_deal, shuffle_deal, ShuffleDealCallbackId}; pub use start_game_reducer::{set_flags_for_start_game, start_game, StartGameCallbackId}; pub use suit_type::Suit; +pub use tile_table::*; pub use tile_type::Tile; pub use turn_state_type::TurnState; pub use wall_table::*; -pub use wall_type::Wall; pub use wind_type::Wind; #[derive(Clone, PartialEq, Debug)] @@ -144,7 +148,8 @@ pub struct DbUpdate { bot: __sdk::TableUpdate, lobby: __sdk::TableUpdate, player: __sdk::TableUpdate, - wall: __sdk::TableUpdate, + tile: __sdk::TableUpdate, + wall: __sdk::TableUpdate, } impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { @@ -162,6 +167,9 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { "player" => db_update .player .append(player_table::parse_table_update(table_update)?), + "tile" => db_update + .tile + .append(tile_table::parse_table_update(table_update)?), "wall" => db_update .wall .append(wall_table::parse_table_update(table_update)?), @@ -200,8 +208,11 @@ impl __sdk::DbUpdate for DbUpdate { diff.player = cache .apply_diff_to_table::("player", &self.player) .with_updates_by_pk(|row| &row.identity); + diff.tile = cache + .apply_diff_to_table::("tile", &self.tile) + .with_updates_by_pk(|row| &row.id); diff.wall = cache - .apply_diff_to_table::("wall", &self.wall) + .apply_diff_to_table::("wall", &self.wall) .with_updates_by_pk(|row| &row.lobby_id); diff @@ -215,7 +226,8 @@ pub struct AppliedDiff<'r> { bot: __sdk::TableAppliedDiff<'r, Bot>, lobby: __sdk::TableAppliedDiff<'r, Lobby>, player: __sdk::TableAppliedDiff<'r, Player>, - wall: __sdk::TableAppliedDiff<'r, Wall>, + tile: __sdk::TableAppliedDiff<'r, DbTile>, + wall: __sdk::TableAppliedDiff<'r, DbWall>, __unused: std::marker::PhantomData<&'r ()>, } @@ -232,7 +244,8 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> { 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); - callbacks.invoke_table_row_callbacks::("wall", &self.wall, event); + callbacks.invoke_table_row_callbacks::("tile", &self.tile, event); + callbacks.invoke_table_row_callbacks::("wall", &self.wall, event); } } @@ -955,6 +968,7 @@ impl __sdk::SpacetimeModule for RemoteModule { bot_table::register_table(client_cache); lobby_table::register_table(client_cache); player_table::register_table(client_cache); + tile_table::register_table(client_cache); wall_table::register_table(client_cache); } } diff --git a/jong/src/stdb/player_table.rs b/jong/src/stdb/player_table.rs index 2cfb5b3..ee7b127 100644 --- a/jong/src/stdb/player_table.rs +++ b/jong/src/stdb/player_table.rs @@ -2,8 +2,8 @@ // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. #![allow(unused, clippy::all)] +use super::db_tile_type::DbTile; use super::player_type::Player; -use super::tile_type::Tile; use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; /// Table handle for the table `player`. diff --git a/jong/src/stdb/player_type.rs b/jong/src/stdb/player_type.rs index 269c160..d902625 100644 --- a/jong/src/stdb/player_type.rs +++ b/jong/src/stdb/player_type.rs @@ -4,7 +4,7 @@ #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; -use super::tile_type::Tile; +use super::db_tile_type::DbTile; #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] #[sats(crate = __lib)] @@ -15,8 +15,8 @@ pub struct Player { pub lobby_id: u32, pub ready: bool, pub sort: bool, - pub hand: Vec, - pub pond: Vec, + pub hand: Vec, + pub pond: Vec, } impl __sdk::InModule for Player { diff --git a/jong/src/stdb/tile_table.rs b/jong/src/stdb/tile_table.rs new file mode 100644 index 0000000..8d188eb --- /dev/null +++ b/jong/src/stdb/tile_table.rs @@ -0,0 +1,143 @@ +// 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::db_tile_type::DbTile; +use super::tile_type::Tile; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `tile`. +/// +/// Obtain a handle from the [`TileTableAccess::tile`] method on [`super::RemoteTables`], +/// like `ctx.db.tile()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.tile().on_insert(...)`. +pub struct TileTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `tile`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait TileTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`TileTableHandle`], which mediates access to the table `tile`. + fn tile(&self) -> TileTableHandle<'_>; +} + +impl TileTableAccess for super::RemoteTables { + fn tile(&self) -> TileTableHandle<'_> { + TileTableHandle { + imp: self.imp.get_table::("tile"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct TileInsertCallbackId(__sdk::CallbackId); +pub struct TileDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for TileTableHandle<'ctx> { + type Row = DbTile; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = TileInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> TileInsertCallbackId { + TileInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: TileInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = TileDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> TileDeleteCallbackId { + TileDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: TileDeleteCallbackId) { + 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::("tile"); + _table.add_unique_constraint::("id", |row| &row.id); +} +pub struct TileUpdateCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::TableWithPrimaryKey for TileTableHandle<'ctx> { + type UpdateCallbackId = TileUpdateCallbackId; + + fn on_update( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, + ) -> TileUpdateCallbackId { + TileUpdateCallbackId(self.imp.on_update(Box::new(callback))) + } + + fn remove_on_update(&self, callback: TileUpdateCallbackId) { + 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 `id` unique index on the table `tile`, +/// which allows point queries on the field of the same name +/// via the [`TileIdUnique::find`] method. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.tile().id().find(...)`. +pub struct TileIdUnique<'ctx> { + imp: __sdk::UniqueConstraintHandle, + phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +impl<'ctx> TileTableHandle<'ctx> { + /// Get a handle on the `id` unique index on the table `tile`. + pub fn id(&self) -> TileIdUnique<'ctx> { + TileIdUnique { + imp: self.imp.get_unique_constraint::("id"), + phantom: std::marker::PhantomData, + } + } +} + +impl<'ctx> TileIdUnique<'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/wall_table.rs b/jong/src/stdb/wall_table.rs index 92a737e..1f920d6 100644 --- a/jong/src/stdb/wall_table.rs +++ b/jong/src/stdb/wall_table.rs @@ -2,8 +2,8 @@ // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. #![allow(unused, clippy::all)] -use super::tile_type::Tile; -use super::wall_type::Wall; +use super::db_tile_type::DbTile; +use super::db_wall_type::DbWall; use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; /// Table handle for the table `wall`. @@ -15,7 +15,7 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; /// but to directly chain method calls, /// like `ctx.db.wall().on_insert(...)`. pub struct WallTableHandle<'ctx> { - imp: __sdk::TableHandle, + imp: __sdk::TableHandle, ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, } @@ -32,7 +32,7 @@ pub trait WallTableAccess { impl WallTableAccess for super::RemoteTables { fn wall(&self) -> WallTableHandle<'_> { WallTableHandle { - imp: self.imp.get_table::("wall"), + imp: self.imp.get_table::("wall"), ctx: std::marker::PhantomData, } } @@ -42,13 +42,13 @@ pub struct WallInsertCallbackId(__sdk::CallbackId); pub struct WallDeleteCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::Table for WallTableHandle<'ctx> { - type Row = Wall; + type Row = DbWall; type EventContext = super::EventContext; fn count(&self) -> u64 { self.imp.count() } - fn iter(&self) -> impl Iterator + '_ { + fn iter(&self) -> impl Iterator + '_ { self.imp.iter() } @@ -81,7 +81,7 @@ impl<'ctx> __sdk::Table for WallTableHandle<'ctx> { #[doc(hidden)] pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("wall"); + let _table = client_cache.get_or_make_table::("wall"); _table.add_unique_constraint::("lobby_id", |row| &row.lobby_id); } pub struct WallUpdateCallbackId(__sdk::CallbackId); @@ -104,9 +104,9 @@ impl<'ctx> __sdk::TableWithPrimaryKey for WallTableHandle<'ctx> { #[doc(hidden)] pub(super) fn parse_table_update( raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __sdk::Result<__sdk::TableUpdate> { +) -> __sdk::Result<__sdk::TableUpdate> { __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") .with_cause(e) .into() }) @@ -120,7 +120,7 @@ pub(super) fn parse_table_update( /// but to directly chain method calls, /// like `ctx.db.wall().lobby_id().find(...)`. pub struct WallLobbyIdUnique<'ctx> { - imp: __sdk::UniqueConstraintHandle, + imp: __sdk::UniqueConstraintHandle, phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, } @@ -137,7 +137,7 @@ impl<'ctx> WallTableHandle<'ctx> { impl<'ctx> WallLobbyIdUnique<'ctx> { /// Find the subscribed row whose `lobby_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 { + pub fn find(&self, col_val: &u32) -> Option { self.imp.find(col_val) } } diff --git a/spacetimedb/src/game/hand.rs b/spacetimedb/src/game/hand.rs index 294b6d9..6db0b6b 100644 --- a/spacetimedb/src/game/hand.rs +++ b/spacetimedb/src/game/hand.rs @@ -13,14 +13,14 @@ pub fn deal_hands(ctx: &ReducerContext, lobby_id: u32) { for mut player in players { let mut tiles = wall.tiles.split_off(wall.tiles.len() - 13); wall = ctx.db.wall().lobby_id().update(wall); - tiles.sort(); + tiles.sort_by_key(|t| t.tile); player.hand = tiles; ctx.db.player().id().update(player); } for mut bot in bots { let mut tiles = wall.tiles.split_off(wall.tiles.len() - 13); wall = ctx.db.wall().lobby_id().update(wall); - tiles.sort(); + tiles.sort_by_key(|t| t.tile); bot.hand = tiles; ctx.db.bot().id().update(bot); } diff --git a/spacetimedb/src/game/wall.rs b/spacetimedb/src/game/wall.rs index 7096559..99069f6 100644 --- a/spacetimedb/src/game/wall.rs +++ b/spacetimedb/src/game/wall.rs @@ -15,7 +15,8 @@ pub fn shuffle_deal(ctx: &ReducerContext, lobby_id: u32) { lobby = ctx.db.lobby().id().update(lobby); let tiles = new_shuffled_wall(ctx); - ctx.db.wall().insert(Wall { + + ctx.db.wall().insert(DbWall { // id: 0, lobby_id, tiles, @@ -29,9 +30,12 @@ pub fn shuffle_deal(ctx: &ReducerContext, lobby_id: u32) { } } -pub fn new_shuffled_wall(ctx: &ReducerContext) -> Vec { +pub fn new_shuffled_wall(ctx: &ReducerContext) -> Vec { let mut rng = ctx.rng(); - let mut wall = tiles(); + let mut wall: Vec<_> = tiles() + .into_iter() + .map(|tile| ctx.db.tile().insert(DbTile { id: 0, tile })) + .collect(); wall.shuffle(&mut rng); wall diff --git a/spacetimedb/src/tables.rs b/spacetimedb/src/tables.rs index 4e84432..7250513 100644 --- a/spacetimedb/src/tables.rs +++ b/spacetimedb/src/tables.rs @@ -21,9 +21,19 @@ pub struct Lobby { } #[table(name = wall)] -pub struct Wall { +pub struct DbWall { #[primary_key] pub lobby_id: u32, - pub tiles: Vec, + pub tiles: Vec, +} + +#[table(name = tile)] +#[derive(Debug)] +pub struct DbTile { + #[primary_key] + #[auto_inc] + pub id: u32, + + pub tile: jong_types::Tile, } diff --git a/spacetimedb/src/tables/player.rs b/spacetimedb/src/tables/player.rs index ab03a06..8c94365 100644 --- a/spacetimedb/src/tables/player.rs +++ b/spacetimedb/src/tables/player.rs @@ -1,10 +1,10 @@ use spacetimedb::Identity; use spacetimedb::{SpacetimeType, table}; -use jong_types::*; +use super::DbTile; -#[derive(Debug)] #[table(name = player, public)] +#[derive(Debug)] pub struct Player { #[primary_key] pub identity: Identity, @@ -21,8 +21,8 @@ pub struct Player { pub sort: bool, - pub hand: Vec, - pub pond: Vec, + pub hand: Vec, + pub pond: Vec, } #[table(name = bot)] @@ -34,8 +34,8 @@ pub struct Bot { #[index(btree)] pub lobby_id: u32, - pub hand: Vec, - pub pond: Vec, + pub hand: Vec, + pub pond: Vec, } #[derive(Debug, Clone, SpacetimeType)]