use log::{info, trace}; use spacetimedb::{ReducerContext, Table, 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::Lobby, turn_state: TurnState::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(mut 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, }); lobby.players.push(PlayerOrBot::Bot { id: bot.id }); ctx.db.lobby().id().update(lobby); info!("added bot {} to lobby {}", bot.id, lobby_id); Ok(()) } else { Err("lobby doesn't exist".into()) } } #[reducer] pub fn set_ready(ctx: &ReducerContext, ready: bool) { let mut player = ctx.db.player().identity().find(ctx.sender).unwrap(); player.ready = ready; let player = ctx.db.player().identity().update(player); } #[reducer] pub fn start_game(ctx: &ReducerContext) { let player = ctx.db.player().identity().find(ctx.sender).unwrap(); if let Some(mut lobby) = ctx.db.lobby().host_player_id().find(player.id) && lobby.players.len() == 4 && lobby.players.iter().all(|p| match p { PlayerOrBot::Player { id } => ctx.db.player().id().find(id).is_some_and(|p| p.ready), PlayerOrBot::Bot { id } => ctx.db.bot().id().find(id).is_some(), }) { lobby.game_state = GameState::Deal; ctx.db.lobby().id().update(lobby); } }