Handle bug that happens when a player leaves the game in an early stage

This commit is contained in:
Pierre HUBERT 2022-10-16 18:25:59 +02:00
parent 04ee20dac2
commit 70d70c2851
5 changed files with 21 additions and 3 deletions

View File

@ -132,6 +132,7 @@ async fn run_app<B: Backend>(terminal: &mut Terminal<B>) -> Res {
#[tokio::main] #[tokio::main]
pub async fn main() -> Result<(), Box<dyn Error>> { pub async fn main() -> Result<(), Box<dyn Error>> {
env_logger::Builder::from_env(Env::default()).init(); env_logger::Builder::from_env(Env::default()).init();
cli_args(); // Avoid a crash if help argument is triggered
// setup terminal // setup terminal
enable_raw_mode()?; enable_raw_mode()?;

View File

@ -68,6 +68,14 @@ enum GameStatus {
RematchRejected, RematchRejected,
} }
impl GameStatus {
pub fn can_game_continue_with_bot(&self) -> bool {
*self != GameStatus::Finished
&& *self != GameStatus::RematchRejected
&& *self != GameStatus::RematchRejected
}
}
pub struct Game { pub struct Game {
rules: GameRules, rules: GameRules,
players: Vec<Arc<dyn Player>>, players: Vec<Arc<dyn Player>>,
@ -363,7 +371,9 @@ impl Handler<PlayerLeftGame> for Game {
self.players[opponent(offline_player)].opponent_left_game(); self.players[opponent(offline_player)].opponent_left_game();
// If the other player is a bot or if the game is not running, stop the game // If the other player is a bot or if the game is not running, stop the game
if self.status != GameStatus::Started || self.players[opponent(offline_player)].is_bot() { if !self.status.can_game_continue_with_bot()
|| self.players[opponent(offline_player)].is_bot()
{
ctx.stop(); ctx.stop();
} else { } else {
// Replace the player with a bot // Replace the player with a bot
@ -371,8 +381,11 @@ impl Handler<PlayerLeftGame> for Game {
Arc::new(BotPlayer::new(self.rules.bot_type, ctx.address())); Arc::new(BotPlayer::new(self.rules.bot_type, ctx.address()));
self.players[opponent(offline_player)].opponent_replaced_by_bot(); self.players[opponent(offline_player)].opponent_replaced_by_bot();
if self.turn == offline_player { // Re-do current action
if self.status == GameStatus::Started {
self.request_fire(); self.request_fire();
} else if self.status == GameStatus::WaitingForBoatsDisposition {
self.players[offline_player].query_boats_layout(&self.rules);
} }
} }
} }

View File

@ -109,6 +109,7 @@ impl Player for HumanPlayer {
impl HumanPlayer { impl HumanPlayer {
pub fn handle_client_message(&self, msg: ClientMessage) { pub fn handle_client_message(&self, msg: ClientMessage) {
log::debug!("Got message from client: {:?}", msg);
match msg { match msg {
ClientMessage::StopGame => self.game.do_send(PlayerLeftGame(self.uuid)), ClientMessage::StopGame => self.game.do_send(PlayerLeftGame(self.uuid)),
ClientMessage::BoatsLayout { layout } => { ClientMessage::BoatsLayout { layout } => {

View File

@ -222,7 +222,7 @@ impl StreamHandler<Result<ws::Message, ProtocolError>> for HumanPlayerWS {
log::warn!("Got unsupported continuation message!"); log::warn!("Got unsupported continuation message!");
} }
Ok(Message::Pong(_)) => { Ok(Message::Pong(_)) => {
log::info!("Got pong message"); log::debug!("Got pong message");
self.hb = Instant::now(); self.hb = Instant::now();
} }
Ok(Message::Close(reason)) => { Ok(Message::Close(reason)) => {
@ -238,6 +238,7 @@ impl Handler<ServerMessage> for HumanPlayerWS {
type Result = (); type Result = ();
fn handle(&mut self, msg: ServerMessage, ctx: &mut Self::Context) -> Self::Result { fn handle(&mut self, msg: ServerMessage, ctx: &mut Self::Context) -> Self::Result {
log::debug!("Send message through WS: {:?}", msg);
ctx.text(serde_json::to_string(&msg).unwrap()); ctx.text(serde_json::to_string(&msg).unwrap());
} }
} }

View File

@ -131,6 +131,8 @@ async fn start_random(
resp resp
} }
pub async fn start_server(args: Args) -> std::io::Result<()> { pub async fn start_server(args: Args) -> std::io::Result<()> {
log::info!("Start to listen on {}", args.listen_address);
let args_clone = args.clone(); let args_clone = args.clone();
let dispatcher_actor = DispatcherActor::default().start(); let dispatcher_actor = DispatcherActor::default().start();