begin better spawn logic
This commit is contained in:
parent
71ec40ee29
commit
7ffef5522b
4 changed files with 267 additions and 253 deletions
|
|
@ -1,10 +1,9 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy_spacetimedb::{
|
||||
ReadInsertMessage, ReadInsertUpdateMessage, ReadStdbConnectedMessage,
|
||||
ReadStdbDisconnectedMessage, ReadUpdateMessage, StdbPlugin,
|
||||
};
|
||||
use bevy_spacetimedb::{ReadInsertMessage, ReadInsertUpdateMessage, ReadUpdateMessage, StdbPlugin};
|
||||
|
||||
use jong_db::{self, GameTimerTableAccess, add_bot, advance_game, set_ready};
|
||||
use jong_db::{
|
||||
self, GameTimerTableAccess, PlayerClockTableAccess, add_bot, advance_game, set_ready,
|
||||
};
|
||||
use jong_db::{
|
||||
BotTableAccess, DbConnection, LobbyTableAccess, PlayerHand, PlayerTableAccess, RemoteTables,
|
||||
ViewClosedHandsTableAccess, ViewHandTableAccess,
|
||||
|
|
@ -12,6 +11,7 @@ use jong_db::{
|
|||
use jong_types::*;
|
||||
use spacetimedb_sdk::Table;
|
||||
|
||||
mod connection;
|
||||
pub mod player;
|
||||
use crate::riichi::player::*;
|
||||
use crate::{SpacetimeDB, creds_store};
|
||||
|
|
@ -23,8 +23,10 @@ impl Plugin for Riichi {
|
|||
.with_uri("http://localhost:3000")
|
||||
.with_module_name("jong-line")
|
||||
.with_run_fn(DbConnection::run_threaded)
|
||||
.add_table(RemoteTables::player)
|
||||
.add_table(RemoteTables::lobby)
|
||||
.add_table(RemoteTables::player)
|
||||
.add_table(RemoteTables::bot)
|
||||
.add_table(RemoteTables::player_clock)
|
||||
// TODO check bevy_spacetimedb PR status
|
||||
.add_view_with_pk(RemoteTables::view_hand, |p| p.id)
|
||||
.add_view_with_pk(RemoteTables::view_closed_hands, |p| {
|
||||
|
|
@ -41,50 +43,42 @@ impl Plugin for Riichi {
|
|||
app.add_plugins(plugins)
|
||||
.init_state::<jong_types::states::GameState>()
|
||||
.add_sub_state::<jong_types::states::TurnState>()
|
||||
.add_message::<SyncPlayer>()
|
||||
.add_message::<SyncOpenHand>()
|
||||
.add_systems(Startup, subscriptions)
|
||||
.add_observer(on_subscribed) // TODO fire once then get removed? or keep around for reconnect logic?
|
||||
.add_systems(Update, (on_connect, on_disconnect))
|
||||
.add_systems(Update, (on_lobby_insert_update, on_player_insert_update))
|
||||
.add_systems(Update, (connection::on_connect, connection::on_disconnect))
|
||||
.add_systems(
|
||||
Update,
|
||||
(on_view_hand_insert, on_view_hand_update)
|
||||
(
|
||||
(on_player_insert_update, on_lobby_insert_update),
|
||||
(sync_player),
|
||||
),
|
||||
)
|
||||
.add_systems(
|
||||
Update,
|
||||
((on_view_hand_insert, on_view_hand_update), (sync_open_hand))
|
||||
.run_if(in_state(GameState::Play).or(in_state(GameState::Deal))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_connect(stdb: SpacetimeDB, mut messages: ReadStdbConnectedMessage) {
|
||||
for msg in messages.read() {
|
||||
info!("you're now jongline");
|
||||
|
||||
// FIXME hack that doesn't work for startup crash?
|
||||
while stdb.try_identity().is_none() {}
|
||||
|
||||
debug!("with identity: {}", stdb.identity());
|
||||
creds_store()
|
||||
.save(&msg.access_token)
|
||||
.expect("i/o error saving token");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO how reconnect?
|
||||
fn on_disconnect(_stdb: SpacetimeDB, mut messages: ReadStdbDisconnectedMessage) {
|
||||
for msg in messages.read() {
|
||||
warn!("lost connection: {:#?}", msg.err);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO we can make this hold more info in the future
|
||||
#[derive(Event)]
|
||||
struct Subscribed;
|
||||
/// on subscribe we need to check:
|
||||
/// if we're in a game already
|
||||
/// spawn (restore) all current game state
|
||||
/// spawn all players and hands
|
||||
/// else
|
||||
/// spawn self player
|
||||
/// then
|
||||
/// wait for lobbies
|
||||
/// spawn other players
|
||||
/// spawn all hands and ponds
|
||||
|
||||
fn subscriptions(stdb: SpacetimeDB, mut commands: Commands) {
|
||||
// commands.queue(command);
|
||||
let (send, recv) = std::sync::mpsc::channel::<Subscribed>();
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
stdb.subscription_builder()
|
||||
.on_applied(move |_| {
|
||||
trace!("subs succeeded");
|
||||
send.send(Subscribed).unwrap();
|
||||
tx.send(()).unwrap();
|
||||
})
|
||||
.on_error(|_, err| {
|
||||
error!("subs failed: {err}");
|
||||
|
|
@ -95,158 +89,164 @@ fn subscriptions(stdb: SpacetimeDB, mut commands: Commands) {
|
|||
"SELECT p.* FROM player p WHERE p.identity = '{}'",
|
||||
stdb.identity()
|
||||
),
|
||||
"SELECT p.* FROM player p JOIN lobby l ON p.lobby_id = l.id".to_string(),
|
||||
// TODO add filter for lobby id for all of these later
|
||||
"SELECT l.* FROM lobby l JOIN player p ON l.id = p.lobby_id".to_string(),
|
||||
"SELECT p.* FROM player p JOIN lobby l ON p.lobby_id = l.id".to_string(),
|
||||
"SELECT c.* FROM player_clock c JOIN player p ON c.player_id = p.id".to_string(),
|
||||
"SELECT b.* FROM bot b JOIN lobby l ON l.id = b.lobby_id".to_string(),
|
||||
"SELECT * FROM view_hand".to_string(),
|
||||
"SELECT * FROM view_closed_hands".to_string(),
|
||||
]);
|
||||
|
||||
while let Ok(event) = recv.recv() {
|
||||
commands.trigger(event);
|
||||
while let Ok(()) = rx.recv() {
|
||||
// todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// spawns entities to be consistent with server state
|
||||
// TODO figure out a way to call this for later changes in the various on_ins_upd systems
|
||||
fn on_subscribed(
|
||||
_event: On<Subscribed>,
|
||||
#[derive(Message)]
|
||||
struct SyncPlayer(u32);
|
||||
|
||||
#[derive(Message)]
|
||||
struct SyncOpenHand(u32);
|
||||
|
||||
#[derive(Message)]
|
||||
struct SyncClosedHand(PlayerOrBot);
|
||||
|
||||
#[derive(Message)]
|
||||
struct SyncPlayerClock(u32);
|
||||
|
||||
fn sync_player(
|
||||
stdb: SpacetimeDB,
|
||||
|
||||
mut messages: MessageReader<SyncPlayer>,
|
||||
mut commands: Commands,
|
||||
mut next_gamestate: ResMut<NextState<GameState>>,
|
||||
|
||||
players: Query<(Entity, &Player)>,
|
||||
) {
|
||||
for SyncPlayer(id) in messages.read() {
|
||||
trace!("sync_player");
|
||||
let Some(player) = stdb.db().player().id().find(id) else {
|
||||
todo!()
|
||||
};
|
||||
|
||||
let player_ent = players
|
||||
.iter()
|
||||
.find_map(|(e, p)| (p.id == PlayerOrBot::Player { id: player.id }).then_some(e))
|
||||
.unwrap_or_else(|| {
|
||||
commands
|
||||
.spawn(Player {
|
||||
id: PlayerOrBot::Player { id: player.id },
|
||||
})
|
||||
.id()
|
||||
});
|
||||
|
||||
if player.identity == stdb.identity() {
|
||||
commands.entity(player_ent).insert(MainPlayer);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sync_open_hand(
|
||||
stdb: SpacetimeDB,
|
||||
|
||||
mut messages: MessageReader<SyncOpenHand>,
|
||||
mut commands: Commands,
|
||||
|
||||
tiles: Query<(Entity, &TileId)>,
|
||||
hands: Query<(Entity, &Hand)>,
|
||||
ponds: Query<(Entity, &Pond)>,
|
||||
|
||||
mut next_turnstate: ResMut<NextState<TurnState>>,
|
||||
) {
|
||||
trace!("on_subscribed");
|
||||
for player in stdb.db().player().iter() {
|
||||
if player.identity == stdb.identity() {
|
||||
// trace!("spawn_main_player");
|
||||
spawn_main_player(&stdb, &mut commands, &mut next_turnstate, &player);
|
||||
} else {
|
||||
// trace!("spawn_other_player");
|
||||
spawn_other_player(&stdb, &mut commands, &player);
|
||||
}
|
||||
}
|
||||
for SyncOpenHand(id) in messages.read() {
|
||||
trace!("sync_open_hand");
|
||||
let Some(player_hand) = stdb.db().view_hand().iter().find(|hand| hand.id == *id) else {
|
||||
todo!()
|
||||
};
|
||||
|
||||
for bot in stdb.db().bot().iter() {
|
||||
let id = PlayerOrBot::Bot { id: bot.id };
|
||||
let hand_view = stdb
|
||||
.db()
|
||||
.view_closed_hands()
|
||||
let hand_ent = hands
|
||||
.iter()
|
||||
.find(|v| PlayerOrBot::from(&v.player) == id)
|
||||
.unwrap();
|
||||
let hand_ent = commands.spawn((Hand, Closed(hand_view.hand_length))).id();
|
||||
commands.spawn(Player { id }).add_child(hand_ent);
|
||||
}
|
||||
.find_map(|(e, h)| (h.owner == PlayerOrBot::Player { id: *id }).then_some(e))
|
||||
.unwrap_or_else(|| {
|
||||
commands
|
||||
.spawn(Hand {
|
||||
owner: PlayerOrBot::Player { id: *id },
|
||||
})
|
||||
.id()
|
||||
});
|
||||
let pond_ent = ponds
|
||||
.iter()
|
||||
.find_map(|(e, h)| (h.owner == PlayerOrBot::Player { id: *id }).then_some(e))
|
||||
.unwrap_or_else(|| {
|
||||
commands
|
||||
.spawn(Pond {
|
||||
owner: PlayerOrBot::Player { id: *id },
|
||||
})
|
||||
.id()
|
||||
});
|
||||
|
||||
if let Some(lobby) = stdb.db().lobby().iter().next() {
|
||||
next_gamestate.set(lobby.game_state.into());
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_main_player(
|
||||
stdb: &SpacetimeDB,
|
||||
|
||||
commands: &mut Commands,
|
||||
next_turnstate: &mut ResMut<NextState<TurnState>>,
|
||||
|
||||
player: &jong_db::Player,
|
||||
) {
|
||||
// trace!("spawn_main_player");
|
||||
let main_player = commands
|
||||
.spawn((
|
||||
Player {
|
||||
id: PlayerOrBot::Player { id: player.id },
|
||||
},
|
||||
MainPlayer,
|
||||
))
|
||||
.id();
|
||||
if let Some(player_hand) = stdb.db().view_hand().iter().next() {
|
||||
spawn_main_hand(commands, next_turnstate, main_player, &player_hand);
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_main_hand(
|
||||
commands: &mut Commands,
|
||||
next_turnstate: &mut ResMut<NextState<TurnState>>,
|
||||
main_player: Entity,
|
||||
|
||||
player_hand: &PlayerHand,
|
||||
) {
|
||||
let hand_tiles: Vec<_> = player_hand
|
||||
// hand and pond both still need ability to spawn for the reconnect case
|
||||
let hand: Vec<Entity> = player_hand
|
||||
.hand
|
||||
.iter()
|
||||
.map(|dbt| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id())
|
||||
.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();
|
||||
let pond_tiles: Vec<_> = player_hand
|
||||
let pond: Vec<Entity> = player_hand
|
||||
.pond
|
||||
.iter()
|
||||
.map(|dbt| commands.spawn((Tile::from(&dbt.tile), TileId(dbt.id))).id())
|
||||
.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();
|
||||
let hand = commands.spawn(Hand).add_children(&hand_tiles).id();
|
||||
let pond = commands.spawn(Pond).add_children(&pond_tiles).id();
|
||||
commands.entity(main_player).add_children(&[hand, pond]);
|
||||
|
||||
debug!("main_hand: {:?}\n main_pond: {:?}", hand_tiles, pond_tiles);
|
||||
commands.entity(hand_ent).replace_children(&hand);
|
||||
commands.entity(pond_ent).replace_children(&pond);
|
||||
|
||||
if player_hand.turn_state == jong_db::TurnState::Tsumo
|
||||
&& let Some(drawn_dbt) = &player_hand.working_tile
|
||||
if let Some(dbt) = player_hand.working_tile
|
||||
&& player_hand.turn_state == jong_db::TurnState::Tsumo
|
||||
{
|
||||
let drawn = commands
|
||||
.spawn((Drawn, Tile::from(&drawn_dbt.tile), TileId(drawn_dbt.id)))
|
||||
.id();
|
||||
commands.entity(main_player).add_child(drawn);
|
||||
commands.spawn((Drawn, Tile::from(&dbt.tile), TileId(dbt.id)));
|
||||
}
|
||||
|
||||
next_turnstate.set(player_hand.turn_state.into());
|
||||
}
|
||||
|
||||
fn spawn_other_player(stdb: &SpacetimeDB, commands: &mut Commands, player: &jong_db::Player) {
|
||||
let id = PlayerOrBot::Player { id: player.id };
|
||||
if let Some(hand_view) = stdb
|
||||
.db()
|
||||
.view_closed_hands()
|
||||
.iter()
|
||||
.find(|v| PlayerOrBot::from(&v.player) == id)
|
||||
{
|
||||
let hand_ent = commands.spawn((Hand, Closed(hand_view.hand_length))).id();
|
||||
commands.spawn(Player { id }).add_child(hand_ent);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_player_insert_update(
|
||||
fn sync_closed_hand(
|
||||
stdb: SpacetimeDB,
|
||||
mut messages: ReadInsertUpdateMessage<jong_db::Player>,
|
||||
|
||||
mut events: MessageReader<SyncClosedHand>,
|
||||
mut commands: Commands,
|
||||
|
||||
main_player: Option<Single<&MainPlayer>>,
|
||||
other_players: Query<&Player, Without<MainPlayer>>,
|
||||
|
||||
mut next_turnstate: ResMut<NextState<jong_types::states::TurnState>>,
|
||||
hands: Query<&mut Closed, With<Hand>>,
|
||||
ponds: Query<&mut Children, With<Pond>>,
|
||||
) {
|
||||
for msg in messages.read() {
|
||||
debug!("on_player_insert_update: {:?}", msg.new);
|
||||
assert_eq!(msg.new.identity, stdb.identity());
|
||||
if main_player.is_none() && msg.new.identity == stdb.identity() {
|
||||
spawn_main_player(&stdb, &mut commands, &mut next_turnstate, &msg.new);
|
||||
} else if other_players.iter().any(|p| {
|
||||
if let PlayerOrBot::Player { id } = &p.id {
|
||||
*id == msg.new.id
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}) {
|
||||
trace!("spawn_other_player");
|
||||
spawn_other_player(&stdb, &mut commands, &msg.new);
|
||||
} else {
|
||||
// TODO update case
|
||||
}
|
||||
|
||||
fn sync_player_clock() {}
|
||||
|
||||
fn on_player_insert_update(
|
||||
mut db_messages: ReadInsertUpdateMessage<jong_db::Player>,
|
||||
|
||||
mut writer: MessageWriter<SyncPlayer>,
|
||||
) {
|
||||
for msg in db_messages.read() {
|
||||
trace!("on_player_insert_update");
|
||||
writer.write(SyncPlayer(msg.new.id));
|
||||
}
|
||||
}
|
||||
|
||||
fn on_bot_insert_update() {}
|
||||
|
||||
fn on_lobby_insert_update(
|
||||
stdb: SpacetimeDB,
|
||||
mut messages: ReadInsertUpdateMessage<jong_db::Lobby>,
|
||||
|
|
@ -264,7 +264,6 @@ fn on_lobby_insert_update(
|
|||
.find(&stdb.identity())
|
||||
.unwrap();
|
||||
|
||||
next_gamestate.set(msg.new.game_state.into());
|
||||
match msg.new.game_state {
|
||||
jong_db::GameState::None => {
|
||||
trace!("game entered none");
|
||||
|
|
@ -299,87 +298,82 @@ fn on_lobby_insert_update(
|
|||
|
||||
fn on_view_hand_insert(
|
||||
mut messages: ReadInsertMessage<jong_db::PlayerHand>,
|
||||
|
||||
mut commands: Commands,
|
||||
main_player: Single<(Entity, Option<&Children>), With<MainPlayer>>,
|
||||
|
||||
mut next_turnstate: ResMut<NextState<jong_types::states::TurnState>>,
|
||||
mut writer: MessageWriter<SyncOpenHand>,
|
||||
) {
|
||||
for msg in messages.read() {
|
||||
trace!("insert hand: {:?}", msg.row);
|
||||
|
||||
if main_player.1.is_none() {
|
||||
spawn_main_hand(&mut commands, &mut next_turnstate, main_player.0, &msg.row);
|
||||
}
|
||||
trace!("on_view_hand_insert");
|
||||
writer.write(SyncOpenHand(msg.row.id));
|
||||
}
|
||||
}
|
||||
|
||||
fn on_view_hand_update(
|
||||
stdb: SpacetimeDB,
|
||||
mut messages: ReadUpdateMessage<jong_db::PlayerHand>,
|
||||
mut writer: MessageWriter<SyncOpenHand>,
|
||||
// mut commands: Commands,
|
||||
// tiles: Query<(Entity, &TileId)>,
|
||||
|
||||
mut commands: Commands,
|
||||
tiles: Query<(Entity, &TileId)>,
|
||||
// main_player: Single<(Entity, &Children), With<MainPlayer>>,
|
||||
|
||||
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>>,
|
||||
// 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() {
|
||||
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();
|
||||
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);
|
||||
// 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!(),
|
||||
}
|
||||
// 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());
|
||||
}
|
||||
// next_turnstate.set(msg.new.turn_state.into());
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
26
jong/src/riichi/connection.rs
Normal file
26
jong/src/riichi/connection.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
use bevy_spacetimedb::{ReadStdbConnectedMessage, ReadStdbDisconnectedMessage};
|
||||
use log::{debug, info, warn};
|
||||
|
||||
use crate::SpacetimeDB;
|
||||
use crate::creds_store;
|
||||
|
||||
pub(crate) fn on_connect(stdb: SpacetimeDB, mut messages: ReadStdbConnectedMessage) {
|
||||
for msg in messages.read() {
|
||||
info!("you're now jongline");
|
||||
|
||||
// FIXME hack that doesn't work for startup crash?
|
||||
while stdb.try_identity().is_none() {}
|
||||
|
||||
debug!("with identity: {}", stdb.identity());
|
||||
creds_store()
|
||||
.save(&msg.access_token)
|
||||
.expect("i/o error saving token");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO how reconnect?
|
||||
pub(crate) fn on_disconnect(_stdb: SpacetimeDB, mut messages: ReadStdbDisconnectedMessage) {
|
||||
for msg in messages.read() {
|
||||
warn!("lost connection: {:#?}", msg.err);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ use jong_types::PlayerOrBot;
|
|||
|
||||
#[derive(Component)]
|
||||
pub struct Player {
|
||||
pub(crate) id: PlayerOrBot,
|
||||
pub id: PlayerOrBot,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
|
|
@ -17,13 +17,20 @@ pub struct CurrentPlayer;
|
|||
pub struct TileId(pub u32);
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Hand;
|
||||
pub struct Hand {
|
||||
pub owner: PlayerOrBot,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Closed(pub(crate) u8);
|
||||
pub struct Closed {
|
||||
pub(crate) owner: PlayerOrBot,
|
||||
pub(crate) length: u8,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Pond;
|
||||
pub struct Pond {
|
||||
pub owner: PlayerOrBot,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Drawn;
|
||||
|
|
|
|||
|
|
@ -150,9 +150,9 @@ pub(crate) fn render_main_hand(
|
|||
tiles: Query<&jong_types::Tile>,
|
||||
hovered: Query<Entity, With<Hovered>>,
|
||||
|
||||
main_player: Single<&Children, With<MainPlayer>>,
|
||||
main_player: Single<&Player, With<MainPlayer>>,
|
||||
|
||||
hand: Query<(&Children, Entity), With<Hand>>,
|
||||
hand: Query<(&Hand, &Children)>,
|
||||
drawn_tile: Option<Single<Entity, With<Drawn>>>,
|
||||
) -> Result {
|
||||
let mut frame = tui.get_frame();
|
||||
|
|
@ -164,14 +164,7 @@ pub(crate) fn render_main_hand(
|
|||
|
||||
let hand: Vec<_> = hand
|
||||
.iter()
|
||||
.find_map(|(c, e)| {
|
||||
// debug!("main_player children: {:?}", *main_player);
|
||||
if main_player.contains(&e) {
|
||||
Some(c)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.find_map(|(h, c)| (main_player.id == h.owner).then_some(c))
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|entity| -> Result<_> {
|
||||
|
|
@ -266,9 +259,9 @@ pub(crate) fn render_main_pond(
|
|||
tiles: Query<&Tile>,
|
||||
hovered: Query<Entity, With<Hovered>>,
|
||||
|
||||
main_player: Single<&Children, With<MainPlayer>>,
|
||||
main_player: Single<&Player, With<MainPlayer>>,
|
||||
|
||||
pond: Query<(&Children, Entity), With<Pond>>,
|
||||
pond: Query<(&Pond, &Children)>,
|
||||
) -> Result {
|
||||
let mut frame = tui.get_frame();
|
||||
|
||||
|
|
@ -278,13 +271,7 @@ pub(crate) fn render_main_pond(
|
|||
|
||||
let pond: Vec<_> = pond
|
||||
.iter()
|
||||
.find_map(|(c, e)| {
|
||||
if main_player.contains(&e) {
|
||||
Some(c)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.find_map(|(p, c)| (main_player.id == p.owner).then_some(c))
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|entity| -> Result<_> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue