WIP Add api game events
This commit is contained in:
parent
12ce134047
commit
8c2714b0dd
4 changed files with 83 additions and 27 deletions
|
@ -15,7 +15,7 @@ use tokio::select;
|
|||
use uuid::Uuid;
|
||||
use word_grid::api::{APIGame, ApiState};
|
||||
use word_grid::dictionary::{Dictionary, DictionaryImpl};
|
||||
use word_grid::game::Game;
|
||||
use word_grid::game::{Error, Game, PlayedTile};
|
||||
use word_grid::player_interaction::ai::Difficulty;
|
||||
use ws::stream::DuplexStream;
|
||||
use ws::Message;
|
||||
|
@ -73,17 +73,29 @@ enum RoomEvent {
|
|||
#[serde(tag = "type")]
|
||||
enum ServerToClientMessage {
|
||||
RoomChange { event: RoomEvent, info: PartyInfo },
|
||||
GameEvent { state: ApiState },
|
||||
GameEvent { state: ApiState, committed: bool },
|
||||
GameError { error: Error },
|
||||
Invalid { reason: String },
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
enum GameMove {
|
||||
Pass,
|
||||
Exchange {
|
||||
tiles: Vec<bool>,
|
||||
},
|
||||
Play {
|
||||
played_tiles: Vec<Option<PlayedTile>>,
|
||||
commit_move: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(tag = "type")]
|
||||
enum ClientToServerMessage {
|
||||
RoomChange,
|
||||
Load,
|
||||
StartGame,
|
||||
GameMove,
|
||||
GameMove { r#move: GameMove },
|
||||
AddAI { difficulty: Difficulty },
|
||||
RemoveAI { index: usize },
|
||||
}
|
||||
|
@ -146,8 +158,9 @@ async fn incoming_message_handler<E: std::fmt::Display>(
|
|||
// TODO
|
||||
println!("Received {message:#?} from client {}", player.id);
|
||||
match message {
|
||||
ClientToServerMessage::RoomChange => {}
|
||||
ClientToServerMessage::Load => {}
|
||||
ClientToServerMessage::Load => {
|
||||
return !game_load(player, room, stream).await
|
||||
}
|
||||
ClientToServerMessage::StartGame => {
|
||||
let mut room = room.write().await;
|
||||
if room.game.is_some() {
|
||||
|
@ -176,7 +189,47 @@ async fn incoming_message_handler<E: std::fmt::Display>(
|
|||
sender.send(InnerRoomMessage::GameEvent).unwrap();
|
||||
}
|
||||
}
|
||||
ClientToServerMessage::GameMove => {}
|
||||
ClientToServerMessage::GameMove { r#move } => {
|
||||
let mut room = room.write().await;
|
||||
if room.game.is_none() {
|
||||
let event = ServerToClientMessage::Invalid {
|
||||
reason: format!("Game hasn't been started yet"),
|
||||
};
|
||||
let event = serde_json::to_string(&event).unwrap();
|
||||
let _ = stream.send(event.into()).await;
|
||||
} else {
|
||||
let game = room.game.as_mut().unwrap();
|
||||
let result = match r#move {
|
||||
GameMove::Pass => game.pass(&player.name),
|
||||
GameMove::Exchange { tiles } => {
|
||||
game.exchange(&player.name, tiles)
|
||||
}
|
||||
GameMove::Play {
|
||||
played_tiles,
|
||||
commit_move,
|
||||
} => {
|
||||
let result = game.play(&player.name, played_tiles, commit_move);
|
||||
if result.is_ok() & !commit_move {
|
||||
let event = ServerToClientMessage::GameEvent {state: result.unwrap(), committed: false};
|
||||
let event = serde_json::to_string(&event).unwrap();
|
||||
let _ = stream.send(event.into()).await;
|
||||
return false;
|
||||
}
|
||||
result
|
||||
},
|
||||
};
|
||||
match result {
|
||||
Ok(_) => {
|
||||
sender.send(InnerRoomMessage::GameEvent).unwrap();
|
||||
}
|
||||
Err(error) => {
|
||||
let event = ServerToClientMessage::GameError { error };
|
||||
let event = serde_json::to_string(&event).unwrap();
|
||||
let _ = stream.send(event.into()).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ClientToServerMessage::AddAI { difficulty } => {
|
||||
let mut room = room.write().await;
|
||||
room.party_info.ais.push(difficulty.clone());
|
||||
|
@ -216,6 +269,19 @@ async fn incoming_message_handler<E: std::fmt::Display>(
|
|||
false
|
||||
}
|
||||
|
||||
async fn game_load(player: &Player, room: &Arc<RwLock<Room>>, stream: &mut DuplexStream) -> bool {
|
||||
// The game object was modified; we need to trigger a load from this player's perspective
|
||||
let mut room = room.write().await;
|
||||
|
||||
let state = room.game.as_mut().unwrap().load(&player.name).unwrap();
|
||||
let event = ServerToClientMessage::GameEvent { state, committed: true };
|
||||
|
||||
let text = serde_json::to_string(&event).unwrap();
|
||||
let x = stream.send(text.into()).await;
|
||||
|
||||
x.is_ok()
|
||||
}
|
||||
|
||||
async fn outgoing_message_handler<E: std::fmt::Debug>(
|
||||
message: Result<InnerRoomMessage, E>,
|
||||
_sender: &Sender<InnerRoomMessage>,
|
||||
|
@ -225,22 +291,14 @@ async fn outgoing_message_handler<E: std::fmt::Debug>(
|
|||
) -> bool {
|
||||
let message = message.unwrap();
|
||||
println!("Inner room message - {:#?}", message);
|
||||
let message = match message {
|
||||
InnerRoomMessage::PassThrough(event) => serde_json::to_string(&event).unwrap(),
|
||||
InnerRoomMessage::GameEvent => {
|
||||
// The game object was modified; we need to trigger a load from this player's perspective
|
||||
let mut room = room.write().await;
|
||||
|
||||
let state = room.game.as_mut().unwrap().load(&player.name).unwrap();
|
||||
let event = ServerToClientMessage::GameEvent { state };
|
||||
|
||||
serde_json::to_string(&event).unwrap()
|
||||
return match message {
|
||||
InnerRoomMessage::PassThrough(event) => {
|
||||
let text = serde_json::to_string(&event).unwrap();
|
||||
let x = stream.send(text.into()).await;
|
||||
x.is_err()
|
||||
}
|
||||
InnerRoomMessage::GameEvent => !game_load(player, room, stream).await,
|
||||
};
|
||||
|
||||
let _ = stream.send(message.into()).await;
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[get("/room/<id>?<player_name>")]
|
||||
|
|
|
@ -46,9 +46,7 @@ impl WasmAPI {
|
|||
let tray_tile_locations: Vec<Option<PlayedTile>> =
|
||||
serde_wasm_bindgen::from_value(tray_tile_locations).unwrap();
|
||||
|
||||
let result = self
|
||||
.0
|
||||
.play("Player".to_string(), tray_tile_locations, commit_move);
|
||||
let result = self.0.play("Player", tray_tile_locations, commit_move);
|
||||
serde_wasm_bindgen::to_value(&result).unwrap()
|
||||
}
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ impl APIGame {
|
|||
|
||||
pub fn play(
|
||||
&mut self,
|
||||
player: String,
|
||||
player: &str,
|
||||
tray_tile_locations: Vec<Option<PlayedTile>>,
|
||||
commit_move: bool,
|
||||
) -> Result<ApiState, Error> {
|
||||
|
@ -190,7 +190,7 @@ impl APIGame {
|
|||
let tray = self.0.player_states.get_tray(&player).unwrap().clone();
|
||||
let update = Update {
|
||||
r#type: turn_action,
|
||||
player,
|
||||
player: player.to_string(),
|
||||
};
|
||||
if commit_move {
|
||||
self.1.push(update.clone())
|
||||
|
|
|
@ -20,7 +20,7 @@ pub enum Player {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Error {
|
||||
InvalidPlayer(String),
|
||||
WrongTurn(String),
|
||||
|
|
Loading…
Reference in a new issue