basic lobby joinage logic
This commit is contained in:
parent
655123b055
commit
78c199b61e
16 changed files with 708 additions and 167 deletions
170
jong/src/game.rs
170
jong/src/game.rs
|
|
@ -1,6 +1,20 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy_spacetimedb::StdbPlugin;
|
||||
#![allow(unused)]
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_spacetimedb::{
|
||||
ReadInsertUpdateMessage, ReadStdbConnectedMessage, ReadStdbDisconnectedMessage, StdbPlugin,
|
||||
TableMessages,
|
||||
};
|
||||
use spacetimedb::Identity;
|
||||
use spacetimedb_sdk::credentials;
|
||||
|
||||
use crate::{
|
||||
SpacetimeDB, creds_store,
|
||||
stdb::{
|
||||
self, DbConnection, LobbyTableAccess, PlayerTableAccess, RemoteTables, add_bot,
|
||||
join_or_create_lobby, login_or_add_player,
|
||||
},
|
||||
};
|
||||
use crate::{
|
||||
game::{
|
||||
hand::{Hand, Pond},
|
||||
|
|
@ -8,7 +22,6 @@ use crate::{
|
|||
round::{TurnState, Wind},
|
||||
wall::Wall,
|
||||
},
|
||||
stdb::DbConnection,
|
||||
tile::{self},
|
||||
};
|
||||
|
||||
|
|
@ -24,6 +37,7 @@ pub enum GameState {
|
|||
Setup,
|
||||
Deal,
|
||||
Play,
|
||||
Exit,
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
|
|
@ -33,77 +47,115 @@ pub enum GameMessage {
|
|||
Called { player: Entity, calltype: Entity },
|
||||
}
|
||||
|
||||
impl GameMessage {
|
||||
pub(crate) fn is_called(&self) -> bool {
|
||||
match self {
|
||||
GameMessage::Called { .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Riichi;
|
||||
impl Plugin for Riichi {
|
||||
fn build(&self, app: &mut App) {
|
||||
// app.add_plugins(
|
||||
// StdbPlugin::default()
|
||||
// .with_uri("http://localhost:3000")
|
||||
// .with_module_name("jongline")
|
||||
// .with_run_fn(DbConnection::run_threaded),
|
||||
// );
|
||||
app
|
||||
// start stopper
|
||||
let mut plugins = StdbPlugin::default()
|
||||
.with_uri("http://localhost:3000")
|
||||
.with_module_name("jongline")
|
||||
.with_run_fn(DbConnection::run_threaded)
|
||||
// TODO change to partial no update or a subscription?
|
||||
.add_table(RemoteTables::player);
|
||||
let plugins =
|
||||
if let Some(token) = creds_store().load().expect("i/o error loading credentials") {
|
||||
// FIXME patch plugin so this takes Option?
|
||||
plugins.with_token(&token)
|
||||
} else {
|
||||
plugins
|
||||
};
|
||||
|
||||
app.add_plugins(plugins)
|
||||
.init_state::<GameState>()
|
||||
.add_sub_state::<TurnState>()
|
||||
.init_resource::<round::MatchSettings>()
|
||||
.init_resource::<round::Compass>()
|
||||
.add_message::<GameMessage>()
|
||||
// .add_sub_state::<TurnState>()
|
||||
// .init_resource::<round::MatchSettings>()
|
||||
// .init_resource::<round::Compass>()
|
||||
// .add_message::<GameMessage>()
|
||||
.add_systems(Startup, tile::init_tiles)
|
||||
.add_systems(OnEnter(GameState::Setup), setup)
|
||||
.add_systems(OnEnter(GameState::Deal), hand::shuffle_deal)
|
||||
.add_systems(Update, hand::sort_hands.run_if(in_state(GameState::Play)))
|
||||
.add_systems(OnEnter(TurnState::Tsumo), round::tsumo)
|
||||
.add_systems(OnEnter(TurnState::Menzen), round::menzen)
|
||||
.add_systems(Update, round::riichi_kan.run_if(in_state(TurnState::RiichiKan)))
|
||||
.add_systems(Update, round::discard.run_if(in_state(TurnState::Discard)))
|
||||
.add_systems(OnEnter(TurnState::RonChiiPonKan), round::notify_callable)
|
||||
.add_systems(Update, round::ron_chi_pon_kan.run_if(in_state(TurnState::RonChiiPonKan)).after(round::notify_callable))
|
||||
.add_systems(OnEnter(TurnState::End), round::end)
|
||||
// .add_systems(OnEnter(GameState::Setup), setup)
|
||||
// .add_systems(OnEnter(GameState::Deal), hand::shuffle_deal)
|
||||
// .add_systems(Update, hand::sort_hands.run_if(in_state(GameState::Play)))
|
||||
// .add_systems(OnEnter(TurnState::Tsumo), round::tsumo)
|
||||
// .add_systems(OnEnter(TurnState::Menzen), round::menzen)
|
||||
// .add_systems(Update, round::riichi_kan.run_if(in_state(TurnState::RiichiKan)))
|
||||
// .add_systems(Update, round::discard.run_if(in_state(TurnState::Discard)))
|
||||
// .add_systems(OnEnter(TurnState::RonChiiPonKan), round::notify_callable)
|
||||
// .add_systems(Update, round::ron_chi_pon_kan.run_if(in_state(TurnState::RonChiiPonKan)).after(round::notify_callable))
|
||||
// .add_systems(OnEnter(TurnState::End), round::end)
|
||||
// stdb
|
||||
.add_systems(Update, on_connect)
|
||||
.add_systems(Update, on_disconnect)
|
||||
.add_systems(Update, on_player_insert_update)
|
||||
.add_systems(OnEnter(GameState::Setup), join_or_create_lobby)
|
||||
.add_systems(OnEnter(GameState::Deal), ||todo!())
|
||||
// semicolon stopper
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn setup(
|
||||
#[derive(Resource, Deref)]
|
||||
struct Player(stdb::Player);
|
||||
|
||||
// TODO or reconnect?
|
||||
fn on_connect(stdb: SpacetimeDB, mut messages: ReadStdbConnectedMessage) {
|
||||
for msg in messages.read() {
|
||||
info!("you're now jongline");
|
||||
debug!("with identity: {}", stdb.identity());
|
||||
creds_store()
|
||||
.save(&msg.access_token)
|
||||
.expect("i/o error saving token");
|
||||
|
||||
// FIXME delet this in future
|
||||
stdb.subscription_builder().subscribe_to_all_tables();
|
||||
}
|
||||
}
|
||||
|
||||
fn on_disconnect(stdb: SpacetimeDB, mut messages: ReadStdbDisconnectedMessage) {
|
||||
for msg in messages.read() {
|
||||
warn!("lost connection: {:#?}", msg.err);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_player_insert_update(
|
||||
stdb: SpacetimeDB,
|
||||
mut messages: ReadInsertUpdateMessage<stdb::Player>,
|
||||
mut commands: Commands,
|
||||
matchsettings: Res<round::MatchSettings>,
|
||||
// mut compass: ResMut<Compass>
|
||||
// tiles: Query<Entity, With<Tile>>,
|
||||
player: Option<Res<Player>>,
|
||||
) {
|
||||
for msg in messages.read() {
|
||||
if player.is_some() {
|
||||
if msg.new.lobby_id != 0 {
|
||||
info!("joined lobby {}", msg.new.lobby_id);
|
||||
for _ in 0..3 {
|
||||
stdb.reducers().add_bot(msg.new.lobby_id).unwrap()
|
||||
}
|
||||
}
|
||||
} else if let Some(player) = stdb.db().player().identity().find(&stdb.identity()) {
|
||||
commands.insert_resource(Player(player));
|
||||
trace!("logged in");
|
||||
} else {
|
||||
debug!(
|
||||
"received player insert update msg: {:?} -> {:?}",
|
||||
msg.old, msg.new
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn join_or_create_lobby(
|
||||
stdb: SpacetimeDB,
|
||||
player: Res<Player>,
|
||||
mut next_gamestate: ResMut<NextState<GameState>>,
|
||||
) {
|
||||
for i in 1..=matchsettings.player_count {
|
||||
let player = player::Player {
|
||||
name: format!("Player {}", i),
|
||||
};
|
||||
let points = player::Points(matchsettings.starting_points);
|
||||
|
||||
let bundle = (
|
||||
player,
|
||||
points,
|
||||
Hand,
|
||||
Pond,
|
||||
Wind::from_repr((i - 1) as usize).unwrap(),
|
||||
);
|
||||
|
||||
if i == 1 {
|
||||
let player = commands.spawn((bundle, MainPlayer, CurrentPlayer)).id();
|
||||
// commands.insert_resource(CurrentPlayer(player));
|
||||
if player.lobby_id == 0 {
|
||||
stdb.reducers().join_or_create_lobby(None).unwrap();
|
||||
stdb.subscription_builder()
|
||||
.on_applied(|_| trace!("subbed to lobby table"))
|
||||
.on_error(|_, err| error!("sub to lobby table failed: {}", err))
|
||||
.subscribe(["SELECT l.* FROM lobby l JOIN player p ON l.host_id = p.id"]);
|
||||
} else {
|
||||
commands.spawn(bundle);
|
||||
}
|
||||
debug!("already in lobby")
|
||||
}
|
||||
|
||||
commands.spawn(Wall);
|
||||
|
||||
// TODO how can this trigger with a reducer or automatically after all players join/ready
|
||||
next_gamestate.set(GameState::Deal);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use bevy::prelude::*;
|
||||
use bevy_spacetimedb::StdbConnection;
|
||||
use spacetimedb_sdk::credentials;
|
||||
|
||||
pub mod game;
|
||||
pub mod tile;
|
||||
|
|
@ -14,3 +15,7 @@ trait EnumNextCycle {
|
|||
}
|
||||
|
||||
pub type SpacetimeDB<'a> = Res<'a, StdbConnection<stdb::DbConnection>>;
|
||||
|
||||
fn creds_store() -> credentials::File {
|
||||
credentials::File::new("jongline")
|
||||
}
|
||||
|
|
|
|||
104
jong/src/stdb/add_bot_reducer.rs
Normal file
104
jong/src/stdb/add_bot_reducer.rs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// 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 AddBotArgs {
|
||||
pub lobby_id: u32,
|
||||
}
|
||||
|
||||
impl From<AddBotArgs> for super::Reducer {
|
||||
fn from(args: AddBotArgs) -> Self {
|
||||
Self::AddBot {
|
||||
lobby_id: args.lobby_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl __sdk::InModule for AddBotArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
pub struct AddBotCallbackId(__sdk::CallbackId);
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the reducer `add_bot`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteReducers`].
|
||||
pub trait add_bot {
|
||||
/// Request that the remote module invoke the reducer `add_bot` 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_add_bot`] callbacks.
|
||||
fn add_bot(&self, lobby_id: u32) -> __sdk::Result<()>;
|
||||
/// Register a callback to run whenever we are notified of an invocation of the reducer `add_bot`.
|
||||
///
|
||||
/// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`]
|
||||
/// to determine the reducer's status.
|
||||
///
|
||||
/// The returned [`AddBotCallbackId`] can be passed to [`Self::remove_on_add_bot`]
|
||||
/// to cancel the callback.
|
||||
fn on_add_bot(
|
||||
&self,
|
||||
callback: impl FnMut(&super::ReducerEventContext, &u32) + Send + 'static,
|
||||
) -> AddBotCallbackId;
|
||||
/// Cancel a callback previously registered by [`Self::on_add_bot`],
|
||||
/// causing it not to run in the future.
|
||||
fn remove_on_add_bot(&self, callback: AddBotCallbackId);
|
||||
}
|
||||
|
||||
impl add_bot for super::RemoteReducers {
|
||||
fn add_bot(&self, lobby_id: u32) -> __sdk::Result<()> {
|
||||
self.imp.call_reducer("add_bot", AddBotArgs { lobby_id })
|
||||
}
|
||||
fn on_add_bot(
|
||||
&self,
|
||||
mut callback: impl FnMut(&super::ReducerEventContext, &u32) + Send + 'static,
|
||||
) -> AddBotCallbackId {
|
||||
AddBotCallbackId(self.imp.on_reducer(
|
||||
"add_bot",
|
||||
Box::new(move |ctx: &super::ReducerEventContext| {
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
let super::ReducerEventContext {
|
||||
event:
|
||||
__sdk::ReducerEvent {
|
||||
reducer: super::Reducer::AddBot { lobby_id },
|
||||
..
|
||||
},
|
||||
..
|
||||
} = ctx
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
callback(ctx, lobby_id)
|
||||
}),
|
||||
))
|
||||
}
|
||||
fn remove_on_add_bot(&self, callback: AddBotCallbackId) {
|
||||
self.imp.remove_on_reducer("add_bot", callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[doc(hidden)]
|
||||
/// Extension trait for setting the call-flags for the reducer `add_bot`.
|
||||
///
|
||||
/// Implemented for [`super::SetReducerFlags`].
|
||||
///
|
||||
/// This type is currently unstable and may be removed without a major version bump.
|
||||
pub trait set_flags_for_add_bot {
|
||||
/// Set the call-reducer flags for the reducer `add_bot` to `flags`.
|
||||
///
|
||||
/// This type is currently unstable and may be removed without a major version bump.
|
||||
fn add_bot(&self, flags: __ws::CallReducerFlags);
|
||||
}
|
||||
|
||||
impl set_flags_for_add_bot for super::SetReducerFlags {
|
||||
fn add_bot(&self, flags: __ws::CallReducerFlags) {
|
||||
self.imp.set_call_reducer_flags("add_bot", flags);
|
||||
}
|
||||
}
|
||||
142
jong/src/stdb/bot_table.rs
Normal file
142
jong/src/stdb/bot_table.rs
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
// 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 super::bot_type::Bot;
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
/// Table handle for the table `bot`.
|
||||
///
|
||||
/// Obtain a handle from the [`BotTableAccess::bot`] method on [`super::RemoteTables`],
|
||||
/// like `ctx.db.bot()`.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.bot().on_insert(...)`.
|
||||
pub struct BotTableHandle<'ctx> {
|
||||
imp: __sdk::TableHandle<Bot>,
|
||||
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the table `bot`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteTables`].
|
||||
pub trait BotTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Obtain a [`BotTableHandle`], which mediates access to the table `bot`.
|
||||
fn bot(&self) -> BotTableHandle<'_>;
|
||||
}
|
||||
|
||||
impl BotTableAccess for super::RemoteTables {
|
||||
fn bot(&self) -> BotTableHandle<'_> {
|
||||
BotTableHandle {
|
||||
imp: self.imp.get_table::<Bot>("bot"),
|
||||
ctx: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BotInsertCallbackId(__sdk::CallbackId);
|
||||
pub struct BotDeleteCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::Table for BotTableHandle<'ctx> {
|
||||
type Row = Bot;
|
||||
type EventContext = super::EventContext;
|
||||
|
||||
fn count(&self) -> u64 {
|
||||
self.imp.count()
|
||||
}
|
||||
fn iter(&self) -> impl Iterator<Item = Bot> + '_ {
|
||||
self.imp.iter()
|
||||
}
|
||||
|
||||
type InsertCallbackId = BotInsertCallbackId;
|
||||
|
||||
fn on_insert(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> BotInsertCallbackId {
|
||||
BotInsertCallbackId(self.imp.on_insert(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_insert(&self, callback: BotInsertCallbackId) {
|
||||
self.imp.remove_on_insert(callback.0)
|
||||
}
|
||||
|
||||
type DeleteCallbackId = BotDeleteCallbackId;
|
||||
|
||||
fn on_delete(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> BotDeleteCallbackId {
|
||||
BotDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_delete(&self, callback: BotDeleteCallbackId) {
|
||||
self.imp.remove_on_delete(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
let _table = client_cache.get_or_make_table::<Bot>("bot");
|
||||
_table.add_unique_constraint::<u32>("id", |row| &row.id);
|
||||
}
|
||||
pub struct BotUpdateCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::TableWithPrimaryKey for BotTableHandle<'ctx> {
|
||||
type UpdateCallbackId = BotUpdateCallbackId;
|
||||
|
||||
fn on_update(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
|
||||
) -> BotUpdateCallbackId {
|
||||
BotUpdateCallbackId(self.imp.on_update(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_update(&self, callback: BotUpdateCallbackId) {
|
||||
self.imp.remove_on_update(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn parse_table_update(
|
||||
raw_updates: __ws::TableUpdate<__ws::BsatnFormat>,
|
||||
) -> __sdk::Result<__sdk::TableUpdate<Bot>> {
|
||||
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
|
||||
__sdk::InternalError::failed_parse("TableUpdate<Bot>", "TableUpdate")
|
||||
.with_cause(e)
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
/// Access to the `id` unique index on the table `bot`,
|
||||
/// which allows point queries on the field of the same name
|
||||
/// via the [`BotIdUnique::find`] method.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.bot().id().find(...)`.
|
||||
pub struct BotIdUnique<'ctx> {
|
||||
imp: __sdk::UniqueConstraintHandle<Bot, u32>,
|
||||
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
impl<'ctx> BotTableHandle<'ctx> {
|
||||
/// Get a handle on the `id` unique index on the table `bot`.
|
||||
pub fn id(&self) -> BotIdUnique<'ctx> {
|
||||
BotIdUnique {
|
||||
imp: self.imp.get_unique_constraint::<u32>("id"),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> BotIdUnique<'ctx> {
|
||||
/// Find the subscribed row whose `id` column value is equal to `col_val`,
|
||||
/// if such a row is present in the client cache.
|
||||
pub fn find(&self, col_val: &u32) -> Option<Bot> {
|
||||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
16
jong/src/stdb/bot_type.rs
Normal file
16
jong/src/stdb/bot_type.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// 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 struct Bot {
|
||||
pub id: u32,
|
||||
pub lobby_id: u32,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for Bot {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
|
@ -82,6 +82,7 @@ impl<'ctx> __sdk::Table for LobbyTableHandle<'ctx> {
|
|||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
let _table = client_cache.get_or_make_table::<Lobby>("lobby");
|
||||
_table.add_unique_constraint::<u32>("id", |row| &row.id);
|
||||
_table.add_unique_constraint::<u32>("host_id", |row| &row.host_id);
|
||||
}
|
||||
pub struct LobbyUpdateCallbackId(__sdk::CallbackId);
|
||||
|
||||
|
|
@ -140,3 +141,33 @@ impl<'ctx> LobbyIdUnique<'ctx> {
|
|||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
||||
/// Access to the `host_id` unique index on the table `lobby`,
|
||||
/// which allows point queries on the field of the same name
|
||||
/// via the [`LobbyHostIdUnique::find`] method.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.lobby().host_id().find(...)`.
|
||||
pub struct LobbyHostIdUnique<'ctx> {
|
||||
imp: __sdk::UniqueConstraintHandle<Lobby, u32>,
|
||||
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
impl<'ctx> LobbyTableHandle<'ctx> {
|
||||
/// Get a handle on the `host_id` unique index on the table `lobby`.
|
||||
pub fn host_id(&self) -> LobbyHostIdUnique<'ctx> {
|
||||
LobbyHostIdUnique {
|
||||
imp: self.imp.get_unique_constraint::<u32>("host_id"),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> LobbyHostIdUnique<'ctx> {
|
||||
/// Find the subscribed row whose `host_id` column value is equal to `col_val`,
|
||||
/// if such a row is present in the client cache.
|
||||
pub fn find(&self, col_val: &u32) -> Option<Lobby> {
|
||||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
|||
#[sats(crate = __lib)]
|
||||
pub struct Lobby {
|
||||
pub id: u32,
|
||||
pub host: __sdk::Identity,
|
||||
pub host_id: u32,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for Lobby {
|
||||
|
|
|
|||
103
jong/src/stdb/login_or_add_player_reducer.rs
Normal file
103
jong/src/stdb/login_or_add_player_reducer.rs
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
// 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 LoginOrAddPlayerArgs {}
|
||||
|
||||
impl From<LoginOrAddPlayerArgs> for super::Reducer {
|
||||
fn from(args: LoginOrAddPlayerArgs) -> Self {
|
||||
Self::LoginOrAddPlayer
|
||||
}
|
||||
}
|
||||
|
||||
impl __sdk::InModule for LoginOrAddPlayerArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
pub struct LoginOrAddPlayerCallbackId(__sdk::CallbackId);
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the reducer `login_or_add_player`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteReducers`].
|
||||
pub trait login_or_add_player {
|
||||
/// Request that the remote module invoke the reducer `login_or_add_player` 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_login_or_add_player`] callbacks.
|
||||
fn login_or_add_player(&self) -> __sdk::Result<()>;
|
||||
/// Register a callback to run whenever we are notified of an invocation of the reducer `login_or_add_player`.
|
||||
///
|
||||
/// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`]
|
||||
/// to determine the reducer's status.
|
||||
///
|
||||
/// The returned [`LoginOrAddPlayerCallbackId`] can be passed to [`Self::remove_on_login_or_add_player`]
|
||||
/// to cancel the callback.
|
||||
fn on_login_or_add_player(
|
||||
&self,
|
||||
callback: impl FnMut(&super::ReducerEventContext) + Send + 'static,
|
||||
) -> LoginOrAddPlayerCallbackId;
|
||||
/// Cancel a callback previously registered by [`Self::on_login_or_add_player`],
|
||||
/// causing it not to run in the future.
|
||||
fn remove_on_login_or_add_player(&self, callback: LoginOrAddPlayerCallbackId);
|
||||
}
|
||||
|
||||
impl login_or_add_player for super::RemoteReducers {
|
||||
fn login_or_add_player(&self) -> __sdk::Result<()> {
|
||||
self.imp
|
||||
.call_reducer("login_or_add_player", LoginOrAddPlayerArgs {})
|
||||
}
|
||||
fn on_login_or_add_player(
|
||||
&self,
|
||||
mut callback: impl FnMut(&super::ReducerEventContext) + Send + 'static,
|
||||
) -> LoginOrAddPlayerCallbackId {
|
||||
LoginOrAddPlayerCallbackId(self.imp.on_reducer(
|
||||
"login_or_add_player",
|
||||
Box::new(move |ctx: &super::ReducerEventContext| {
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
let super::ReducerEventContext {
|
||||
event:
|
||||
__sdk::ReducerEvent {
|
||||
reducer: super::Reducer::LoginOrAddPlayer {},
|
||||
..
|
||||
},
|
||||
..
|
||||
} = ctx
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
callback(ctx)
|
||||
}),
|
||||
))
|
||||
}
|
||||
fn remove_on_login_or_add_player(&self, callback: LoginOrAddPlayerCallbackId) {
|
||||
self.imp
|
||||
.remove_on_reducer("login_or_add_player", callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[doc(hidden)]
|
||||
/// Extension trait for setting the call-flags for the reducer `login_or_add_player`.
|
||||
///
|
||||
/// Implemented for [`super::SetReducerFlags`].
|
||||
///
|
||||
/// This type is currently unstable and may be removed without a major version bump.
|
||||
pub trait set_flags_for_login_or_add_player {
|
||||
/// Set the call-reducer flags for the reducer `login_or_add_player` to `flags`.
|
||||
///
|
||||
/// This type is currently unstable and may be removed without a major version bump.
|
||||
fn login_or_add_player(&self, flags: __ws::CallReducerFlags);
|
||||
}
|
||||
|
||||
impl set_flags_for_login_or_add_player for super::SetReducerFlags {
|
||||
fn login_or_add_player(&self, flags: __ws::CallReducerFlags) {
|
||||
self.imp
|
||||
.set_call_reducer_flags("login_or_add_player", flags);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,21 +6,22 @@
|
|||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
pub mod add_player_reducer;
|
||||
pub mod add_bot_reducer;
|
||||
pub mod bot_table;
|
||||
pub mod bot_type;
|
||||
pub mod deal_hands_reducer;
|
||||
pub mod dragon_type;
|
||||
pub mod hand_table;
|
||||
pub mod hand_type;
|
||||
pub mod insert_wall_reducer;
|
||||
pub mod join_or_create_lobby_reducer;
|
||||
pub mod lobby_table;
|
||||
pub mod lobby_type;
|
||||
pub mod login_or_add_player_reducer;
|
||||
pub mod player_table;
|
||||
pub mod player_type;
|
||||
pub mod pond_table;
|
||||
pub mod pond_type;
|
||||
pub mod rank_type;
|
||||
pub mod set_name_reducer;
|
||||
pub mod shuffle_wall_reducer;
|
||||
pub mod sort_hand_reducer;
|
||||
pub mod suit_type;
|
||||
|
|
@ -29,23 +30,26 @@ pub mod wall_table;
|
|||
pub mod wall_type;
|
||||
pub mod wind_type;
|
||||
|
||||
pub use add_player_reducer::{add_player, set_flags_for_add_player, AddPlayerCallbackId};
|
||||
pub use add_bot_reducer::{add_bot, set_flags_for_add_bot, AddBotCallbackId};
|
||||
pub use bot_table::*;
|
||||
pub use bot_type::Bot;
|
||||
pub use deal_hands_reducer::{deal_hands, set_flags_for_deal_hands, DealHandsCallbackId};
|
||||
pub use dragon_type::Dragon;
|
||||
pub use hand_table::*;
|
||||
pub use hand_type::Hand;
|
||||
pub use insert_wall_reducer::{insert_wall, set_flags_for_insert_wall, InsertWallCallbackId};
|
||||
pub use join_or_create_lobby_reducer::{
|
||||
join_or_create_lobby, set_flags_for_join_or_create_lobby, JoinOrCreateLobbyCallbackId,
|
||||
};
|
||||
pub use lobby_table::*;
|
||||
pub use lobby_type::Lobby;
|
||||
pub use login_or_add_player_reducer::{
|
||||
login_or_add_player, set_flags_for_login_or_add_player, LoginOrAddPlayerCallbackId,
|
||||
};
|
||||
pub use player_table::*;
|
||||
pub use player_type::Player;
|
||||
pub use pond_table::*;
|
||||
pub use pond_type::Pond;
|
||||
pub use rank_type::Rank;
|
||||
pub use set_name_reducer::{set_flags_for_set_name, set_name, SetNameCallbackId};
|
||||
pub use shuffle_wall_reducer::{set_flags_for_shuffle_wall, shuffle_wall, ShuffleWallCallbackId};
|
||||
pub use sort_hand_reducer::{set_flags_for_sort_hand, sort_hand, SortHandCallbackId};
|
||||
pub use suit_type::Suit;
|
||||
|
|
@ -62,11 +66,10 @@ pub use wind_type::Wind;
|
|||
/// to indicate which reducer caused the event.
|
||||
|
||||
pub enum Reducer {
|
||||
AddPlayer { name: Option<String> },
|
||||
AddBot { lobby_id: u32 },
|
||||
DealHands,
|
||||
InsertWall { player_ids: Vec<u32> },
|
||||
JoinOrCreateLobby { lobby: Option<u32> },
|
||||
SetName { name: String },
|
||||
LoginOrAddPlayer,
|
||||
ShuffleWall,
|
||||
SortHand,
|
||||
}
|
||||
|
|
@ -78,11 +81,10 @@ impl __sdk::InModule for Reducer {
|
|||
impl __sdk::Reducer for Reducer {
|
||||
fn reducer_name(&self) -> &'static str {
|
||||
match self {
|
||||
Reducer::AddPlayer { .. } => "add_player",
|
||||
Reducer::AddBot { .. } => "add_bot",
|
||||
Reducer::DealHands => "deal_hands",
|
||||
Reducer::InsertWall { .. } => "insert_wall",
|
||||
Reducer::JoinOrCreateLobby { .. } => "join_or_create_lobby",
|
||||
Reducer::SetName { .. } => "set_name",
|
||||
Reducer::LoginOrAddPlayer => "login_or_add_player",
|
||||
Reducer::ShuffleWall => "shuffle_wall",
|
||||
Reducer::SortHand => "sort_hand",
|
||||
_ => unreachable!(),
|
||||
|
|
@ -93,13 +95,11 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer {
|
|||
type Error = __sdk::Error;
|
||||
fn try_from(value: __ws::ReducerCallInfo<__ws::BsatnFormat>) -> __sdk::Result<Self> {
|
||||
match &value.reducer_name[..] {
|
||||
"add_player" => Ok(
|
||||
__sdk::parse_reducer_args::<add_player_reducer::AddPlayerArgs>(
|
||||
"add_player",
|
||||
"add_bot" => Ok(__sdk::parse_reducer_args::<add_bot_reducer::AddBotArgs>(
|
||||
"add_bot",
|
||||
&value.args,
|
||||
)?
|
||||
.into(),
|
||||
),
|
||||
.into()),
|
||||
"deal_hands" => Ok(
|
||||
__sdk::parse_reducer_args::<deal_hands_reducer::DealHandsArgs>(
|
||||
"deal_hands",
|
||||
|
|
@ -107,21 +107,13 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer {
|
|||
)?
|
||||
.into(),
|
||||
),
|
||||
"insert_wall" => Ok(
|
||||
__sdk::parse_reducer_args::<insert_wall_reducer::InsertWallArgs>(
|
||||
"insert_wall",
|
||||
&value.args,
|
||||
)?
|
||||
.into(),
|
||||
),
|
||||
"join_or_create_lobby" => Ok(__sdk::parse_reducer_args::<
|
||||
join_or_create_lobby_reducer::JoinOrCreateLobbyArgs,
|
||||
>("join_or_create_lobby", &value.args)?
|
||||
.into()),
|
||||
"set_name" => Ok(__sdk::parse_reducer_args::<set_name_reducer::SetNameArgs>(
|
||||
"set_name",
|
||||
&value.args,
|
||||
)?
|
||||
"login_or_add_player" => Ok(__sdk::parse_reducer_args::<
|
||||
login_or_add_player_reducer::LoginOrAddPlayerArgs,
|
||||
>("login_or_add_player", &value.args)?
|
||||
.into()),
|
||||
"shuffle_wall" => Ok(
|
||||
__sdk::parse_reducer_args::<shuffle_wall_reducer::ShuffleWallArgs>(
|
||||
|
|
@ -151,6 +143,7 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer {
|
|||
#[allow(non_snake_case)]
|
||||
#[doc(hidden)]
|
||||
pub struct DbUpdate {
|
||||
bot: __sdk::TableUpdate<Bot>,
|
||||
hand: __sdk::TableUpdate<Hand>,
|
||||
lobby: __sdk::TableUpdate<Lobby>,
|
||||
player: __sdk::TableUpdate<Player>,
|
||||
|
|
@ -164,6 +157,9 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate {
|
|||
let mut db_update = DbUpdate::default();
|
||||
for table_update in raw.tables {
|
||||
match &table_update.table_name[..] {
|
||||
"bot" => db_update
|
||||
.bot
|
||||
.append(bot_table::parse_table_update(table_update)?),
|
||||
"hand" => db_update
|
||||
.hand
|
||||
.append(hand_table::parse_table_update(table_update)?),
|
||||
|
|
@ -205,6 +201,9 @@ impl __sdk::DbUpdate for DbUpdate {
|
|||
) -> AppliedDiff<'_> {
|
||||
let mut diff = AppliedDiff::default();
|
||||
|
||||
diff.bot = cache
|
||||
.apply_diff_to_table::<Bot>("bot", &self.bot)
|
||||
.with_updates_by_pk(|row| &row.id);
|
||||
diff.hand = cache
|
||||
.apply_diff_to_table::<Hand>("hand", &self.hand)
|
||||
.with_updates_by_pk(|row| &row.player_ident);
|
||||
|
|
@ -227,6 +226,7 @@ impl __sdk::DbUpdate for DbUpdate {
|
|||
#[allow(non_snake_case)]
|
||||
#[doc(hidden)]
|
||||
pub struct AppliedDiff<'r> {
|
||||
bot: __sdk::TableAppliedDiff<'r, Bot>,
|
||||
hand: __sdk::TableAppliedDiff<'r, Hand>,
|
||||
lobby: __sdk::TableAppliedDiff<'r, Lobby>,
|
||||
player: __sdk::TableAppliedDiff<'r, Player>,
|
||||
|
|
@ -245,6 +245,7 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> {
|
|||
event: &EventContext,
|
||||
callbacks: &mut __sdk::DbCallbacks<RemoteModule>,
|
||||
) {
|
||||
callbacks.invoke_table_row_callbacks::<Bot>("bot", &self.bot, event);
|
||||
callbacks.invoke_table_row_callbacks::<Hand>("hand", &self.hand, event);
|
||||
callbacks.invoke_table_row_callbacks::<Lobby>("lobby", &self.lobby, event);
|
||||
callbacks.invoke_table_row_callbacks::<Player>("player", &self.player, event);
|
||||
|
|
@ -969,6 +970,7 @@ impl __sdk::SpacetimeModule for RemoteModule {
|
|||
type SubscriptionHandle = SubscriptionHandle;
|
||||
|
||||
fn register_tables(client_cache: &mut __sdk::ClientCache<Self>) {
|
||||
bot_table::register_table(client_cache);
|
||||
hand_table::register_table(client_cache);
|
||||
lobby_table::register_table(client_cache);
|
||||
player_table::register_table(client_cache);
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ impl<'ctx> __sdk::Table for PlayerTableHandle<'ctx> {
|
|||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
let _table = client_cache.get_or_make_table::<Player>("player");
|
||||
_table.add_unique_constraint::<__sdk::Identity>("identity", |row| &row.identity);
|
||||
_table.add_unique_constraint::<u32>("id", |row| &row.id);
|
||||
}
|
||||
pub struct PlayerUpdateCallbackId(__sdk::CallbackId);
|
||||
|
||||
|
|
@ -142,3 +143,33 @@ impl<'ctx> PlayerIdentityUnique<'ctx> {
|
|||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
||||
/// Access to the `id` unique index on the table `player`,
|
||||
/// which allows point queries on the field of the same name
|
||||
/// via the [`PlayerIdUnique::find`] method.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.player().id().find(...)`.
|
||||
pub struct PlayerIdUnique<'ctx> {
|
||||
imp: __sdk::UniqueConstraintHandle<Player, u32>,
|
||||
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
impl<'ctx> PlayerTableHandle<'ctx> {
|
||||
/// Get a handle on the `id` unique index on the table `player`.
|
||||
pub fn id(&self) -> PlayerIdUnique<'ctx> {
|
||||
PlayerIdUnique {
|
||||
imp: self.imp.get_unique_constraint::<u32>("id"),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> PlayerIdUnique<'ctx> {
|
||||
/// Find the subscribed row whose `id` column value is equal to `col_val`,
|
||||
/// if such a row is present in the client cache.
|
||||
pub fn find(&self, col_val: &u32) -> Option<Player> {
|
||||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
|||
#[sats(crate = __lib)]
|
||||
pub struct Player {
|
||||
pub identity: __sdk::Identity,
|
||||
pub id: u32,
|
||||
pub name: Option<String>,
|
||||
pub lobby_id: u32,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ impl<'ctx> __sdk::Table for WallTableHandle<'ctx> {
|
|||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
let _table = client_cache.get_or_make_table::<Wall>("wall");
|
||||
_table.add_unique_constraint::<u32>("id", |row| &row.id);
|
||||
_table.add_unique_constraint::<u32>("lobby_id", |row| &row.lobby_id);
|
||||
}
|
||||
pub struct WallUpdateCallbackId(__sdk::CallbackId);
|
||||
|
||||
|
|
@ -141,3 +142,33 @@ impl<'ctx> WallIdUnique<'ctx> {
|
|||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
||||
/// Access to the `lobby_id` unique index on the table `wall`,
|
||||
/// which allows point queries on the field of the same name
|
||||
/// via the [`WallLobbyIdUnique::find`] method.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.wall().lobby_id().find(...)`.
|
||||
pub struct WallLobbyIdUnique<'ctx> {
|
||||
imp: __sdk::UniqueConstraintHandle<Wall, u32>,
|
||||
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
impl<'ctx> WallTableHandle<'ctx> {
|
||||
/// Get a handle on the `lobby_id` unique index on the table `wall`.
|
||||
pub fn lobby_id(&self) -> WallLobbyIdUnique<'ctx> {
|
||||
WallLobbyIdUnique {
|
||||
imp: self.imp.get_unique_constraint::<u32>("lobby_id"),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> WallLobbyIdUnique<'ctx> {
|
||||
/// Find the subscribed row whose `lobby_id` column value is equal to `col_val`,
|
||||
/// if such a row is present in the client cache.
|
||||
pub fn find(&self, col_val: &u32) -> Option<Wall> {
|
||||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use super::tile_type::Tile;
|
|||
#[sats(crate = __lib)]
|
||||
pub struct Wall {
|
||||
pub id: u32,
|
||||
pub lobby_id: u32,
|
||||
pub tiles: Vec<Tile>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,55 +1,7 @@
|
|||
use bevy::prelude::*;
|
||||
// use spacetimedb::SpacetimeType;
|
||||
// use strum::FromRepr;
|
||||
|
||||
use jong_types::*;
|
||||
|
||||
// #[derive(Component, Debug, Clone, Copy, SpacetimeType)]
|
||||
// pub struct Tile {
|
||||
// pub suit: Suit,
|
||||
// }
|
||||
|
||||
// #[derive(/* MapEntities, */ Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, SpacetimeType)]
|
||||
// pub enum Suit {
|
||||
// Man(Rank),
|
||||
// Pin(Rank),
|
||||
// Sou(Rank),
|
||||
// Wind(Wind),
|
||||
// Dragon(Dragon),
|
||||
// }
|
||||
|
||||
// impl Suit {
|
||||
// pub fn rank(&self) -> Option<Rank> {
|
||||
// match self {
|
||||
// Suit::Man(rank) => Some(*rank),
|
||||
// Suit::Pin(rank) => Some(*rank),
|
||||
// Suit::Sou(rank) => Some(*rank),
|
||||
// // Suit::Wind(wind) | Suit::Dragon(dragon) => None,
|
||||
// _ => None,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[derive(Deref, DerefMut, Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, SpacetimeType)]
|
||||
// pub struct Rank {
|
||||
// pub number: u8,
|
||||
// }
|
||||
|
||||
// #[derive(FromRepr, Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, SpacetimeType)]
|
||||
// pub enum Wind {
|
||||
// Ton,
|
||||
// Nan,
|
||||
// Shaa,
|
||||
// Pei,
|
||||
// }
|
||||
|
||||
// #[derive(Debug, FromRepr, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, SpacetimeType)]
|
||||
// pub enum Dragon {
|
||||
// Haku,
|
||||
// Hatsu,
|
||||
// Chun,
|
||||
// }
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Dora;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "jongline"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,45 @@
|
|||
use spacetimedb::{rand::seq::SliceRandom, reducer, table, Identity, ReducerContext, Table};
|
||||
use log::info;
|
||||
use spacetimedb::{Identity, ReducerContext, Table, rand::seq::SliceRandom, reducer, table};
|
||||
|
||||
use jong_types::*;
|
||||
|
||||
#[table(name = player)]
|
||||
#[derive(Debug)]
|
||||
#[table(name = player, public)]
|
||||
pub struct Player {
|
||||
#[primary_key]
|
||||
identity: Identity,
|
||||
|
||||
#[auto_inc]
|
||||
#[index(direct)]
|
||||
#[unique]
|
||||
id: u32,
|
||||
|
||||
name: Option<String>,
|
||||
|
||||
#[index(btree)]
|
||||
lobby_id: u32,
|
||||
}
|
||||
|
||||
#[table(name = bot)]
|
||||
pub struct Bot {
|
||||
#[primary_key]
|
||||
#[auto_inc]
|
||||
id: u32,
|
||||
|
||||
#[index(btree)]
|
||||
lobby_id: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[table(name = lobby, public)]
|
||||
pub struct Lobby {
|
||||
#[primary_key]
|
||||
#[auto_inc]
|
||||
id: u32,
|
||||
|
||||
host: Identity,
|
||||
#[index(direct)]
|
||||
#[unique]
|
||||
host_id: u32,
|
||||
}
|
||||
|
||||
#[table(name = wall)]
|
||||
|
|
@ -26,6 +48,10 @@ pub struct Wall {
|
|||
#[auto_inc]
|
||||
id: u32,
|
||||
|
||||
#[index(direct)]
|
||||
#[unique]
|
||||
lobby_id: u32,
|
||||
|
||||
tiles: Vec<Tile>,
|
||||
}
|
||||
|
||||
|
|
@ -42,47 +68,75 @@ pub struct Pond {
|
|||
tiles: Vec<Tile>,
|
||||
}
|
||||
|
||||
#[reducer]
|
||||
pub fn add_player(ctx: &ReducerContext, name: Option<String>) {
|
||||
let identity = ctx.identity();
|
||||
ctx.db.player().insert(Player {
|
||||
identity,
|
||||
name,
|
||||
lobby_id: 0,
|
||||
});
|
||||
}
|
||||
#[reducer(client_connected)]
|
||||
pub fn login_or_add_player(ctx: &ReducerContext) {
|
||||
let identity = ctx.sender;
|
||||
|
||||
#[reducer]
|
||||
pub fn set_name(ctx: &ReducerContext, name: String) -> Result<(), String> {
|
||||
if name.is_empty() {
|
||||
return Err("names must not be empty".into());
|
||||
}
|
||||
if let Some(player) = ctx.db.player().identity().find(ctx.sender) {
|
||||
ctx.db.player().identity().update(Player {
|
||||
name: Some(name),
|
||||
..player
|
||||
});
|
||||
Ok(())
|
||||
// TODO remove player on disconnect
|
||||
if let Ok(player) = ctx.db.player().try_insert(Player {
|
||||
identity,
|
||||
id: 0,
|
||||
name: None,
|
||||
lobby_id: 0,
|
||||
}) {
|
||||
info!("added player: {:?}", player);
|
||||
} else {
|
||||
Err("Cannot set name for unknown user".into())
|
||||
let player = ctx.db.player().identity().find(identity).unwrap();
|
||||
info!("player {:?} has reconnected", player)
|
||||
}
|
||||
}
|
||||
|
||||
#[reducer]
|
||||
pub fn join_or_create_lobby(ctx: &ReducerContext, lobby: Option<u32>) -> Result<(), String> {
|
||||
let player = ctx.db.player().identity().find(ctx.sender).unwrap();
|
||||
let mut player = ctx
|
||||
.db
|
||||
.player()
|
||||
.identity()
|
||||
.find(ctx.sender)
|
||||
.ok_or(format!("cannot find player {}", ctx.sender))?;
|
||||
|
||||
todo!()
|
||||
let lobby_id = lobby.unwrap_or_else(|| {
|
||||
let lobby = ctx.db.lobby().insert(Lobby {
|
||||
id: 0,
|
||||
host_id: player.id,
|
||||
});
|
||||
info!("created lobby: {:?}", lobby);
|
||||
|
||||
lobby.id
|
||||
});
|
||||
|
||||
player.lobby_id = lobby_id;
|
||||
|
||||
let player = ctx.db.player().identity().update(player);
|
||||
|
||||
info!("player {} joined lobby {}", player.id, lobby_id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[reducer]
|
||||
pub fn insert_wall(ctx: &ReducerContext, player_ids: Vec<u32>) {
|
||||
let tiles: Vec<Tile> = tiles();
|
||||
ctx.db.wall().insert(Wall { id: 0, tiles });
|
||||
pub fn add_bot(ctx: &ReducerContext, lobby_id: u32) -> Result<(), String> {
|
||||
if lobby_id == 0 {
|
||||
Err("cannot add a bot without a lobby".into())
|
||||
} else if let Some(lobby) = ctx.db.lobby().id().find(lobby_id)
|
||||
&& (ctx.db.player().lobby_id().filter(lobby_id).count()
|
||||
+ ctx.db.bot().lobby_id().filter(lobby_id).count()
|
||||
<= 4)
|
||||
{
|
||||
let bot = ctx.db.bot().insert(Bot { id: 0, lobby_id });
|
||||
info!("added bot {} to lobby {}", bot.id, lobby_id);
|
||||
Ok(())
|
||||
} else {
|
||||
Err("lobby doesn't exist".into())
|
||||
}
|
||||
}
|
||||
|
||||
#[reducer]
|
||||
pub fn shuffle_wall(ctx: &ReducerContext) {
|
||||
// if let Some(wall) =
|
||||
|
||||
// let mut rng = ctx.rng();
|
||||
// let mut wall = tiles();
|
||||
// wall.shuffle(&mut rng);
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
|
@ -123,3 +177,19 @@ pub fn sort_hand(ctx: &ReducerContext) {
|
|||
// }
|
||||
// log::info!("Hello, World!");
|
||||
// }
|
||||
|
||||
// #[reducer]
|
||||
// pub fn set_name(ctx: &ReducerContext, name: String) -> Result<(), String> {
|
||||
// if name.is_empty() {
|
||||
// return Err("names must not be empty".into());
|
||||
// }
|
||||
// if let Some(player) = ctx.db.player().identity().find(ctx.sender) {
|
||||
// ctx.db.player().identity().update(Player {
|
||||
// name: Some(name),
|
||||
// ..player
|
||||
// });
|
||||
// Ok(())
|
||||
// } else {
|
||||
// Err("cannot set name for unknown user".into())
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue