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{