partialy draw a tile

wind assignment and turn ordering
This commit is contained in:
Tao Tien 2026-02-13 06:10:09 -08:00
parent b9c653f3a2
commit 63e21713ab
14 changed files with 189 additions and 38 deletions

View file

@ -8,8 +8,9 @@ use bevy_spacetimedb::{
use spacetimedb::Identity;
use spacetimedb_sdk::{DbContext, Table, credentials};
use crate::game::hand::Drawn;
use crate::stdb::{
self, DbConnection, LobbyTableAccess, PlayerTableAccess, RemoteTables, add_bot,
self, DbConnection, LobbyTableAccess, PlayerTableAccess, RemoteTables, add_bot, draw_tile,
join_or_create_lobby, login_or_add_player, set_ready, shuffle_deal, start_game,
};
use crate::{
@ -146,6 +147,7 @@ fn on_player_insert_update(
.hand
.iter()
.map(|dbt| {
// TODO this seems a lil expensive
if let Some(ent) = tiles
.iter()
.find(|(_, id, _)| id.0 == dbt.id)
@ -158,6 +160,9 @@ fn on_player_insert_update(
})
.collect();
commands.entity(**hand_ent).replace_children(&tiles);
if let Some(dbt) = &msg.new.drawn_tile {
commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id), Drawn));
}
} else {
let player = Player {
name: msg
@ -179,6 +184,7 @@ fn on_lobby_insert_update(
mut commands: Commands,
mut next_gamestate: ResMut<NextState<GameState>>,
mut next_turnstate: ResMut<NextState<TurnState>>,
) {
for msg in messages.read() {
// trace!("on_lobby_insert_update msg:\n{:#?}", msg.new);
@ -214,6 +220,18 @@ fn on_lobby_insert_update(
}
stdb::GameState::Play => {
trace!("game entered play");
match msg.new.turn_state {
stdb::TurnState::None => {}
stdb::TurnState::Tsumo => {
stdb.reducers().draw_tile().unwrap();
}
stdb::TurnState::Menzen => todo!(),
stdb::TurnState::RiichiKan => todo!(),
stdb::TurnState::Discard => todo!(),
stdb::TurnState::RonChiiPonKan => todo!(),
stdb::TurnState::End => todo!(),
}
next_turnstate.set(msg.new.turn_state.into());
}
stdb::GameState::Exit => {
trace!("game enetered exit");

View file

@ -21,14 +21,13 @@ fn creds_store() -> credentials::File {
impl From<stdb::GameState> for jong_types::GameState {
fn from(value: stdb::GameState) -> Self {
match value {
stdb::GameState::None => Self::None,
stdb::GameState::Lobby => Self::Lobby,
stdb::GameState::Setup => Self::Setup,
stdb::GameState::Deal => Self::Deal,
stdb::GameState::Play => Self::Play,
stdb::GameState::Exit => Self::Exit,
}
Self::from_repr(value as usize).unwrap()
}
}
impl From<stdb::TurnState> for jong_types::TurnState {
fn from(value: stdb::TurnState) -> Self {
Self::from_repr(value as usize).unwrap()
}
}

View file

@ -0,0 +1,100 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub(super) struct DrawTileArgs {}
impl From<DrawTileArgs> for super::Reducer {
fn from(args: DrawTileArgs) -> Self {
Self::DrawTile
}
}
impl __sdk::InModule for DrawTileArgs {
type Module = super::RemoteModule;
}
pub struct DrawTileCallbackId(__sdk::CallbackId);
#[allow(non_camel_case_types)]
/// Extension trait for access to the reducer `draw_tile`.
///
/// Implemented for [`super::RemoteReducers`].
pub trait draw_tile {
/// Request that the remote module invoke the reducer `draw_tile` to run as soon as possible.
///
/// This method returns immediately, and errors only if we are unable to send the request.
/// The reducer will run asynchronously in the future,
/// and its status can be observed by listening for [`Self::on_draw_tile`] callbacks.
fn draw_tile(&self) -> __sdk::Result<()>;
/// Register a callback to run whenever we are notified of an invocation of the reducer `draw_tile`.
///
/// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`]
/// to determine the reducer's status.
///
/// The returned [`DrawTileCallbackId`] can be passed to [`Self::remove_on_draw_tile`]
/// to cancel the callback.
fn on_draw_tile(
&self,
callback: impl FnMut(&super::ReducerEventContext) + Send + 'static,
) -> DrawTileCallbackId;
/// Cancel a callback previously registered by [`Self::on_draw_tile`],
/// causing it not to run in the future.
fn remove_on_draw_tile(&self, callback: DrawTileCallbackId);
}
impl draw_tile for super::RemoteReducers {
fn draw_tile(&self) -> __sdk::Result<()> {
self.imp.call_reducer("draw_tile", DrawTileArgs {})
}
fn on_draw_tile(
&self,
mut callback: impl FnMut(&super::ReducerEventContext) + Send + 'static,
) -> DrawTileCallbackId {
DrawTileCallbackId(self.imp.on_reducer(
"draw_tile",
Box::new(move |ctx: &super::ReducerEventContext| {
#[allow(irrefutable_let_patterns)]
let super::ReducerEventContext {
event:
__sdk::ReducerEvent {
reducer: super::Reducer::DrawTile {},
..
},
..
} = ctx
else {
unreachable!()
};
callback(ctx)
}),
))
}
fn remove_on_draw_tile(&self, callback: DrawTileCallbackId) {
self.imp.remove_on_reducer("draw_tile", callback.0)
}
}
#[allow(non_camel_case_types)]
#[doc(hidden)]
/// Extension trait for setting the call-flags for the reducer `draw_tile`.
///
/// Implemented for [`super::SetReducerFlags`].
///
/// This type is currently unstable and may be removed without a major version bump.
pub trait set_flags_for_draw_tile {
/// Set the call-reducer flags for the reducer `draw_tile` to `flags`.
///
/// This type is currently unstable and may be removed without a major version bump.
fn draw_tile(&self, flags: __ws::CallReducerFlags);
}
impl set_flags_for_draw_tile for super::SetReducerFlags {
fn draw_tile(&self, flags: __ws::CallReducerFlags) {
self.imp.set_call_reducer_flags("draw_tile", flags);
}
}

View file

@ -12,6 +12,7 @@ pub mod bot_type;
pub mod db_tile_type;
pub mod db_wall_type;
pub mod dragon_type;
pub mod draw_tile_reducer;
pub mod game_state_type;
pub mod join_or_create_lobby_reducer;
pub mod lobby_table;
@ -37,6 +38,7 @@ pub use bot_type::Bot;
pub use db_tile_type::DbTile;
pub use db_wall_type::DbWall;
pub use dragon_type::Dragon;
pub use draw_tile_reducer::{draw_tile, set_flags_for_draw_tile, DrawTileCallbackId};
pub use game_state_type::GameState;
pub use join_or_create_lobby_reducer::{
join_or_create_lobby, set_flags_for_join_or_create_lobby, JoinOrCreateLobbyCallbackId,
@ -69,6 +71,7 @@ pub use wind_type::Wind;
pub enum Reducer {
AddBot { lobby_id: u32 },
DrawTile,
JoinOrCreateLobby { lobby_id: u32 },
LoginOrAddPlayer,
SetReady { ready: bool },
@ -84,6 +87,7 @@ impl __sdk::Reducer for Reducer {
fn reducer_name(&self) -> &'static str {
match self {
Reducer::AddBot { .. } => "add_bot",
Reducer::DrawTile => "draw_tile",
Reducer::JoinOrCreateLobby { .. } => "join_or_create_lobby",
Reducer::LoginOrAddPlayer => "login_or_add_player",
Reducer::SetReady { .. } => "set_ready",
@ -102,6 +106,13 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer {
&value.args,
)?
.into()),
"draw_tile" => Ok(
__sdk::parse_reducer_args::<draw_tile_reducer::DrawTileArgs>(
"draw_tile",
&value.args,
)?
.into(),
),
"join_or_create_lobby" => Ok(__sdk::parse_reducer_args::<
join_or_create_lobby_reducer::JoinOrCreateLobbyArgs,
>("join_or_create_lobby", &value.args)?

View file

@ -17,6 +17,7 @@ pub struct Player {
pub sort: bool,
pub hand: Vec<DbTile>,
pub pond: Vec<DbTile>,
pub drawn_tile: Option<DbTile>,
}
impl __sdk::InModule for Player {

View file

@ -10,7 +10,7 @@ use jong::game::{
hand::{Drawn, Hand},
player::{CurrentPlayer, Player},
};
use jong_types::GameState;
use jong_types::{GameState, TurnState};
mod input;
mod layout;
@ -82,7 +82,10 @@ impl Plugin for TuiPlugin {
(input::keyboard, input::mouse).in_set(TuiSet::Input),
)
.add_systems(Update, layout::layout.in_set(TuiSet::Layout))
.add_systems(Update, discard_tile.run_if(in_state(GameState::Play)))
.add_systems(
Update,
discard_tile.run_if(in_state(GameState::Play).and(in_state(TurnState::Tsumo))),
)
.add_systems(
Update,
(

View file

@ -126,7 +126,7 @@ pub(crate) fn render_hands(
curr_player: Single<Entity, With<CurrentPlayer>>,
players: Query<(&Player, Entity, &Children)>,
hands: Query<(&Children, Entity), With<Hand>>,
// drawn_tile: Single<Entity, With<Drawn>>,
drawn_tile: Single<Entity, With<Drawn>>,
) -> Result {
let mut frame = tui.get_frame();
debug_blocks(*layouts, &mut frame);
@ -196,24 +196,24 @@ pub(crate) fn render_hands(
// tsumo tile
// if this_drawer {
// // trace!("this_drawer");
// let mut area = drawn_area.resize(Size {
// width: 5,
// height: 4,
// });
// area = area.offset(Offset { x: 2, y: 0 });
// let hovered = hovered.contains(*drawn_tile);
// let widget = render_tile(tiles.get(*drawn_tile)?, hovered);
// if hovered {
// area = area.offset(Offset { x: 0, y: -1 });
// let mut hitbox = area.as_size();
// hitbox.height += 1;
// commands.entity(*drawn_tile).insert(PickRegion {
// area: area.resize(hitbox),
// });
// } else {
// commands.entity(*drawn_tile).insert(PickRegion { area });
// }
// frame.render_widget(widget, area);
let mut area = drawn_area.resize(Size {
width: 5,
height: 4,
});
area = area.offset(Offset { x: 2, y: 0 });
let hovered = hovered.contains(*drawn_tile);
let widget = render_tile(tiles.get(*drawn_tile)?, hovered);
if hovered {
area = area.offset(Offset { x: 0, y: -1 });
let mut hitbox = area.as_size();
hitbox.height += 1;
commands.entity(*drawn_tile).insert(PickRegion {
area: area.resize(hitbox),
});
} else {
commands.entity(*drawn_tile).insert(PickRegion { area });
}
frame.render_widget(widget, area);
// }
// TODO draw melds
// } else {