Compare commits

..

No commits in common. "9b01f6b96aac313c575bb93c1a02f94d001896f7" and "d183f5d993f8b0e3b605fcdd45673dfdf53a86b2" have entirely different histories.

23 changed files with 716 additions and 216 deletions

View file

@ -1 +0,0 @@
jong/src/stdb

View file

@ -12,9 +12,7 @@ bevy.default-features = false
bevy_ratatui = "0.10.0" bevy_ratatui = "0.10.0"
bevy_spacetimedb = "0.7" bevy_spacetimedb = "0.7"
spacetimedb.version = "1.11.*" spacetimedb = "1.11.*"
spacetimedb.features = ["unstable"]
spacetimedb-sdk = "1.11.*" spacetimedb-sdk = "1.11.*"
strum.version = "0.27.2" strum.version = "0.27.2"

View file

@ -9,8 +9,9 @@ use spacetimedb::Identity;
use spacetimedb_sdk::{DbContext, Table, credentials}; use spacetimedb_sdk::{DbContext, Table, credentials};
use crate::stdb::{ use crate::stdb::{
self, DbConnection, LobbyTableAccess, PlayerTableAccess, RemoteTables, add_bot, self, DbConnection, HandTableAccess, LobbyTableAccess, PlayerTableAccess, RemoteTables,
join_or_create_lobby, login_or_add_player, set_ready, shuffle_deal, start_game, ViewPlayerHandTableAccess, add_bot, join_or_create_lobby, login_or_add_player, set_ready,
shuffle_deal, start_game,
}; };
use crate::{ use crate::{
SpacetimeDB, creds_store, SpacetimeDB, creds_store,
@ -44,11 +45,11 @@ impl Plugin for Riichi {
.with_uri("http://localhost:3000") .with_uri("http://localhost:3000")
.with_module_name("jongline") .with_module_name("jongline")
.with_run_fn(DbConnection::run_threaded) .with_run_fn(DbConnection::run_threaded)
// TODO why don't I need to call add_reducer?
// TODO do these need to be subscription & vice-versa? // TODO do these need to be subscription & vice-versa?
.add_table(RemoteTables::player) .add_table(RemoteTables::player)
.add_table(RemoteTables::lobby) .add_table(RemoteTables::lobby)
.add_table(RemoteTables::hand)
// semicolon stopper // semicolon stopper
; ;
@ -82,7 +83,7 @@ impl Plugin for Riichi {
.add_systems(Update, on_player_insert_update) .add_systems(Update, on_player_insert_update)
.add_systems(Update, on_lobby_insert_update) .add_systems(Update, on_lobby_insert_update)
// .add_systems(OnEnter(GameState::Lobby), join_or_create_lobby) // .add_systems(OnEnter(GameState::Lobby), join_or_create_lobby)
.add_systems(Update, view_hand.run_if(in_state(GameState::Play)))
// semicolon stopper // semicolon stopper
; ;
} }
@ -114,6 +115,7 @@ fn subscriptions(stdb: SpacetimeDB) {
stdb.identity() stdb.identity()
), ),
"SELECT l.* FROM lobby l JOIN player p ON l.host_player_id = p.id".to_string(), "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(); // .subscribe_to_all_tables();
} }
@ -123,10 +125,7 @@ fn on_player_insert_update(
mut messages: ReadInsertUpdateMessage<stdb::Player>, mut messages: ReadInsertUpdateMessage<stdb::Player>,
mut commands: Commands, mut commands: Commands,
tiles: Query<(&Tile, Entity)>,
mut player: Option<Single<&mut player::Player>>, mut player: Option<Single<&mut player::Player>>,
mut hand_ent: Option<Single<Entity, With<Hand>>>,
) { ) {
use player::*; use player::*;
@ -138,28 +137,6 @@ fn on_player_insert_update(
// // TODO add a start game button in the future // // TODO add a start game button in the future
// stdb.reducers().start_game().unwrap(); // stdb.reducers().start_game().unwrap();
// } // }
let mut view: Vec<_> = msg.new.hand.iter().map(Tile::from).collect();
// let mut tiles = tiles
// .iter()
// .filter(|(tt, _)| {
// if let Some((i, _)) = view.iter().enumerate().find(|(_, t)| t == tt) {
// view.swap_remove(i);
// true
// } else {
// false
// }
// })
// // .map(|(t, e)| e)
// .collect::<Vec<_>>();
// tiles.sort_by_key(|(t, e)| **t);
// tiles.get_many(entities)
let tiles = tiles.into_iter().map(|(_, e)| e).collect::<Vec<_>>();
commands
.entity(**hand_ent.as_ref().unwrap())
.replace_children(&tiles);
} else { } else {
let player = Player { let player = Player {
name: msg name: msg
@ -175,6 +152,21 @@ fn on_player_insert_update(
} }
} }
// 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();
// } else {
// info!("in lobby: {}", player.lobby_id)
// }
// }
fn on_lobby_insert_update( fn on_lobby_insert_update(
stdb: SpacetimeDB, stdb: SpacetimeDB,
mut messages: ReadInsertUpdateMessage<stdb::Lobby>, mut messages: ReadInsertUpdateMessage<stdb::Lobby>,
@ -183,7 +175,7 @@ fn on_lobby_insert_update(
mut next_gamestate: ResMut<NextState<GameState>>, mut next_gamestate: ResMut<NextState<GameState>>,
) { ) {
for msg in messages.read() { for msg in messages.read() {
// trace!("on_lobby_insert_update msg:\n{:#?}", msg.new); trace!("on_lobby_insert_update msg:\n{:#?}", msg.new);
let player = stdb let player = stdb
.db() .db()
@ -198,7 +190,7 @@ fn on_lobby_insert_update(
trace!("game entered none"); trace!("game entered none");
} }
stdb::GameState::Lobby => { stdb::GameState::Lobby => {
trace!("game entered lobby"); trace!("game in lobby");
if !player.ready { if !player.ready {
for _ in 0..3 { for _ in 0..3 {
stdb.reducers().add_bot(player.lobby_id).unwrap(); stdb.reducers().add_bot(player.lobby_id).unwrap();
@ -225,3 +217,31 @@ fn on_lobby_insert_update(
next_gamestate.set(msg.new.game_state.into()); next_gamestate.set(msg.new.game_state.into());
} }
} }
fn view_hand(
stdb: SpacetimeDB,
mut commands: Commands,
tiles: Query<(&Tile, Entity)>,
hand_ent: Single<Entity, With<Hand>>,
) {
// trace!("view_hand");
if let Some(view) = stdb.db().view_player_hand().iter().next() {
let mut view = view.tiles.iter().map(Tile::from).collect::<Vec<_>>();
let tiles = tiles
.iter()
.filter(|(tt, _)| {
if let Some((i, _)) = view.iter().enumerate().find(|(_, t)| t == tt) {
view.swap_remove(i);
true
} else {
false
}
})
.map(|(_, e)| e)
.collect::<Vec<_>>();
commands.entity(*hand_ent).replace_children(&tiles);
}
}

View file

@ -3,7 +3,6 @@
#![allow(unused, clippy::all)] #![allow(unused, clippy::all)]
use super::bot_type::Bot; use super::bot_type::Bot;
use super::tile_type::Tile;
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
/// Table handle for the table `bot`. /// Table handle for the table `bot`.

View file

@ -4,15 +4,13 @@
#![allow(unused, clippy::all)] #![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; 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)] #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)] #[sats(crate = __lib)]
pub struct Bot { pub struct Bot {
pub id: u32, pub id: u32,
pub lobby_id: u32, pub lobby_id: u32,
pub hand: Vec<Tile>, pub hand_id: u32,
pub pond: Vec<Tile>, pub pond_id: u32,
} }
impl __sdk::InModule for Bot { impl __sdk::InModule for Bot {

144
jong/src/stdb/hand_table.rs Normal file
View file

@ -0,0 +1,144 @@
// 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::player_or_bot_type::PlayerOrBot;
use super::tile_type::Tile;
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
/// Table handle for the table `hand`.
///
/// Obtain a handle from the [`HandTableAccess::hand`] method on [`super::RemoteTables`],
/// like `ctx.db.hand()`.
///
/// Users are encouraged not to explicitly reference this type,
/// but to directly chain method calls,
/// like `ctx.db.hand().on_insert(...)`.
pub struct HandTableHandle<'ctx> {
imp: __sdk::TableHandle<Hand>,
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
}
#[allow(non_camel_case_types)]
/// Extension trait for access to the table `hand`.
///
/// Implemented for [`super::RemoteTables`].
pub trait HandTableAccess {
#[allow(non_snake_case)]
/// Obtain a [`HandTableHandle`], which mediates access to the table `hand`.
fn hand(&self) -> HandTableHandle<'_>;
}
impl HandTableAccess for super::RemoteTables {
fn hand(&self) -> HandTableHandle<'_> {
HandTableHandle {
imp: self.imp.get_table::<Hand>("hand"),
ctx: std::marker::PhantomData,
}
}
}
pub struct HandInsertCallbackId(__sdk::CallbackId);
pub struct HandDeleteCallbackId(__sdk::CallbackId);
impl<'ctx> __sdk::Table for HandTableHandle<'ctx> {
type Row = Hand;
type EventContext = super::EventContext;
fn count(&self) -> u64 {
self.imp.count()
}
fn iter(&self) -> impl Iterator<Item = Hand> + '_ {
self.imp.iter()
}
type InsertCallbackId = HandInsertCallbackId;
fn on_insert(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> HandInsertCallbackId {
HandInsertCallbackId(self.imp.on_insert(Box::new(callback)))
}
fn remove_on_insert(&self, callback: HandInsertCallbackId) {
self.imp.remove_on_insert(callback.0)
}
type DeleteCallbackId = HandDeleteCallbackId;
fn on_delete(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> HandDeleteCallbackId {
HandDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
}
fn remove_on_delete(&self, callback: HandDeleteCallbackId) {
self.imp.remove_on_delete(callback.0)
}
}
#[doc(hidden)]
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
let _table = client_cache.get_or_make_table::<Hand>("hand");
_table.add_unique_constraint::<u32>("id", |row| &row.id);
}
pub struct HandUpdateCallbackId(__sdk::CallbackId);
impl<'ctx> __sdk::TableWithPrimaryKey for HandTableHandle<'ctx> {
type UpdateCallbackId = HandUpdateCallbackId;
fn on_update(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
) -> HandUpdateCallbackId {
HandUpdateCallbackId(self.imp.on_update(Box::new(callback)))
}
fn remove_on_update(&self, callback: HandUpdateCallbackId) {
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<Hand>> {
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
__sdk::InternalError::failed_parse("TableUpdate<Hand>", "TableUpdate")
.with_cause(e)
.into()
})
}
/// Access to the `id` unique index on the table `hand`,
/// which allows point queries on the field of the same name
/// via the [`HandIdUnique::find`] method.
///
/// Users are encouraged not to explicitly reference this type,
/// but to directly chain method calls,
/// like `ctx.db.hand().id().find(...)`.
pub struct HandIdUnique<'ctx> {
imp: __sdk::UniqueConstraintHandle<Hand, u32>,
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
}
impl<'ctx> HandTableHandle<'ctx> {
/// 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::<u32>("id"),
phantom: std::marker::PhantomData,
}
}
}
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: &u32) -> Option<Hand> {
self.imp.find(col_val)
}
}

View file

@ -0,0 +1,21 @@
// 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::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 id: u32,
pub owner: PlayerOrBot,
pub sort: bool,
pub tiles: Vec<Tile>,
}
impl __sdk::InModule for Hand {
type Module = super::RemoteModule;
}

View file

@ -11,6 +11,8 @@ pub mod bot_table;
pub mod bot_type; pub mod bot_type;
pub mod dragon_type; pub mod dragon_type;
pub mod game_state_type; pub mod game_state_type;
pub mod hand_table;
pub mod hand_type;
pub mod join_or_create_lobby_reducer; pub mod join_or_create_lobby_reducer;
pub mod lobby_table; pub mod lobby_table;
pub mod lobby_type; pub mod lobby_type;
@ -18,6 +20,8 @@ pub mod login_or_add_player_reducer;
pub mod player_or_bot_type; pub mod player_or_bot_type;
pub mod player_table; pub mod player_table;
pub mod player_type; pub mod player_type;
pub mod pond_table;
pub mod pond_type;
pub mod rank_type; pub mod rank_type;
pub mod set_ready_reducer; pub mod set_ready_reducer;
pub mod shuffle_deal_reducer; pub mod shuffle_deal_reducer;
@ -25,6 +29,7 @@ pub mod start_game_reducer;
pub mod suit_type; pub mod suit_type;
pub mod tile_type; pub mod tile_type;
pub mod turn_state_type; pub mod turn_state_type;
pub mod view_player_hand_table;
pub mod wall_table; pub mod wall_table;
pub mod wall_type; pub mod wall_type;
pub mod wind_type; pub mod wind_type;
@ -34,6 +39,8 @@ pub use bot_table::*;
pub use bot_type::Bot; pub use bot_type::Bot;
pub use dragon_type::Dragon; pub use dragon_type::Dragon;
pub use game_state_type::GameState; pub use game_state_type::GameState;
pub use hand_table::*;
pub use hand_type::Hand;
pub use join_or_create_lobby_reducer::{ pub use join_or_create_lobby_reducer::{
join_or_create_lobby, set_flags_for_join_or_create_lobby, JoinOrCreateLobbyCallbackId, join_or_create_lobby, set_flags_for_join_or_create_lobby, JoinOrCreateLobbyCallbackId,
}; };
@ -45,6 +52,8 @@ pub use login_or_add_player_reducer::{
pub use player_or_bot_type::PlayerOrBot; pub use player_or_bot_type::PlayerOrBot;
pub use player_table::*; pub use player_table::*;
pub use player_type::Player; pub use player_type::Player;
pub use pond_table::*;
pub use pond_type::Pond;
pub use rank_type::Rank; pub use rank_type::Rank;
pub use set_ready_reducer::{set_flags_for_set_ready, set_ready, SetReadyCallbackId}; pub use set_ready_reducer::{set_flags_for_set_ready, set_ready, SetReadyCallbackId};
pub use shuffle_deal_reducer::{set_flags_for_shuffle_deal, shuffle_deal, ShuffleDealCallbackId}; pub use shuffle_deal_reducer::{set_flags_for_shuffle_deal, shuffle_deal, ShuffleDealCallbackId};
@ -52,6 +61,7 @@ pub use start_game_reducer::{set_flags_for_start_game, start_game, StartGameCall
pub use suit_type::Suit; pub use suit_type::Suit;
pub use tile_type::Tile; pub use tile_type::Tile;
pub use turn_state_type::TurnState; pub use turn_state_type::TurnState;
pub use view_player_hand_table::*;
pub use wall_table::*; pub use wall_table::*;
pub use wall_type::Wall; pub use wall_type::Wall;
pub use wind_type::Wind; pub use wind_type::Wind;
@ -142,8 +152,11 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer {
#[doc(hidden)] #[doc(hidden)]
pub struct DbUpdate { pub struct DbUpdate {
bot: __sdk::TableUpdate<Bot>, bot: __sdk::TableUpdate<Bot>,
hand: __sdk::TableUpdate<Hand>,
lobby: __sdk::TableUpdate<Lobby>, lobby: __sdk::TableUpdate<Lobby>,
player: __sdk::TableUpdate<Player>, player: __sdk::TableUpdate<Player>,
pond: __sdk::TableUpdate<Pond>,
view_player_hand: __sdk::TableUpdate<Hand>,
wall: __sdk::TableUpdate<Wall>, wall: __sdk::TableUpdate<Wall>,
} }
@ -156,12 +169,21 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate {
"bot" => db_update "bot" => db_update
.bot .bot
.append(bot_table::parse_table_update(table_update)?), .append(bot_table::parse_table_update(table_update)?),
"hand" => db_update
.hand
.append(hand_table::parse_table_update(table_update)?),
"lobby" => db_update "lobby" => db_update
.lobby .lobby
.append(lobby_table::parse_table_update(table_update)?), .append(lobby_table::parse_table_update(table_update)?),
"player" => db_update "player" => db_update
.player .player
.append(player_table::parse_table_update(table_update)?), .append(player_table::parse_table_update(table_update)?),
"pond" => db_update
.pond
.append(pond_table::parse_table_update(table_update)?),
"view_player_hand" => db_update
.view_player_hand
.append(view_player_hand_table::parse_table_update(table_update)?),
"wall" => db_update "wall" => db_update
.wall .wall
.append(wall_table::parse_table_update(table_update)?), .append(wall_table::parse_table_update(table_update)?),
@ -194,15 +216,23 @@ impl __sdk::DbUpdate for DbUpdate {
diff.bot = cache diff.bot = cache
.apply_diff_to_table::<Bot>("bot", &self.bot) .apply_diff_to_table::<Bot>("bot", &self.bot)
.with_updates_by_pk(|row| &row.id); .with_updates_by_pk(|row| &row.id);
diff.hand = cache
.apply_diff_to_table::<Hand>("hand", &self.hand)
.with_updates_by_pk(|row| &row.id);
diff.lobby = cache diff.lobby = cache
.apply_diff_to_table::<Lobby>("lobby", &self.lobby) .apply_diff_to_table::<Lobby>("lobby", &self.lobby)
.with_updates_by_pk(|row| &row.id); .with_updates_by_pk(|row| &row.id);
diff.player = cache diff.player = cache
.apply_diff_to_table::<Player>("player", &self.player) .apply_diff_to_table::<Player>("player", &self.player)
.with_updates_by_pk(|row| &row.identity); .with_updates_by_pk(|row| &row.identity);
diff.pond = cache
.apply_diff_to_table::<Pond>("pond", &self.pond)
.with_updates_by_pk(|row| &row.id);
diff.wall = cache diff.wall = cache
.apply_diff_to_table::<Wall>("wall", &self.wall) .apply_diff_to_table::<Wall>("wall", &self.wall)
.with_updates_by_pk(|row| &row.lobby_id); .with_updates_by_pk(|row| &row.lobby_id);
diff.view_player_hand =
cache.apply_diff_to_table::<Hand>("view_player_hand", &self.view_player_hand);
diff diff
} }
@ -213,8 +243,11 @@ impl __sdk::DbUpdate for DbUpdate {
#[doc(hidden)] #[doc(hidden)]
pub struct AppliedDiff<'r> { pub struct AppliedDiff<'r> {
bot: __sdk::TableAppliedDiff<'r, Bot>, bot: __sdk::TableAppliedDiff<'r, Bot>,
hand: __sdk::TableAppliedDiff<'r, Hand>,
lobby: __sdk::TableAppliedDiff<'r, Lobby>, lobby: __sdk::TableAppliedDiff<'r, Lobby>,
player: __sdk::TableAppliedDiff<'r, Player>, player: __sdk::TableAppliedDiff<'r, Player>,
pond: __sdk::TableAppliedDiff<'r, Pond>,
view_player_hand: __sdk::TableAppliedDiff<'r, Hand>,
wall: __sdk::TableAppliedDiff<'r, Wall>, wall: __sdk::TableAppliedDiff<'r, Wall>,
__unused: std::marker::PhantomData<&'r ()>, __unused: std::marker::PhantomData<&'r ()>,
} }
@ -230,8 +263,15 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> {
callbacks: &mut __sdk::DbCallbacks<RemoteModule>, callbacks: &mut __sdk::DbCallbacks<RemoteModule>,
) { ) {
callbacks.invoke_table_row_callbacks::<Bot>("bot", &self.bot, event); callbacks.invoke_table_row_callbacks::<Bot>("bot", &self.bot, event);
callbacks.invoke_table_row_callbacks::<Hand>("hand", &self.hand, event);
callbacks.invoke_table_row_callbacks::<Lobby>("lobby", &self.lobby, event); callbacks.invoke_table_row_callbacks::<Lobby>("lobby", &self.lobby, event);
callbacks.invoke_table_row_callbacks::<Player>("player", &self.player, event); callbacks.invoke_table_row_callbacks::<Player>("player", &self.player, event);
callbacks.invoke_table_row_callbacks::<Pond>("pond", &self.pond, event);
callbacks.invoke_table_row_callbacks::<Hand>(
"view_player_hand",
&self.view_player_hand,
event,
);
callbacks.invoke_table_row_callbacks::<Wall>("wall", &self.wall, event); callbacks.invoke_table_row_callbacks::<Wall>("wall", &self.wall, event);
} }
} }
@ -953,8 +993,11 @@ impl __sdk::SpacetimeModule for RemoteModule {
fn register_tables(client_cache: &mut __sdk::ClientCache<Self>) { fn register_tables(client_cache: &mut __sdk::ClientCache<Self>) {
bot_table::register_table(client_cache); bot_table::register_table(client_cache);
hand_table::register_table(client_cache);
lobby_table::register_table(client_cache); lobby_table::register_table(client_cache);
player_table::register_table(client_cache); player_table::register_table(client_cache);
pond_table::register_table(client_cache);
view_player_hand_table::register_table(client_cache);
wall_table::register_table(client_cache); wall_table::register_table(client_cache);
} }
} }

View file

@ -3,7 +3,6 @@
#![allow(unused, clippy::all)] #![allow(unused, clippy::all)]
use super::player_type::Player; use super::player_type::Player;
use super::tile_type::Tile;
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
/// Table handle for the table `player`. /// Table handle for the table `player`.

View file

@ -4,8 +4,6 @@
#![allow(unused, clippy::all)] #![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; 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)] #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)] #[sats(crate = __lib)]
pub struct Player { pub struct Player {
@ -13,10 +11,9 @@ pub struct Player {
pub id: u32, pub id: u32,
pub name: Option<String>, pub name: Option<String>,
pub lobby_id: u32, pub lobby_id: u32,
pub hand_id: u32,
pub pond_id: u32,
pub ready: bool, pub ready: bool,
pub sort: bool,
pub hand: Vec<Tile>,
pub pond: Vec<Tile>,
} }
impl __sdk::InModule for Player { impl __sdk::InModule for Player {

144
jong/src/stdb/pond_table.rs Normal file
View file

@ -0,0 +1,144 @@
// 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::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};
/// Table handle for the table `pond`.
///
/// Obtain a handle from the [`PondTableAccess::pond`] method on [`super::RemoteTables`],
/// like `ctx.db.pond()`.
///
/// Users are encouraged not to explicitly reference this type,
/// but to directly chain method calls,
/// like `ctx.db.pond().on_insert(...)`.
pub struct PondTableHandle<'ctx> {
imp: __sdk::TableHandle<Pond>,
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
}
#[allow(non_camel_case_types)]
/// Extension trait for access to the table `pond`.
///
/// Implemented for [`super::RemoteTables`].
pub trait PondTableAccess {
#[allow(non_snake_case)]
/// Obtain a [`PondTableHandle`], which mediates access to the table `pond`.
fn pond(&self) -> PondTableHandle<'_>;
}
impl PondTableAccess for super::RemoteTables {
fn pond(&self) -> PondTableHandle<'_> {
PondTableHandle {
imp: self.imp.get_table::<Pond>("pond"),
ctx: std::marker::PhantomData,
}
}
}
pub struct PondInsertCallbackId(__sdk::CallbackId);
pub struct PondDeleteCallbackId(__sdk::CallbackId);
impl<'ctx> __sdk::Table for PondTableHandle<'ctx> {
type Row = Pond;
type EventContext = super::EventContext;
fn count(&self) -> u64 {
self.imp.count()
}
fn iter(&self) -> impl Iterator<Item = Pond> + '_ {
self.imp.iter()
}
type InsertCallbackId = PondInsertCallbackId;
fn on_insert(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> PondInsertCallbackId {
PondInsertCallbackId(self.imp.on_insert(Box::new(callback)))
}
fn remove_on_insert(&self, callback: PondInsertCallbackId) {
self.imp.remove_on_insert(callback.0)
}
type DeleteCallbackId = PondDeleteCallbackId;
fn on_delete(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> PondDeleteCallbackId {
PondDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
}
fn remove_on_delete(&self, callback: PondDeleteCallbackId) {
self.imp.remove_on_delete(callback.0)
}
}
#[doc(hidden)]
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
let _table = client_cache.get_or_make_table::<Pond>("pond");
_table.add_unique_constraint::<u32>("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)]
pub(super) fn parse_table_update(
raw_updates: __ws::TableUpdate<__ws::BsatnFormat>,
) -> __sdk::Result<__sdk::TableUpdate<Pond>> {
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
__sdk::InternalError::failed_parse("TableUpdate<Pond>", "TableUpdate")
.with_cause(e)
.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<Pond, u32>,
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::<u32>("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<Pond> {
self.imp.find(col_val)
}
}

View file

@ -0,0 +1,20 @@
// 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::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<Tile>,
}
impl __sdk::InModule for Pond {
type Module = super::RemoteModule;
}

View file

@ -0,0 +1,97 @@
// 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::player_or_bot_type::PlayerOrBot;
use super::tile_type::Tile;
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
/// Table handle for the table `view_player_hand`.
///
/// Obtain a handle from the [`ViewPlayerHandTableAccess::view_player_hand`] method on [`super::RemoteTables`],
/// like `ctx.db.view_player_hand()`.
///
/// Users are encouraged not to explicitly reference this type,
/// but to directly chain method calls,
/// like `ctx.db.view_player_hand().on_insert(...)`.
pub struct ViewPlayerHandTableHandle<'ctx> {
imp: __sdk::TableHandle<Hand>,
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
}
#[allow(non_camel_case_types)]
/// Extension trait for access to the table `view_player_hand`.
///
/// Implemented for [`super::RemoteTables`].
pub trait ViewPlayerHandTableAccess {
#[allow(non_snake_case)]
/// Obtain a [`ViewPlayerHandTableHandle`], which mediates access to the table `view_player_hand`.
fn view_player_hand(&self) -> ViewPlayerHandTableHandle<'_>;
}
impl ViewPlayerHandTableAccess for super::RemoteTables {
fn view_player_hand(&self) -> ViewPlayerHandTableHandle<'_> {
ViewPlayerHandTableHandle {
imp: self.imp.get_table::<Hand>("view_player_hand"),
ctx: std::marker::PhantomData,
}
}
}
pub struct ViewPlayerHandInsertCallbackId(__sdk::CallbackId);
pub struct ViewPlayerHandDeleteCallbackId(__sdk::CallbackId);
impl<'ctx> __sdk::Table for ViewPlayerHandTableHandle<'ctx> {
type Row = Hand;
type EventContext = super::EventContext;
fn count(&self) -> u64 {
self.imp.count()
}
fn iter(&self) -> impl Iterator<Item = Hand> + '_ {
self.imp.iter()
}
type InsertCallbackId = ViewPlayerHandInsertCallbackId;
fn on_insert(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> ViewPlayerHandInsertCallbackId {
ViewPlayerHandInsertCallbackId(self.imp.on_insert(Box::new(callback)))
}
fn remove_on_insert(&self, callback: ViewPlayerHandInsertCallbackId) {
self.imp.remove_on_insert(callback.0)
}
type DeleteCallbackId = ViewPlayerHandDeleteCallbackId;
fn on_delete(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> ViewPlayerHandDeleteCallbackId {
ViewPlayerHandDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
}
fn remove_on_delete(&self, callback: ViewPlayerHandDeleteCallbackId) {
self.imp.remove_on_delete(callback.0)
}
}
#[doc(hidden)]
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
let _table = client_cache.get_or_make_table::<Hand>("view_player_hand");
}
#[doc(hidden)]
pub(super) fn parse_table_update(
raw_updates: __ws::TableUpdate<__ws::BsatnFormat>,
) -> __sdk::Result<__sdk::TableUpdate<Hand>> {
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
__sdk::InternalError::failed_parse("TableUpdate<Hand>", "TableUpdate")
.with_cause(e)
.into()
})
}

View file

@ -86,7 +86,7 @@ impl Plugin for TuiPlugin {
.add_systems( .add_systems(
Update, Update,
( (
render::render_hands.run_if(in_state(GameState::Play)), (render::render_hands, render::render_arg_check).run_if(in_state(GameState::Play)),
render::render, render::render,
) )
.chain() .chain()

View file

@ -95,24 +95,23 @@ pub(crate) fn render(
Ok(()) Ok(())
} }
// pub(crate) fn render_arg_check( pub(crate) fn render_arg_check(
// mut commands: Commands, mut commands: Commands,
// mut tui: ResMut<RatatuiContext>, mut tui: ResMut<RatatuiContext>,
// hovered: Query<Entity, With<Hovered>>, hovered: Query<Entity, With<Hovered>>,
// layouts: Res<HandLayouts>, layouts: Res<HandLayouts>,
// tiles: Query<&jong_types::Tile>, tiles: Query<&jong_types::Tile>,
// // main_player: Single<(&Player, Entity, &Wind), With<MainPlayer>>, // main_player: Single<(&Player, Entity, &Wind), With<MainPlayer>>,
// curr_player: Single<Entity, With<CurrentPlayer>>, curr_player: Single<Entity, With<CurrentPlayer>>,
// players: Query<(&Player, Entity, &Children)>, players: Query<(&Player, Entity, &Children)>,
// hands: Query<(&Children, Entity), (With<Hand>, Without<Player>)>, hands: Query<(&Children, Entity), (With<Hand>, Without<Player>)>,
// // drawn_tile: Single<Entity, With<Drawn>>, // drawn_tile: Single<Entity, With<Drawn>>,
// ) { ) {
// // trace!("arg!"); // trace!("arg!");
// } }
// FIXME we don't care about other players atm
#[allow(clippy::too_many_arguments, clippy::type_complexity)] #[allow(clippy::too_many_arguments, clippy::type_complexity)]
pub(crate) fn render_hands( pub(crate) fn render_hands(
mut commands: Commands, mut commands: Commands,
@ -122,21 +121,23 @@ pub(crate) fn render_hands(
layouts: Res<HandLayouts>, layouts: Res<HandLayouts>,
tiles: Query<&jong_types::Tile>, tiles: Query<&jong_types::Tile>,
main_player: Single<(&Player, Entity /* , &Wind */), With<MainPlayer>>, main_player: Single<(&Player, Entity, &Wind), With<MainPlayer>>,
curr_player: Single<Entity, With<CurrentPlayer>>, curr_player: Single<Entity, With<CurrentPlayer>>,
players: Query<(&Player, Entity, &Children)>, players: Query<(&Player, Entity, &Children)>,
hands: Query<(&Children, Entity), With<Hand>>, hands: Query<(&Children, Entity), (With<Hand>, Without<Player>)>,
// drawn_tile: Single<Entity, With<Drawn>>, drawn_tile: Single<Entity, With<Drawn>>,
) -> Result { ) -> Result {
trace!("render_hands");
let mut frame = tui.get_frame(); let mut frame = tui.get_frame();
debug_blocks(*layouts, &mut frame); debug_blocks(*layouts, &mut frame);
for (hand, hand_ent) in hands { for (hand, hand_ent) in hands {
// debug!("{hand:?}"); // debug!("{hand:?}");
// let (player, player_ent, _) = players let (player, player_ent, _) = players
// .iter() .iter()
// .find(|(_, e, c)| c.contains(&hand_ent)) .find(|(_, e, c)| c.contains(&hand_ent))
// .unwrap(); .unwrap();
let hand: Vec<_> = hand let hand: Vec<_> = hand
.iter() .iter()
.map(|entity| -> Result<_> { .map(|entity| -> Result<_> {
@ -148,81 +149,80 @@ pub(crate) fn render_hands(
}) })
.collect::<Result<_>>()?; .collect::<Result<_>>()?;
let (player, player_ent) = *main_player; if player == main_player.0 {
// if player == main_player.0 { // split main box into thirds
// split main box into thirds let mut this_hand = layouts.this_hand;
let mut this_hand = layouts.this_hand; // let this_drawer = drawn_tile..is_some_and(|dt| dt.0 == player);
// let this_drawer = drawn_tile..is_some_and(|dt| dt.0 == player); let this_drawer = player_ent == *curr_player;
let this_drawer = player_ent == *curr_player; let tile_drawn = if this_drawer { 7 } else { 0 };
let tile_drawn = if this_drawer { 7 } else { 0 }; let hand_draw_meld = Layout::horizontal([
let hand_draw_meld = Layout::horizontal([ Constraint::Max(hand.len() as u16 * 5),
Constraint::Max(hand.len() as u16 * 5), Constraint::Max(tile_drawn),
Constraint::Max(tile_drawn), Constraint::Fill(1),
Constraint::Fill(1), ])
]) .flex(Flex::SpaceBetween);
.flex(Flex::SpaceBetween); this_hand = this_hand.offset(Offset {
this_hand = this_hand.offset(Offset { x: 0,
x: 0, y: this_hand.height.abs_diff(5) as i32 + 1,
y: this_hand.height.abs_diff(5) as i32 + 1, });
}); this_hand = this_hand.resize(Size {
this_hand = this_hand.resize(Size { width: this_hand.width,
width: this_hand.width, height: 4,
height: 4, });
}); let [hand_area, drawn_area, meld_area] = hand_draw_meld.areas::<3>(this_hand);
let [hand_area, drawn_area, meld_area] = hand_draw_meld.areas::<3>(this_hand);
// split hand area into tile areas // split hand area into tile areas
let mut constraints = vec![Constraint::Max(5); hand.len()]; let mut constraints = vec![Constraint::Max(5); hand.len()];
constraints.push(Constraint::Fill(1)); constraints.push(Constraint::Fill(1));
let layout = Layout::horizontal(constraints).flex(Flex::Start); let layout = Layout::horizontal(constraints).flex(Flex::Start);
let tile_areas = layout.split(hand_area); let tile_areas = layout.split(hand_area);
for ((entity, widget, hovered), mut area) in for ((entity, widget, hovered), mut area) in
hand.into_iter().zip(tile_areas.iter().copied()) hand.into_iter().zip(tile_areas.iter().copied())
{ {
if hovered { if hovered {
area = area.offset(Offset { x: 0, y: -1 }); area = area.offset(Offset { x: 0, y: -1 });
let mut hitbox = area.as_size(); let mut hitbox = area.as_size();
hitbox.height += 1; hitbox.height += 1;
commands.entity(entity).insert(PickRegion { commands.entity(entity).insert(PickRegion {
area: area.resize(hitbox), area: area.resize(hitbox),
}); });
} else { } else {
commands.entity(entity).insert(PickRegion { area }); commands.entity(entity).insert(PickRegion { area });
}
frame.render_widget(widget, area);
} }
frame.render_widget(widget, area);
}
// tsumo tile // tsumo tile
// if this_drawer { if this_drawer {
// // trace!("this_drawer"); // trace!("this_drawer");
// let mut area = drawn_area.resize(Size { let mut area = drawn_area.resize(Size {
// width: 5, width: 5,
// height: 4, height: 4,
// }); });
// area = area.offset(Offset { x: 2, y: 0 }); area = area.offset(Offset { x: 2, y: 0 });
// let hovered = hovered.contains(*drawn_tile); let hovered = hovered.contains(*drawn_tile);
// let widget = render_tile(tiles.get(*drawn_tile)?, hovered); let widget = render_tile(tiles.get(*drawn_tile)?, hovered);
// if hovered { if hovered {
// area = area.offset(Offset { x: 0, y: -1 }); area = area.offset(Offset { x: 0, y: -1 });
// let mut hitbox = area.as_size(); let mut hitbox = area.as_size();
// hitbox.height += 1; hitbox.height += 1;
// commands.entity(*drawn_tile).insert(PickRegion { commands.entity(*drawn_tile).insert(PickRegion {
// area: area.resize(hitbox), area: area.resize(hitbox),
// }); });
// } else { } else {
// commands.entity(*drawn_tile).insert(PickRegion { area }); commands.entity(*drawn_tile).insert(PickRegion { area });
// } }
// frame.render_widget(widget, area); frame.render_widget(widget, area);
// } }
// TODO draw melds // TODO draw melds
// } else { } else {
// match mainplayer.1.relate(wind) { // match mainplayer.1.relate(wind) {
// jong::game::round::WindRelation::Shimocha => todo!(), // jong::game::round::WindRelation::Shimocha => todo!(),
// jong::game::round::WindRelation::Toimen => todo!(), // jong::game::round::WindRelation::Toimen => todo!(),
// jong::game::round::WindRelation::Kamicha => todo!(), // jong::game::round::WindRelation::Kamicha => todo!(),
// } // }
// } }
} }
Ok(()) Ok(())

View file

@ -8,8 +8,8 @@ default:
just --list just --list
run-tui: run-tui:
mprocs -s localhost:4050 --ctl $"({c: restart-proc, name: spacetimedb_generate_bindings} | to yaml)" # mprocs -s localhost:4050 --ctl $"({c: restart-proc, name: spacetimedb_generate_bindings} | to yaml)"
sleep 3sec # sleep 3sec
cargo run -- run-tui cargo run -- run-tui
update: update:

View file

@ -1,7 +1,7 @@
use log::{info, trace}; use log::{info, trace};
use spacetimedb::{ReducerContext, Table, reducer}; use spacetimedb::{ReducerContext, Table, reducer};
use crate::tables::{player::player, *}; use crate::tables::*;
use jong_types::*; use jong_types::*;
mod hand; mod hand;
@ -50,8 +50,8 @@ pub fn add_bot(ctx: &ReducerContext, lobby_id: u32) -> Result<(), String> {
let bot = ctx.db.bot().insert(Bot { let bot = ctx.db.bot().insert(Bot {
id: 0, id: 0,
lobby_id, lobby_id,
hand: vec![], hand_id: 0,
pond: vec![], pond_id: 0,
}); });
lobby.players.push(PlayerOrBot::Bot { id: bot.id }); lobby.players.push(PlayerOrBot::Bot { id: bot.id });
ctx.db.lobby().id().update(lobby); ctx.db.lobby().id().update(lobby);
@ -80,7 +80,7 @@ pub fn start_game(ctx: &ReducerContext) {
PlayerOrBot::Bot { id } => ctx.db.bot().id().find(id).is_some(), PlayerOrBot::Bot { id } => ctx.db.bot().id().find(id).is_some(),
}) })
{ {
lobby.game_state = GameState::Setup; lobby.game_state = GameState::Deal;
ctx.db.lobby().id().update(lobby); ctx.db.lobby().id().update(lobby);
} }
} }

View file

@ -1,6 +1,6 @@
use spacetimedb::{ReducerContext, Table, ViewContext, reducer, view}; use spacetimedb::{ReducerContext, Table, ViewContext, reducer, view};
use crate::tables::{player::player, *}; use crate::tables::*;
use jong_types::*; use jong_types::*;
pub fn deal_hands(ctx: &ReducerContext, lobby_id: u32) { pub fn deal_hands(ctx: &ReducerContext, lobby_id: u32) {
@ -12,28 +12,40 @@ pub fn deal_hands(ctx: &ReducerContext, lobby_id: u32) {
// FIXME rectify deal orders // FIXME rectify deal orders
for mut player in players { for mut player in players {
let mut tiles = wall.tiles.split_off(wall.tiles.len() - 13); let mut tiles = wall.tiles.split_off(wall.tiles.len() - 13);
wall = ctx.db.wall().lobby_id().update(wall);
tiles.sort(); tiles.sort();
player.hand = tiles; 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); ctx.db.player().id().update(player);
} }
for mut bot in bots { for mut bot in bots {
let mut tiles = wall.tiles.split_off(wall.tiles.len() - 13); let mut tiles = wall.tiles.split_off(wall.tiles.len() - 13);
wall = ctx.db.wall().lobby_id().update(wall);
tiles.sort(); tiles.sort();
bot.hand = tiles; 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); ctx.db.bot().id().update(bot);
} }
} }
// #[view(name = view_player_hand, public)] #[view(name = view_player_hand, public)]
// pub fn view_player_hand(ctx: &ViewContext) -> Option<Hand> { pub fn view_player_hand(ctx: &ViewContext) -> Option<Hand> {
// ctx.db ctx.db
// .player() .player()
// .identity() .identity()
// .find(ctx.sender) .find(ctx.sender)
// .map(|p| ctx.db.hand().id().find(p.hand_id))? .map(|p| ctx.db.hand().id().find(p.hand_id))?
// } }
// #[reducer] // #[reducer]
// pub fn sort_hand(ctx: &ReducerContext) { // pub fn sort_hand(ctx: &ReducerContext) {

View file

@ -10,10 +10,7 @@ pub fn shuffle_deal(ctx: &ReducerContext, lobby_id: u32) {
debug!("lobby_id: {lobby_id}"); debug!("lobby_id: {lobby_id}");
let mut lobby = ctx.db.lobby().id().find(lobby_id).unwrap(); let mut lobby = ctx.db.lobby().id().find(lobby_id).unwrap();
if lobby.game_state == GameState::Setup { if lobby.game_state == GameState::Deal {
lobby.game_state = GameState::Deal;
lobby = ctx.db.lobby().id().update(lobby);
let tiles = new_shuffled_wall(ctx); let tiles = new_shuffled_wall(ctx);
ctx.db.wall().insert(Wall { ctx.db.wall().insert(Wall {
// id: 0, // id: 0,

View file

@ -1,7 +1,7 @@
use log::info; use log::info;
use spacetimedb::{ReducerContext, Table, reducer}; use spacetimedb::{ReducerContext, Table, reducer};
use crate::tables::{player::player, *}; use crate::tables::*;
mod game; mod game;
mod tables; mod tables;
@ -16,10 +16,9 @@ pub fn login_or_add_player(ctx: &ReducerContext) {
id: 0, id: 0,
name: None, name: None,
lobby_id: 0, lobby_id: 0,
hand_id: 0,
pond_id: 0,
ready: false, ready: false,
sort: true,
hand: vec![],
pond: vec![],
}) { }) {
info!("added player: {:?}", player); info!("added player: {:?}", player);
} else { } else {

View file

@ -1,9 +1,44 @@
use spacetimedb::{Filter, SpacetimeType, client_visibility_filter, table}; use spacetimedb::{Identity, SpacetimeType, table};
use jong_types::*; use jong_types::*;
pub mod player; #[derive(Debug)]
pub use player::*; #[table(name = player, public)]
pub struct Player {
#[primary_key]
pub identity: Identity,
#[unique]
#[auto_inc]
pub id: u32,
pub name: Option<String>,
#[index(btree)]
pub lobby_id: u32,
pub hand_id: u32,
pub pond_id: u32,
pub ready: bool,
}
#[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)] #[derive(Debug, Clone)]
#[table(name = lobby, public)] #[table(name = lobby, public)]
@ -14,7 +49,7 @@ pub struct Lobby {
#[unique] #[unique]
pub host_player_id: u32, pub host_player_id: u32,
pub players: Vec<player::PlayerOrBot>, pub players: Vec<PlayerOrBot>,
pub game_state: GameState, pub game_state: GameState,
pub turn_state: TurnState, pub turn_state: TurnState,
@ -27,3 +62,26 @@ pub struct Wall {
pub tiles: Vec<Tile>, pub tiles: Vec<Tile>,
} }
#[table(name = hand)]
pub struct Hand {
#[primary_key]
#[auto_inc]
pub id: u32,
pub owner: PlayerOrBot,
pub sort: bool,
pub tiles: Vec<Tile>,
}
#[table(name = pond, public)]
pub struct Pond {
#[primary_key]
#[auto_inc]
pub id: u32,
pub owner: PlayerOrBot,
pub tiles: Vec<Tile>,
}

View file

@ -1,45 +0,0 @@
use spacetimedb::Identity;
use spacetimedb::{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<String>,
#[index(btree)]
pub lobby_id: u32,
pub ready: bool,
pub sort: bool,
pub hand: Vec<Tile>,
pub pond: Vec<Tile>,
}
#[table(name = bot)]
pub struct Bot {
#[primary_key]
#[auto_inc]
pub id: u32,
#[index(btree)]
pub lobby_id: u32,
pub hand: Vec<Tile>,
pub pond: Vec<Tile>,
}
#[derive(Debug, Clone, SpacetimeType)]
pub enum PlayerOrBot {
Player { id: u32 },
Bot { id: u32 },
}

View file