various smol changes

This commit is contained in:
Tao Tien 2026-03-02 20:27:56 -08:00
parent bf23dbaf80
commit 0713d6869b
13 changed files with 108 additions and 93 deletions

View file

@ -1,2 +1,2 @@
jong-db
jong-db/src/db
bevy_spacetimedb

View file

@ -4,6 +4,7 @@
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::db_tile_type::DbTile;
use super::player_or_bot_type::PlayerOrBot;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
@ -11,6 +12,7 @@ use super::player_or_bot_type::PlayerOrBot;
pub struct HandView {
pub player: PlayerOrBot,
pub hand_length: u8,
pub pond: Vec<DbTile>,
pub drawn: bool,
}
@ -24,6 +26,7 @@ impl __sdk::InModule for HandView {
pub struct HandViewCols {
pub player: __sdk::__query_builder::Col<HandView, PlayerOrBot>,
pub hand_length: __sdk::__query_builder::Col<HandView, u8>,
pub pond: __sdk::__query_builder::Col<HandView, Vec<DbTile>>,
pub drawn: __sdk::__query_builder::Col<HandView, bool>,
}
@ -33,6 +36,7 @@ impl __sdk::__query_builder::HasCols for HandView {
HandViewCols {
player: __sdk::__query_builder::Col::new(table_name, "player"),
hand_length: __sdk::__query_builder::Col::new(table_name, "hand_length"),
pond: __sdk::__query_builder::Col::new(table_name, "pond"),
drawn: __sdk::__query_builder::Col::new(table_name, "drawn"),
}
}

View file

@ -2,6 +2,7 @@
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use super::db_tile_type::DbTile;
use super::hand_view_type::HandView;
use super::player_or_bot_type::PlayerOrBot;
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};

View file

@ -121,7 +121,7 @@ pub fn advance_game_private(ctx: &ReducerContext, mut game_timer: GameTimer) ->
let mut hand = ctx.db.player_hand().player_id().find(player_id).unwrap();
match hand.turn_state {
TurnState::None => {
trace!("draw a tile");
// trace!("draw a tile");
if let Some(mut wall) = ctx.db.wall().lobby_id().find(lobby.id)
&& let Some(tile) = wall.tiles.pop()
{

View file

@ -68,7 +68,7 @@ pub fn add_bot(ctx: &ReducerContext, lobby_id: u32) -> Result<(), String> {
info!("added bot {} to lobby {}", bot.id, lobby_id);
Ok(())
} else {
Err("lobby doesn't exist".into())
Err(format!("lobby {lobby_id} doesn't exist or is full"))
}
}

View file

@ -129,11 +129,12 @@ fn view_hand(ctx: &ViewContext) -> Option<PlayerHand> {
.and_then(|p| ctx.db.player_hand().player_id().find(p.id))
}
#[derive(SpacetimeType, Clone, Copy)]
#[derive(SpacetimeType, Clone)]
pub struct HandView {
pub player: PlayerOrBot,
pub hand_length: u8,
// pub melds: u8,
pub pond: Vec<DbTile>,
pub drawn: bool,
}
@ -151,6 +152,7 @@ fn view_closed_hands(ctx: &ViewContext) -> Vec<HandView> {
Some(HandView {
player,
hand_length: player_hand.hand.len() as u8,
pond: player_hand.pond,
drawn: player_hand.turn_state == TurnState::Tsumo
&& player_hand.working_tile.is_some(),
})
@ -163,6 +165,7 @@ fn view_closed_hands(ctx: &ViewContext) -> Vec<HandView> {
Some(HandView {
player,
hand_length: bot.hand.len() as u8,
pond: bot.pond,
drawn: bot.turn_state == TurnState::Tsumo && bot.working_tile.is_some(),
})
} else {

View file

@ -1,6 +1,7 @@
use std::time::Duration;
use bevy::prelude::*;
use bevy::render::render_resource::AsBindGroupShaderType;
use bevy_spacetimedb::{ReadInsertMessage, ReadInsertUpdateMessage, ReadUpdateMessage, StdbPlugin};
use jong_db::{
@ -47,13 +48,18 @@ impl Plugin for Riichi {
.add_sub_state::<jong_types::states::TurnState>()
.add_message::<SyncPlayer>()
.add_message::<SyncOpenHand>()
.add_message::<SyncBot>()
.add_systems(Startup, subscriptions)
.add_systems(Update, (connection::on_connect, connection::on_disconnect))
.add_systems(
Update,
(
(on_player_insert_update, on_lobby_insert_update),
(sync_player),
(
on_lobby_insert_update,
on_player_insert_update,
on_bot_insert_update,
),
(sync_player, sync_bot),
),
)
.add_systems(
@ -112,6 +118,9 @@ fn subscriptions(stdb: SpacetimeDB, mut commands: Commands) {
#[derive(Message)]
struct SyncPlayer(u32);
#[derive(Message)]
struct SyncBot(u32);
#[derive(Message)]
struct SyncOpenHand(u32);
@ -153,6 +162,14 @@ fn sync_player(
}
}
fn sync_bot(
stdb: SpacetimeDB,
mut messages: MessageReader<SyncBot>,
mut commands: Commands,
players: Query<(Entity, &Player)>,
) {
}
fn sync_open_hand(
stdb: SpacetimeDB,
@ -183,7 +200,7 @@ fn sync_open_hand(
});
let pond_ent = ponds
.iter()
.find_map(|(e, h)| (h.owner == PlayerOrBot::Player { id: *id }).then_some(e))
.find_map(|(e, p)| (p.owner == PlayerOrBot::Player { id: *id }).then_some(e))
.unwrap_or_else(|| {
commands
.spawn(Pond {
@ -230,12 +247,52 @@ fn sync_open_hand(
fn sync_closed_hand(
stdb: SpacetimeDB,
mut events: MessageReader<SyncClosedHand>,
mut messages: MessageReader<SyncClosedHand>,
mut commands: Commands,
hands: Query<&mut Closed, With<Hand>>,
ponds: Query<&mut Children, With<Pond>>,
tiles: Query<(Entity, &TileId)>,
hands: Query<(Entity, &mut Closed, &Hand)>,
ponds: Query<(Entity, &Pond)>,
) {
for SyncClosedHand(id) in messages.read() {
let Some(hand_view) = stdb
.db()
.view_closed_hands()
.iter()
.find(|hand| PlayerOrBot::from(&hand.player) == *id)
else {
todo!()
};
let hand_ent = hands
.iter()
.find_map(|(e, c, h)| (h.owner == *id).then_some(e))
.unwrap_or_else(|| commands.spawn(Hand { owner: *id }).id());
let pond_ent = ponds
.iter()
.find_map(|(e, p)| (p.owner == *id).then_some(e))
.unwrap_or_else(|| commands.spawn(Pond { owner: *id }).id());
let pond: Vec<Entity> = hand_view
.pond
.iter()
.map(|dbt| {
tiles
.iter()
.find_map(|(e, i)| (i.0 == dbt.id).then_some(e))
.unwrap_or_else(|| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id())
})
.collect();
commands.entity(hand_ent).insert(Closed {
length: hand_view.hand_length,
});
commands.entity(pond_ent).replace_children(&pond);
if hand_view.drawn {
commands.spawn(Drawn);
}
}
}
fn sync_player_clock() {}
@ -251,7 +308,19 @@ fn on_player_insert_update(
}
}
fn on_bot_insert_update() {}
fn on_bot_insert_update(
mut db_messages: ReadInsertUpdateMessage<jong_db::Bot>,
mut writer: MessageWriter<SyncBot>,
) {
for msg in db_messages.read() {
writer.write(SyncBot(msg.new.id));
}
}
#[derive(Resource)]
struct Lobby {
players: Vec<PlayerOrBot>,
}
fn on_lobby_insert_update(
stdb: SpacetimeDB,
@ -272,10 +341,10 @@ fn on_lobby_insert_update(
match msg.new.game_state {
jong_db::GameState::None => {
trace!("game entered none");
// trace!("game entered none");
}
jong_db::GameState::Lobby => {
trace!("game entered lobby");
// trace!("game entered lobby");
if !player.ready {
for _ in 0..3 {
stdb.reducers().add_bot(player.lobby_id).unwrap();
@ -285,16 +354,16 @@ fn on_lobby_insert_update(
}
}
jong_db::GameState::Setup => {
trace!("game entered setup");
// trace!("game entered setup");
}
jong_db::GameState::Deal => {
trace!("game entered deal");
// trace!("game entered deal");
}
jong_db::GameState::Play => {
trace!("game entered play");
// trace!("game entered play");
}
jong_db::GameState::Exit => {
trace!("game enetered exit");
// trace!("game enetered exit");
}
}
@ -315,71 +384,9 @@ fn on_view_hand_insert(
fn on_view_hand_update(
mut messages: ReadUpdateMessage<jong_db::PlayerHand>,
mut writer: MessageWriter<SyncOpenHand>,
// mut commands: Commands,
// tiles: Query<(Entity, &TileId)>,
// main_player: Single<(Entity, &Children), With<MainPlayer>>,
// hand: Query<Entity, With<Hand>>,
// pond: Query<Entity, With<Pond>>,
// // drawn: Option<Single<Entity, With<Drawn>>>,
// mut next_turnstate: ResMut<NextState<jong_types::states::TurnState>>,
) {
// TODO can this and similar run at startup or on play/reconnect?
for msg in messages.read() {
trace!("on_view_hand_update");
writer.write(SyncOpenHand(msg.new.player_id));
}
// let hand_tiles: Vec<_> = msg
// .new
// .hand
// .iter()
// .map(|dbt| {
// tiles
// .iter()
// .find_map(|(e, t)| if *t == TileId(dbt.id) { Some(e) } else { None })
// .unwrap_or_else(|| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id())
// })
// .collect();
// let pond_tiles: Vec<_> = msg
// .new
// .pond
// .iter()
// .map(|dbt| {
// tiles
// .iter()
// .find_map(|(e, t)| if *t == TileId(dbt.id) { Some(e) } else { None })
// .unwrap_or_else(|| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id())
// })
// .collect();
// commands
// .entity(hand.iter().find(|e| main_player.1.contains(e)).unwrap())
// .replace_children(&hand_tiles);
// commands
// .entity(pond.iter().find(|e| main_player.1.contains(e)).unwrap())
// .replace_children(&pond_tiles);
// match msg.new.turn_state {
// jong_db::TurnState::None => {
// trace!("turnstate none");
// // TODO do we reconcile hand state here or in ::End?
// }
// jong_db::TurnState::Tsumo => {
// trace!("turnstate tsumo");
// let dbt = msg
// .new
// .working_tile
// .as_ref()
// .expect("entered tsumo without a drawn tile");
// commands.spawn((Drawn, Tile::from(&dbt.tile), TileId(dbt.id)));
// }
// jong_db::TurnState::Menzen => todo!(),
// jong_db::TurnState::RiichiKan => todo!(),
// jong_db::TurnState::RonChiiPonKan => todo!(),
// jong_db::TurnState::End => todo!(),
// }
// next_turnstate.set(msg.new.turn_state.into());
// }
}

View file

@ -23,7 +23,6 @@ pub struct Hand {
#[derive(Component)]
pub struct Closed {
pub(crate) owner: PlayerOrBot,
pub(crate) length: u8,
}
@ -34,6 +33,3 @@ pub struct Pond {
#[derive(Component)]
pub struct Drawn;
#[derive(Component)]
pub struct Discarded;

View file

@ -104,13 +104,12 @@ fn discard_tile(
mut commands: Commands,
// main_player: Single<&Children, With<MainPlayer>>,
// only main player will have a Drawn tile?
// only main player will have a Drawn tile with TileId?
drawn: Single<(Entity, &TileId), With<Drawn>>,
tiles: Query<&TileId>,
) {
// TODO disable this when we're not current player?
if let Ok(tile_id) = tiles.get(selected.0) {
trace!("{:?}, {tile_id:?}", selected.0);
stdb.reducers().discard_tile(tile_id.0).unwrap();
stdb.reducers().advance_game().unwrap();
commands.entity(drawn.0).remove::<Drawn>();

View file

@ -1,11 +1,12 @@
use bevy::prelude::*;
use bevy_ratatui::crossterm::event::KeyCode;
use bevy_ratatui::event::KeyMessage;
use jong_db::PlayerTableAccess;
use jong_db::join_or_create_lobby;
use tui_logger::TuiWidgetEvent;
use jong::SpacetimeDB;
use jong_db::PlayerTableAccess;
use jong_db::join_or_create_lobby;
use jong_types::GameState;
use crate::tui::layout::Overlays;
use crate::tui::states::ConsoleWidget;
@ -38,6 +39,11 @@ pub(crate) fn keyboard(
}
}
if *curr_gamestate.get() != GameState::None {
next_tuistate.set(TuiState::InGame);
continue;
}
match curr_tuistate.get() {
TuiState::MainMenu => match key {
KeyCode::Char('p') => {

View file

@ -152,17 +152,17 @@ pub(crate) fn render_main_hand(
main_player: Single<&Player, With<MainPlayer>>,
hand: Query<(&Hand, &Children)>,
hands: Query<(&Hand, &Children)>,
drawn_tile: Option<Single<Entity, With<Drawn>>>,
) -> Result {
let mut frame = tui.get_frame();
debug_blocks(layouts.clone(), &mut frame);
if hand.is_empty() {
if hands.is_empty() {
return Ok(());
}
let hand: Vec<_> = hand
let hand: Vec<_> = hands
.iter()
.find_map(|(h, c)| (main_player.id == h.owner).then_some(c))
.unwrap()

View file

@ -18,7 +18,7 @@ spacetime:
devenv up
spacetime_dev:
spacetime dev --module-bindings-path jong-db/src/db jong-line --delete-data=always --yes --server-only
spacetime dev --module-bindings-path jong-db/src/db jong-line --delete-data=on-conflict --yes --server-only
spacetime_generate-bindings:
spacetime generate --lang rust --out-dir jong-db/src/db --module-path jong-line

View file

@ -2,7 +2,6 @@
"dev": {
"run": ""
},
"_source-config": "spacetime.local.json",
"module-path": "jong-line",
"server": "local",
"database": "jong-line"