discard out of hand, many new bugs

This commit is contained in:
Tao Tien 2026-02-15 08:45:42 -08:00
parent f71e32b0b9
commit 4a833da757
3 changed files with 111 additions and 126 deletions

View file

@ -31,13 +31,6 @@ pub mod player;
pub mod round; pub mod round;
pub mod wall; pub mod wall;
#[derive(Message)]
pub enum GameMessage {
Discarded(Entity),
CallPending,
Called { player: Entity, calltype: Entity },
}
pub struct Riichi; pub struct Riichi;
impl Plugin for Riichi { impl Plugin for Riichi {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
@ -66,7 +59,6 @@ impl Plugin for Riichi {
.add_sub_state::<TurnState>() .add_sub_state::<TurnState>()
// .init_resource::<round::MatchSettings>() // .init_resource::<round::MatchSettings>()
// .init_resource::<round::Compass>() // .init_resource::<round::Compass>()
.add_message::<GameMessage>()
// .add_systems(Startup, tile::init_tiles) // .add_systems(Startup, tile::init_tiles)
// .add_systems(Update, hand::sort_hands.run_if(in_state(GameState::Play))) // .add_systems(Update, hand::sort_hands.run_if(in_state(GameState::Play)))
// .add_systems(OnEnter(TurnState::Tsumo), round::tsumo) // .add_systems(OnEnter(TurnState::Tsumo), round::tsumo)
@ -91,6 +83,9 @@ impl Plugin for Riichi {
fn on_connect(stdb: SpacetimeDB, mut messages: ReadStdbConnectedMessage, mut commands: Commands) { fn on_connect(stdb: SpacetimeDB, mut messages: ReadStdbConnectedMessage, mut commands: Commands) {
for msg in messages.read() { for msg in messages.read() {
info!("you're now jongline"); info!("you're now jongline");
while stdb.try_identity().is_none() {}
debug!("with identity: {}", stdb.identity()); debug!("with identity: {}", stdb.identity());
creds_store() creds_store()
.save(&msg.access_token) .save(&msg.access_token)

View file

@ -6,7 +6,7 @@ use strum::{EnumCount, FromRepr};
use crate::{ use crate::{
EnumNextCycle, EnumNextCycle,
game::{ game::{
GameMessage, GameState, GameState,
hand::{Discarded, Drawn, Hand, Pond}, hand::{Discarded, Drawn, Hand, Pond},
player::{CurrentPlayer, Player}, player::{CurrentPlayer, Player},
wall::Wall, wall::Wall,
@ -111,85 +111,85 @@ impl EnumNextCycle for TurnState {
} }
} }
pub(crate) fn tsumo( // pub(crate) fn tsumo(
mut commands: Commands, // mut commands: Commands,
// curr_player: Res<CurrentPlayer>, // // curr_player: Res<CurrentPlayer>,
curr_player: Single<Entity, With<CurrentPlayer>>, // curr_player: Single<Entity, With<CurrentPlayer>>,
wall: Single<Entity, With<Wall>>, // wall: Single<Entity, With<Wall>>,
walltiles: Single<&Children, With<Wall>>, // walltiles: Single<&Children, With<Wall>>,
curr_turnstate: Res<State<TurnState>>, // curr_turnstate: Res<State<TurnState>>,
mut next_turnstate: ResMut<NextState<TurnState>>, // mut next_turnstate: ResMut<NextState<TurnState>>,
) { // ) {
let drawn = walltiles.last().unwrap(); // let drawn = walltiles.last().unwrap();
commands.entity(*wall).remove_child(*drawn); // commands.entity(*wall).remove_child(*drawn);
let drawn = commands.entity(*drawn).insert(Drawn).id(); // let drawn = commands.entity(*drawn).insert(Drawn).id();
commands.entity(*curr_player).add_child(drawn); // commands.entity(*curr_player).add_child(drawn);
debug!("tsumo for: {:?}, tile: {:?}", *curr_player, drawn); // debug!("tsumo for: {:?}, tile: {:?}", *curr_player, drawn);
next_turnstate.set(curr_turnstate.next()); // next_turnstate.set(curr_turnstate.next());
} // }
pub(crate) fn menzen( // pub(crate) fn menzen(
curr_turnstate: Res<State<TurnState>>, // curr_turnstate: Res<State<TurnState>>,
mut next_turnstate: ResMut<NextState<TurnState>>, // mut next_turnstate: ResMut<NextState<TurnState>>,
) { // ) {
trace!("menzen check"); // trace!("menzen check");
next_turnstate.set(curr_turnstate.next()); // next_turnstate.set(curr_turnstate.next());
} // }
pub(crate) fn riichi_kan( // pub(crate) fn riichi_kan(
curr_turnstate: Res<State<TurnState>>, // curr_turnstate: Res<State<TurnState>>,
mut next_turnstate: ResMut<NextState<TurnState>>, // mut next_turnstate: ResMut<NextState<TurnState>>,
) { // ) {
trace!("riichi_kan"); // trace!("riichi_kan");
next_turnstate.set(curr_turnstate.next()); // next_turnstate.set(curr_turnstate.next());
} // }
#[allow(clippy::too_many_arguments, irrefutable_let_patterns)] // #[allow(clippy::too_many_arguments, irrefutable_let_patterns)]
pub(crate) fn discard( // pub(crate) fn discard(
mut commands: Commands, // mut commands: Commands,
mut reader: MessageReader<GameMessage>, // mut reader: MessageReader<GameMessage>,
curr_player: Single<Entity, With<CurrentPlayer>>, // curr_player: Single<Entity, With<CurrentPlayer>>,
players: Query<&Children, With<Player>>, // players: Query<&Children, With<Player>>,
mut hands: Query<(&Children, Entity), (With<Hand>, Without<Player>)>, // mut hands: Query<(&Children, Entity), (With<Hand>, Without<Player>)>,
drawn: Single<Entity, With<Drawn>>, // drawn: Single<Entity, With<Drawn>>,
curr_turnstate: Res<State<TurnState>>, // curr_turnstate: Res<State<TurnState>>,
mut next_turnstate: ResMut<NextState<TurnState>>, // mut next_turnstate: ResMut<NextState<TurnState>>,
) -> Result { // ) -> Result {
// trace!("discard"); // // trace!("discard");
let (handtiles, hand) = hands.get_mut(players.get(*curr_player)?.iter().next().unwrap())?; // let (handtiles, hand) = hands.get_mut(players.get(*curr_player)?.iter().next().unwrap())?;
let mut done = false; // let mut done = false;
while let Some(message) = reader.read().next() { // while let Some(message) = reader.read().next() {
if let GameMessage::Discarded(discarded) = message { // if let GameMessage::Discarded(discarded) = message {
debug!("discarded: {discarded:?}"); // debug!("discarded: {discarded:?}");
if *discarded == *drawn { // if *discarded == *drawn {
} else if handtiles.contains(discarded) { // } else if handtiles.contains(discarded) {
commands // commands
.entity(hand) // .entity(hand)
.remove_child(*discarded) // .remove_child(*discarded)
.add_child(*drawn); // .add_child(*drawn);
} else { // } else {
panic!("current hand nor drawn tile contains discarded tile") // panic!("current hand nor drawn tile contains discarded tile")
} // }
commands.entity(*drawn).remove::<Drawn>(); // commands.entity(*drawn).remove::<Drawn>();
commands.entity(*discarded).insert(Discarded); // commands.entity(*discarded).insert(Discarded);
done = true; // done = true;
break; // break;
} // }
} // }
if done { // if done {
next_turnstate.set(curr_turnstate.next()); // next_turnstate.set(curr_turnstate.next());
} // }
Ok(()) // Ok(())
} // }
#[derive(Resource)] #[derive(Resource)]
pub struct PendingCalls { pub struct PendingCalls {
@ -197,45 +197,45 @@ pub struct PendingCalls {
calls: HashMap<Entity, CallType>, calls: HashMap<Entity, CallType>,
} }
pub(crate) fn notify_callable() {} // pub(crate) fn notify_callable() {}
pub(crate) fn ron_chi_pon_kan( // pub(crate) fn ron_chi_pon_kan(
mut commands: Commands, // mut commands: Commands,
mut reader: MessageReader<GameMessage>, // mut reader: MessageReader<GameMessage>,
discarded: Single<Entity, With<Discarded>>, // discarded: Single<Entity, With<Discarded>>,
mut ponds: Query<(&Children, Entity), (With<Pond>, Without<Player>)>, // mut ponds: Query<(&Children, Entity), (With<Pond>, Without<Player>)>,
calls: Query<&CallType>, // calls: Query<&CallType>,
curr_turnstate: Res<State<TurnState>>, // curr_turnstate: Res<State<TurnState>>,
mut next_turnstate: ResMut<NextState<TurnState>>, // mut next_turnstate: ResMut<NextState<TurnState>>,
) { // ) {
// check if can call? // // check if can call?
// message players? // // message players?
// collect then prioritize // // collect then prioritize
// let mut received = vec![]; // // let mut received = vec![];
let mut received: Vec<_> = reader // let mut received: Vec<_> = reader
.read() // .read()
.filter_map(|m| { // .filter_map(|m| {
if let GameMessage::Called { player, calltype } = m // if let GameMessage::Called { player, calltype } = m
&& let Ok(calltype) = calls.get(*calltype) // && let Ok(calltype) = calls.get(*calltype)
{ // {
Some((calltype, player)) // Some((calltype, player))
} else { // } else {
None // None
} // }
}) // })
.collect(); // .collect();
// received.sort_unstable_by_key(|(c, t)| c); // // received.sort_unstable_by_key(|(c, t)| c);
// received.sort_unstable_by_key(|m| m.); // // received.sort_unstable_by_key(|m| m.);
next_turnstate.set(curr_turnstate.next()); // next_turnstate.set(curr_turnstate.next());
} // }
pub(crate) fn end( // pub(crate) fn end(
curr_turnstate: Res<State<TurnState>>, // curr_turnstate: Res<State<TurnState>>,
mut next_turnstate: ResMut<NextState<TurnState>>, // mut next_turnstate: ResMut<NextState<TurnState>>,
) { // ) {
next_turnstate.set(curr_turnstate.next()); // next_turnstate.set(curr_turnstate.next());
} // }

View file

@ -13,7 +13,6 @@ use jong::stdb::{self, discard_tile as _};
use jong::{ use jong::{
SpacetimeDB, SpacetimeDB,
game::{ game::{
GameMessage,
hand::{Drawn, Hand}, hand::{Drawn, Hand},
player::{CurrentPlayer, Player}, player::{CurrentPlayer, Player},
}, },
@ -106,7 +105,6 @@ impl Plugin for TuiPlugin {
fn discard_tile( fn discard_tile(
stdb: SpacetimeDB, stdb: SpacetimeDB,
mut writer: MessageWriter<GameMessage>,
mut selected: MessageReader<ConfirmSelect>, mut selected: MessageReader<ConfirmSelect>,
mut commands: Commands, mut commands: Commands,
@ -115,8 +113,8 @@ fn discard_tile(
// player_hands: Populated<(&Player, &Children), With<Hand>>, // player_hands: Populated<(&Player, &Children), With<Hand>>,
// hands: Populated<&Children, (With<Hand>, Without<Player>)>, // hands: Populated<&Children, (With<Hand>, Without<Player>)>,
main_player: Single<(&Player, Entity), With<MainPlayer>>, main_player: Single<(&Player, Entity), With<MainPlayer>>,
hands: Query<(&mut Children, Entity), With<Hand> >, hands: Query<(&Children, Entity), With<Hand>>,
tiles: Populated<&TileId>, tiles: Query<&TileId>,
) { ) {
// trace!("discard_tile"); // trace!("discard_tile");
@ -125,17 +123,9 @@ fn discard_tile(
while let Some(message) = selected.read().next() while let Some(message) = selected.read().next()
// && (message.0 == drawn.0 || hand.contains(&message.0)) // && (message.0 == drawn.0 || hand.contains(&message.0))
{ {
if message.0 == drawn.0 { if let Ok(tile_id) = tiles.get(message.0) {
stdb.reducers().discard_tile(drawn.1.0).unwrap(); stdb.reducers().discard_tile(tile_id.0).unwrap();
// commands.get_entity(drawn.0).unwrap().remove_parent_in_place();
commands.get_entity(drawn.0).unwrap().despawn(); commands.get_entity(drawn.0).unwrap().despawn();
} else if let Some(tile_ent) = hand.iter().find(|t| *t == message.0) {
stdb.reducers()
.discard_tile(tiles.get(tile_ent).unwrap().0)
.unwrap();
} }
// FIXME check if discard actually in hand?
writer.write(GameMessage::Discarded(message.0));
} }
} }