diff --git a/client/src/game/messageListener.tsx b/client/src/game/messageListener.tsx index d38e941d6..b390c2909 100644 --- a/client/src/game/messageListener.tsx +++ b/client/src/game/messageListener.tsx @@ -31,16 +31,16 @@ export default function messageListener(packet: ToClientPacket){ break; case "rejectJoin": switch(packet.reason) { - case "INVALID_ROOM_CODE": + case "invalidRoomCode": Anchor.pushInfo("Couldn't join", "No lobby has that room code!"); break; - case "GAME_ALREADY_STARTED": + case "gameAlreadyStarted": Anchor.pushInfo("Couldn't join", "That game has already begun!"); break; - case "ROOM_FULL": + case "roomFull": Anchor.pushInfo("Couldn't join", "That lobby is full!"); break; - case "SERVER_BUSY": + case "serverBusy": Anchor.pushInfo("Couldn't join", "The server is busy. Try again later!"); break; default: @@ -52,12 +52,24 @@ export default function messageListener(packet: ToClientPacket){ Anchor.setContent(); break; case "rejectStart": + /* + GameEndsInstantly, + RoleListTooSmall, + RoleListCannotCreateRoles, + ZeroTimeGame, + */ switch(packet.reason) { - case "GameEndsInstantly": + case "gameEndsInstantly": Anchor.pushInfo("Couldn't start", "Game would end instantly! Make sure your role list is valid."); break; - case "ZeroTimeGame": - Anchor.pushInfo("Couldn't start", "Make sure your phase time settings are valid!"); + case "roleListTooSmall": + Anchor.pushInfo("Couldn't start", "Role list is too small!"); + break; + case "roleListCannotCreateRoles": + Anchor.pushInfo("Couldn't start", "Role list is invalid! Excluded roles could be the problem."); + break; + case "zeroTimeGame": + Anchor.pushInfo("Couldn't start", "Game has zero time."); break; default: Anchor.pushInfo("Couldn't start", "Failed to start lobby. Try again later!"); @@ -257,7 +269,7 @@ export default function messageListener(packet: ToClientPacket){ if(GAME_MANAGER.state.stateType === "game"){ GAME_MANAGER.state.ticking = false; switch(packet.reason) { - case "ReachedMaxDay": + case "reachedMaxDay": // alert("Game Over: Reached the maximum day!"); console.log("incoming message response not implemented " + packet.type + ": " + packet.reason); console.log(packet); diff --git a/server/src/game/mod.rs b/server/src/game/mod.rs index bd5ca5c87..116f9b51f 100644 --- a/server/src/game/mod.rs +++ b/server/src/game/mod.rs @@ -17,13 +17,13 @@ pub mod recruit; use std::time::Duration; use rand::seq::SliceRandom; use rand::thread_rng; +use serde::Serialize; use crate::lobby::LobbyPlayer; -use crate::log; -use crate::packet::{ToClientPacket, GameOverReason}; +use crate::packet::ToClientPacket; use chat::{ChatMessage, ChatGroup}; use player::PlayerReference; -use role_list::{RoleOutline, create_random_roles}; +use role_list::create_random_roles; use player::Player; use phase::PhaseStateMachine; use settings::Settings; @@ -48,20 +48,43 @@ pub struct Game { pub ticking: bool } +#[derive(Serialize, Debug, Clone, Copy)] +#[serde(rename_all = "camelCase")] +pub enum RejectStartReason { + GameEndsInstantly, + RoleListTooSmall, + RoleListCannotCreateRoles, + ZeroTimeGame, +} + +#[derive(Serialize, Debug, Clone, Copy)] +#[serde(rename_all = "camelCase")] +pub enum GameOverReason { + ReachedMaxDay, + Winner, + Draw + /*TODO Winner { who won? }*/ +} + impl Game { - pub fn new(mut settings: Settings, lobby_players: Vec) -> Self{ + pub fn new(settings: Settings, lobby_players: Vec) -> Result{ + //check settings are not completly off the rails + if [ + settings.phase_times.evening, settings.phase_times.morning, + settings.phase_times.discussion, settings.phase_times.voting, + settings.phase_times.judgement, settings.phase_times.testimony, + settings.phase_times.night, + ].iter().all(|t| *t == 0) { + return Err(RejectStartReason::ZeroTimeGame); + } + + let mut roles = match create_random_roles(&settings.excluded_roles, &settings.role_list){ Some(roles) => { roles }, None => { - let mut new_list = vec![]; - for _ in 0..lobby_players.len(){ - new_list.push(RoleOutline::Any); - } - settings.role_list = new_list; - settings.excluded_roles = vec![]; - create_random_roles(&settings.excluded_roles, &settings.role_list).expect("All any with no exclusions should have open roles") + return Err(RejectStartReason::RoleListCannotCreateRoles); } }; roles.shuffle(&mut thread_rng()); @@ -74,8 +97,7 @@ impl Game { match roles.get(player_index){ Some(role) => *role, None => { - log!(error "Game::new"; "Failed to generate role. rolelist wasnt big enough for number of players"); - RoleOutline::Any.get_random_role(&settings.excluded_roles, &roles).expect("Any should have open roles") + return Err(RejectStartReason::RoleListTooSmall); }, } ); @@ -104,7 +126,7 @@ impl Game { Teams::on_team_creation(&mut game); - game + Ok(game) } /// Returns a tuple containing the number of guilty votes and the number of innocent votes diff --git a/server/src/game/player/player_send_packet.rs b/server/src/game/player/player_send_packet.rs index 537a6c092..96d003d51 100644 --- a/server/src/game/player/player_send_packet.rs +++ b/server/src/game/player/player_send_packet.rs @@ -1,6 +1,6 @@ use std::time::Duration; -use crate::{game::{Game, available_buttons::AvailableButtons, phase::PhaseState}, packet::{ToClientPacket, GameOverReason}, websocket_connections::connection::ClientSender}; +use crate::{game::{Game, available_buttons::AvailableButtons, phase::PhaseState, GameOverReason}, packet::ToClientPacket, websocket_connections::connection::ClientSender}; use super::{PlayerReference, ClientConnection, DISCONNECT_TIMER_SECS}; diff --git a/server/src/lib.rs b/server/src/lib.rs index d10c4815c..e8a109af8 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -16,6 +16,15 @@ pub mod log { /// log!(error "Game::new"; "Failed to generate role. rolelist wasnt big enough for number of players"); /// log!(info "Listener"; "{}: {}", "Received message", "message"); /// ``` + /// + /// # Markers + /// - `fatal`: Prints the word FATAL + /// - `error`: Prints red and writes "WARN" + /// - `important`: + /// - `info`: + /// + /// if none are put then it defaults to info + /// macro_rules! log { // Each case in this macro definition is for a different log marker. // None diff --git a/server/src/lobby.rs b/server/src/lobby.rs index 8f5a5439d..286927d0b 100644 --- a/server/src/lobby.rs +++ b/server/src/lobby.rs @@ -8,7 +8,7 @@ use crate::{ role_list::RoleOutline, phase::PhaseType }, - listener::{PlayerID, RoomCode}, packet::{ToClientPacket, RejectJoinReason, ToServerPacket, RejectStartReason}, websocket_connections::connection::ClientSender, log + listener::{PlayerID, RoomCode}, packet::{ToClientPacket, RejectJoinReason, ToServerPacket}, websocket_connections::connection::ClientSender, log }; pub struct Lobby { @@ -88,29 +88,18 @@ impl Lobby { Self::send_players_lobby(players); }, ToServerPacket::StartGame => { - let LobbyState::Lobby { settings, players } = &mut self.lobby_state else { + let LobbyState::Lobby { settings: _, players } = &mut self.lobby_state else { log!(error "Lobby"; "{} {}", "ToServerPacket::StartGame can not be used outside of LobbyState::Lobby", player_id); return; }; if let Some(player) = players.get(&player_id){ if !player.host {return;} } - - if [ - settings.phase_times.evening, settings.phase_times.morning, - settings.phase_times.discussion, settings.phase_times.voting, - settings.phase_times.judgement, settings.phase_times.testimony, - settings.phase_times.night, - ].iter().all(|t| *t == 0) { - send.send(ToClientPacket::RejectStart { reason: RejectStartReason::ZeroTimeGame }); - return; - } let mut player_indices: HashMap = HashMap::new(); let mut game_players = Vec::new(); - self.send_to_all(ToClientPacket::StartGame); let LobbyState::Lobby { settings, players} = &mut self.lobby_state else { unreachable!("LobbyState::Lobby was checked to be to LobbyState::Lobby in the previous line") @@ -121,10 +110,19 @@ impl Lobby { game_players.push(lobby_player); } + let game = match Game::new(settings.clone(), game_players){ + Ok(game) => game, + Err(err) => { + send.send(ToClientPacket::RejectStart { reason: err }); + log!(info "Lobby"; "Failed to start game: {:?}", err); + return; + } + }; + self.send_to_all(ToClientPacket::StartGame); self.lobby_state = LobbyState::Game{ - game: Game::new(settings.clone(), game_players), + game, players: player_indices, }; let LobbyState::Game { game, players: _player } = &mut self.lobby_state else { diff --git a/server/src/packet.rs b/server/src/packet.rs index 5af3e02e3..7a15d58f5 100644 --- a/server/src/packet.rs +++ b/server/src/packet.rs @@ -26,7 +26,7 @@ use crate::{game::{ verdict::Verdict, phase::PhaseType, chat::ChatMessage, role::{Role, RoleState, doomsayer::DoomsayerGuess}, - Game, grave::Grave, available_buttons::AvailableButtons, tag::Tag, settings::PhaseTimeSettings + Game, grave::Grave, available_buttons::AvailableButtons, tag::Tag, settings::PhaseTimeSettings, RejectStartReason, GameOverReason }, listener::{RoomCode, PlayerID}, log}; #[derive(Serialize, Debug, Clone)] @@ -128,7 +128,7 @@ impl ToClientPacket { } #[derive(Serialize, Debug, Clone, Copy)] -#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "camelCase")] pub enum RejectJoinReason { GameAlreadyStarted, RoomFull, @@ -136,22 +136,6 @@ pub enum RejectJoinReason { ServerBusy, } -#[derive(Serialize, Debug, Clone, Copy)] -#[serde(rename_all = "SCREAMING_SNAKE_CASE")] -pub enum RejectStartReason { - GameEndsInstantly, - ZeroTimeGame, -} - -#[derive(Serialize, Debug, Clone, Copy)] -#[serde(rename_all = "SCREAMING_SNAKE_CASE")] -pub enum GameOverReason { - ReachedMaxDay, - Winner, - Draw - /*TODO Winner { who won? }*/ -} - #[derive(Deserialize, Debug, Clone)] #[serde(tag = "type", rename_all = "camelCase")] pub enum ToServerPacket{