Automatically replace player by boat if he leaves game

This commit is contained in:
Pierre HUBERT 2022-09-16 17:59:07 +02:00
parent 45060ae14b
commit 6efaa81ecb
5 changed files with 69 additions and 3 deletions

View File

@ -5,12 +5,15 @@ use actix::{Actor, Context, Handler};
use uuid::Uuid;
use crate::data::*;
use crate::random_bot::RandomBot;
pub trait Player {
fn get_name(&self) -> &str;
fn get_uid(&self) -> Uuid;
fn is_bot(&self) -> bool;
fn set_other_player_name(&self, name: &str);
fn query_boats_layout(&self, rules: &GameRules);
@ -38,6 +41,10 @@ pub trait Player {
fn opponent_rejected_rematch(&self);
fn opponent_accepted_rematch(&self);
fn opponent_left_game(&self);
fn opponent_replaced_by_bot(&self);
}
fn opponent(index: usize) -> usize {
@ -338,3 +345,29 @@ impl Handler<RespondRequestRematch> for Game {
self.handle_request_rematch_response(msg.1);
}
}
#[derive(Message, Debug)]
#[rtype(result = "()")]
pub struct PlayerLeftGame(pub Uuid);
impl Handler<PlayerLeftGame> for Game {
type Result = ();
fn handle(&mut self, msg: PlayerLeftGame, ctx: &mut Self::Context) -> Self::Result {
let offline_player = self.player_id_by_uuid(msg.0);
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 self.status != GameStatus::Started || self.players[opponent(offline_player)].is_bot() {
ctx.stop();
} else {
// Replace the player with a bot
self.players[offline_player] = Arc::new(RandomBot::new(ctx.address()));
self.players[opponent(offline_player)].opponent_replaced_by_bot();
if self.turn == offline_player {
self.request_fire();
}
}
}
}

View File

@ -21,6 +21,10 @@ impl Player for HumanPlayer {
self.uuid
}
fn is_bot(&self) -> bool {
false
}
fn set_other_player_name(&self, name: &str) {
self.player.do_send(ServerMessage::SetOpponentName {
name: name.to_string(),
@ -95,14 +99,20 @@ impl Player for HumanPlayer {
fn opponent_accepted_rematch(&self) {
self.player.do_send(ServerMessage::OpponentAcceptedRematch);
}
fn opponent_left_game(&self) {
self.player.do_send(ServerMessage::OpponentLeftGame);
}
fn opponent_replaced_by_bot(&self) {
self.player.do_send(ServerMessage::OpponentReplacedByBot);
}
}
impl HumanPlayer {
pub fn handle_client_message(&self, msg: ClientMessage) {
match msg {
ClientMessage::StopGame => {
// TODO : do something
}
ClientMessage::StopGame => self.game.do_send(PlayerLeftGame(self.uuid)),
ClientMessage::BoatsLayout { layout } => {
self.game.do_send(SetBoatsLayout(self.uuid, layout))
}

View File

@ -82,6 +82,8 @@ pub enum ServerMessage {
OpponentRequestedRematch,
OpponentAcceptedRematch,
OpponentRejectedRematch,
OpponentLeftGame,
OpponentReplacedByBot,
}
pub struct HumanPlayerWS {

View File

@ -28,6 +28,10 @@ impl Player for RandomBot {
self.uuid
}
fn is_bot(&self) -> bool {
true
}
fn set_other_player_name(&self, _name: &str) {}
fn query_boats_layout(&self, rules: &GameRules) {
@ -71,4 +75,13 @@ impl Player for RandomBot {
fn opponent_rejected_rematch(&self) {}
fn opponent_accepted_rematch(&self) {}
fn opponent_left_game(&self) {
// Human are not reliable lol
}
fn opponent_replaced_by_bot(&self) {
// Not such a good idea. will panic, just in case
panic!("Bot shall not play against each other (it is completely useless)");
}
}

View File

@ -12,6 +12,7 @@ pub enum ClientEndResult {
Finished,
InvalidBoatsLayout,
OpponentRejectedRematch,
OpponentLeftGame,
}
pub struct BotClient {
@ -197,6 +198,13 @@ impl BotClient {
log::debug!("Opponent rejected rematch");
return Ok(ClientEndResult::OpponentRejectedRematch);
}
ServerMessage::OpponentLeftGame => {
log::debug!("Opponent left game");
return Ok(ClientEndResult::OpponentLeftGame);
}
ServerMessage::OpponentReplacedByBot => {
log::debug!("Opponent replaced by bot");
}
}
}