state advancer reducer

This commit is contained in:
Tao Tien 2026-02-20 15:36:04 -08:00
parent c12667938e
commit e2c9c815ec
44 changed files with 2063 additions and 773 deletions

View file

@ -1,3 +1,5 @@
use std::time::Duration;
use log::info;
use spacetimedb::{ReducerContext, Table, rand::seq::SliceRandom, reducer};
@ -5,18 +7,16 @@ use crate::tables::*;
#[reducer]
pub fn join_or_create_lobby(ctx: &ReducerContext, mut lobby_id: u32) -> Result<(), String> {
let ok_or = ctx
let mut player = 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: jong_types::states::GameState::Lobby,
dealer_idx: 0,
@ -49,7 +49,8 @@ pub fn add_bot(ctx: &ReducerContext, lobby_id: u32) -> Result<(), String> {
lobby_id,
hand: vec![],
pond: vec![],
drawn_tile: None,
working_tile: None,
turn_state: jong_types::TurnState::None,
});
lobby.players.push(PlayerOrBot::Bot { id: bot.id });
ctx.db.lobby().id().update(lobby);
@ -61,29 +62,33 @@ pub fn add_bot(ctx: &ReducerContext, lobby_id: u32) -> Result<(), String> {
}
#[reducer]
pub fn set_ready(ctx: &ReducerContext, ready: bool) {
pub fn set_ready(ctx: &ReducerContext, ready: bool) -> Result<(), String> {
let mut player = ctx.db.player().identity().find(ctx.sender).unwrap();
player.ready = ready;
player = ctx.db.player().identity().update(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)
if let Some(mut lobby) = ctx.db.lobby().id().find(player.lobby_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(),
})
&& ctx.db.player().lobby_id().filter(lobby.id).all(|p| p.ready)
{
lobby.game_state = jong_types::states::GameState::Setup;
lobby.players.shuffle(&mut ctx.rng());
lobby.dealer_idx += 1;
if lobby.dealer_idx > 3 {
lobby.dealer_idx = 0;
}
ctx.db.lobby().id().update(lobby);
let lobby = ctx.db.lobby().id().update(lobby);
// TODO should we schedule this outside so that we can clear out stale lobbies?
ctx.db.game_timer().insert(GameTimer {
id: 0,
lobby_id: lobby.id,
scheduled_at: spacetimedb::ScheduleAt::Interval(Duration::from_secs(1).into()),
});
} else {
// if lobby doesn't exist, reset player state
player.lobby_id = 0;
player.ready = false;
player = ctx.db.player().identity().update(player);
return Err(format!("couldn't find lobby with id: {}", player.lobby_id));
}
Ok(())
}