2026-02-22 00:39:51 -08:00
|
|
|
use spacetimedb::{SpacetimeType, ViewContext, table, view};
|
2026-02-08 23:47:57 -08:00
|
|
|
|
2026-02-16 00:05:57 -08:00
|
|
|
use jong_types::{
|
2026-02-24 00:56:34 -08:00
|
|
|
PlayerOrBot,
|
2026-02-16 00:05:57 -08:00
|
|
|
states::{GameState, TurnState},
|
2026-02-20 03:20:29 -08:00
|
|
|
tiles::Tile,
|
2026-02-16 00:05:57 -08:00
|
|
|
};
|
2026-02-08 23:47:57 -08:00
|
|
|
|
2026-02-25 15:22:10 -08:00
|
|
|
use crate::reducers::advance_game_private;
|
2026-02-20 15:36:04 -08:00
|
|
|
|
2026-02-08 23:47:57 -08:00
|
|
|
#[derive(Debug, Clone)]
|
2026-02-25 15:22:10 -08:00
|
|
|
#[table(accessor = lobby, public)]
|
2026-02-08 23:47:57 -08:00
|
|
|
pub struct Lobby {
|
|
|
|
|
#[primary_key]
|
|
|
|
|
#[auto_inc]
|
|
|
|
|
pub id: u32,
|
|
|
|
|
|
2026-02-16 00:05:57 -08:00
|
|
|
pub players: Vec<PlayerOrBot>,
|
2026-02-13 08:16:41 -08:00
|
|
|
pub dealer_idx: u8,
|
|
|
|
|
pub current_idx: u8,
|
2026-02-08 23:47:57 -08:00
|
|
|
|
|
|
|
|
pub game_state: GameState,
|
2026-02-24 00:56:34 -08:00
|
|
|
// pub open_hands: bool,
|
2026-02-08 23:47:57 -08:00
|
|
|
}
|
|
|
|
|
|
2026-02-25 15:22:10 -08:00
|
|
|
#[table(accessor = wall)]
|
2026-02-12 17:06:28 -08:00
|
|
|
pub struct DbWall {
|
2026-02-08 23:47:57 -08:00
|
|
|
#[primary_key]
|
|
|
|
|
pub lobby_id: u32,
|
|
|
|
|
|
2026-02-12 17:06:28 -08:00
|
|
|
pub tiles: Vec<DbTile>,
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-25 15:22:10 -08:00
|
|
|
#[table(accessor = tile)]
|
2026-02-13 07:49:09 -08:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
2026-02-12 17:06:28 -08:00
|
|
|
pub struct DbTile {
|
|
|
|
|
#[primary_key]
|
|
|
|
|
#[auto_inc]
|
|
|
|
|
pub id: u32,
|
|
|
|
|
|
2026-02-16 00:05:57 -08:00
|
|
|
pub tile: Tile,
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-25 15:22:10 -08:00
|
|
|
#[table(accessor = player, public)]
|
|
|
|
|
#[table(accessor = logged_out_player)]
|
2026-02-20 03:20:29 -08:00
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct Player {
|
|
|
|
|
#[unique]
|
|
|
|
|
#[auto_inc]
|
|
|
|
|
pub id: u32,
|
|
|
|
|
|
2026-02-20 15:36:04 -08:00
|
|
|
#[primary_key]
|
|
|
|
|
pub identity: spacetimedb::Identity,
|
|
|
|
|
|
2026-02-20 03:20:29 -08:00
|
|
|
pub name: Option<String>,
|
|
|
|
|
|
|
|
|
|
#[index(btree)]
|
|
|
|
|
pub lobby_id: u32,
|
|
|
|
|
pub ready: bool,
|
|
|
|
|
|
|
|
|
|
pub sort: bool,
|
2026-02-20 15:36:04 -08:00
|
|
|
}
|
|
|
|
|
|
2026-02-25 15:22:10 -08:00
|
|
|
#[table(accessor = player_clock, public)]
|
2026-02-20 15:36:04 -08:00
|
|
|
pub struct PlayerClock {
|
|
|
|
|
#[primary_key]
|
|
|
|
|
pub id: u32,
|
|
|
|
|
|
|
|
|
|
#[unique]
|
|
|
|
|
pub player_id: u32,
|
|
|
|
|
|
|
|
|
|
pub renewable: u16,
|
|
|
|
|
pub total: u16,
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-25 15:22:10 -08:00
|
|
|
#[table(accessor = player_hand)]
|
2026-02-20 15:36:04 -08:00
|
|
|
pub struct PlayerHand {
|
|
|
|
|
#[primary_key]
|
|
|
|
|
#[auto_inc]
|
|
|
|
|
pub id: u32,
|
|
|
|
|
|
|
|
|
|
#[unique]
|
|
|
|
|
pub player_id: u32,
|
|
|
|
|
|
|
|
|
|
pub turn_state: TurnState,
|
2026-02-20 03:20:29 -08:00
|
|
|
|
|
|
|
|
pub pond: Vec<DbTile>,
|
2026-02-20 15:36:04 -08:00
|
|
|
pub hand: Vec<DbTile>,
|
2026-02-20 03:20:29 -08:00
|
|
|
|
2026-02-20 15:36:04 -08:00
|
|
|
/// drawn or callable tile
|
|
|
|
|
pub working_tile: Option<DbTile>,
|
2026-02-20 03:20:29 -08:00
|
|
|
}
|
|
|
|
|
|
2026-02-25 15:22:10 -08:00
|
|
|
#[table(accessor = bot, public)]
|
2026-02-20 03:20:29 -08:00
|
|
|
pub struct Bot {
|
|
|
|
|
#[primary_key]
|
|
|
|
|
#[auto_inc]
|
|
|
|
|
pub id: u32,
|
|
|
|
|
|
|
|
|
|
#[index(btree)]
|
|
|
|
|
pub lobby_id: u32,
|
|
|
|
|
|
2026-02-20 15:36:04 -08:00
|
|
|
pub turn_state: TurnState,
|
|
|
|
|
|
2026-02-20 03:20:29 -08:00
|
|
|
pub hand: Vec<DbTile>,
|
|
|
|
|
pub pond: Vec<DbTile>,
|
|
|
|
|
|
2026-02-20 15:36:04 -08:00
|
|
|
pub working_tile: Option<DbTile>,
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-25 15:22:10 -08:00
|
|
|
#[table(accessor = game_timer, scheduled(advance_game_private), public)]
|
2026-02-20 15:36:04 -08:00
|
|
|
pub struct GameTimer {
|
|
|
|
|
#[primary_key]
|
|
|
|
|
#[auto_inc]
|
|
|
|
|
pub id: u64,
|
|
|
|
|
|
|
|
|
|
#[unique]
|
|
|
|
|
pub lobby_id: u32,
|
|
|
|
|
|
|
|
|
|
pub scheduled_at: spacetimedb::ScheduleAt,
|
2026-02-20 03:20:29 -08:00
|
|
|
}
|
2026-02-22 00:39:51 -08:00
|
|
|
|
2026-02-25 15:22:10 -08:00
|
|
|
#[view(accessor = view_hand, public)]
|
2026-02-22 00:39:51 -08:00
|
|
|
fn view_hand(ctx: &ViewContext) -> Option<PlayerHand> {
|
|
|
|
|
ctx.db
|
|
|
|
|
.player()
|
|
|
|
|
.identity()
|
2026-02-25 15:22:10 -08:00
|
|
|
.find(ctx.sender())
|
2026-02-22 00:39:51 -08:00
|
|
|
.and_then(|p| ctx.db.player_hand().player_id().find(p.id))
|
|
|
|
|
}
|
2026-02-24 00:56:34 -08:00
|
|
|
|
|
|
|
|
#[derive(SpacetimeType, Clone, Copy)]
|
|
|
|
|
pub struct HandView {
|
|
|
|
|
pub player: PlayerOrBot,
|
|
|
|
|
pub hand_length: u8,
|
|
|
|
|
// pub melds: u8,
|
|
|
|
|
pub drawn: bool,
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-25 15:22:10 -08:00
|
|
|
#[view(accessor = view_closed_hands, public)]
|
2026-02-24 00:56:34 -08:00
|
|
|
fn view_closed_hands(ctx: &ViewContext) -> Vec<HandView> {
|
2026-02-25 14:34:05 -08:00
|
|
|
if let Some(this_player) = ctx.db.player().identity().find(ctx.sender())
|
|
|
|
|
&& let Some(lobby) = ctx.db.lobby().id().find(this_player.lobby_id)
|
|
|
|
|
{
|
2026-02-24 08:42:23 -08:00
|
|
|
lobby
|
|
|
|
|
.players
|
|
|
|
|
.iter()
|
|
|
|
|
.filter_map(|&player| match player {
|
2026-02-24 00:56:34 -08:00
|
|
|
PlayerOrBot::Player { id } => {
|
2026-02-24 08:42:23 -08:00
|
|
|
if let Some(player_hand) = ctx.db.player_hand().player_id().find(id) {
|
|
|
|
|
Some(HandView {
|
|
|
|
|
player,
|
|
|
|
|
hand_length: player_hand.hand.len() as u8,
|
|
|
|
|
drawn: player_hand.turn_state == TurnState::Tsumo
|
|
|
|
|
&& player_hand.working_tile.is_some(),
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
2026-02-24 00:56:34 -08:00
|
|
|
}
|
|
|
|
|
PlayerOrBot::Bot { id } => {
|
2026-02-24 08:42:23 -08:00
|
|
|
if let Some(bot) = ctx.db.bot().id().find(id) {
|
|
|
|
|
Some(HandView {
|
|
|
|
|
player,
|
|
|
|
|
hand_length: bot.hand.len() as u8,
|
|
|
|
|
drawn: bot.turn_state == TurnState::Tsumo && bot.working_tile.is_some(),
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
2026-02-24 00:56:34 -08:00
|
|
|
}
|
|
|
|
|
})
|
2026-02-24 08:42:23 -08:00
|
|
|
.collect()
|
|
|
|
|
} else {
|
|
|
|
|
vec![]
|
|
|
|
|
}
|
2026-02-24 00:56:34 -08:00
|
|
|
}
|