use spacetimedb::{SpacetimeType, ViewContext, table, view}; use jong_types::{ PlayerOrBot, states::{GameState, TurnState}, tiles::Tile, }; use crate::reducers::advance_game; #[derive(Debug, Clone)] #[table(name = lobby, public)] pub struct Lobby { #[primary_key] #[auto_inc] pub id: u32, pub players: Vec, pub dealer_idx: u8, pub current_idx: u8, pub game_state: GameState, // pub open_hands: bool, } #[table(name = wall)] pub struct DbWall { #[primary_key] pub lobby_id: u32, pub tiles: Vec, } #[table(name = tile)] #[derive(Debug, Clone, Copy)] pub struct DbTile { #[primary_key] #[auto_inc] pub id: u32, pub tile: Tile, } #[table(name = player, public)] #[table(name = logged_out_player)] #[derive(Debug)] pub struct Player { #[unique] #[auto_inc] pub id: u32, #[primary_key] pub identity: spacetimedb::Identity, pub name: Option, #[index(btree)] pub lobby_id: u32, pub ready: bool, pub sort: bool, } #[table(name = player_clock, public)] pub struct PlayerClock { #[primary_key] pub id: u32, #[unique] pub player_id: u32, pub renewable: u16, pub total: u16, } #[table(name = player_hand)] pub struct PlayerHand { #[primary_key] #[auto_inc] pub id: u32, #[unique] pub player_id: u32, pub turn_state: TurnState, pub pond: Vec, pub hand: Vec, /// drawn or callable tile pub working_tile: Option, } #[table(name = bot, public)] pub struct Bot { #[primary_key] #[auto_inc] pub id: u32, #[index(btree)] pub lobby_id: u32, pub turn_state: TurnState, pub hand: Vec, pub pond: Vec, pub working_tile: Option, } #[table(name = game_timer, scheduled(advance_game))] pub struct GameTimer { #[primary_key] #[auto_inc] pub id: u64, #[unique] pub lobby_id: u32, pub scheduled_at: spacetimedb::ScheduleAt, } #[view(name = view_hand, public)] fn view_hand(ctx: &ViewContext) -> Option { ctx.db .player() .identity() .find(ctx.sender) .and_then(|p| ctx.db.player_hand().player_id().find(p.id)) } #[derive(SpacetimeType, Clone, Copy)] pub struct HandView { pub player: PlayerOrBot, pub hand_length: u8, // pub melds: u8, pub drawn: bool, } #[view(name = view_closed_hands, public)] fn view_closed_hands(ctx: &ViewContext) -> Vec { let this_player = ctx.db.player().identity().find(ctx.sender).unwrap(); if let Some(lobby) = ctx.db.lobby().id().find(this_player.lobby_id) { lobby .players .iter() .filter_map(|&player| match player { PlayerOrBot::Player { id } => { 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 } } PlayerOrBot::Bot { id } => { 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 } } }) .collect() } else { vec![] } }