|
@@ -1,18 +1,16 @@
|
|
|
use std::collections::BTreeMap;
|
|
|
use std::sync::Arc;
|
|
|
-use std::borrow::Borrow;
|
|
|
|
|
|
use rand::thread_rng;
|
|
|
use rand::seq::SliceRandom;
|
|
|
|
|
|
use actix::prelude::*;
|
|
|
+use log::info;
|
|
|
|
|
|
use crate::server::server::{GameConnection, Server};
|
|
|
use crate::datasource;
|
|
|
use crate::game;
|
|
|
-use crate::websocket;
|
|
|
-use crate::websocket::*;
|
|
|
-
|
|
|
+use crate::server::protocol::*;
|
|
|
use crate::server::messages::*;
|
|
|
|
|
|
#[derive(PartialEq)]
|
|
@@ -40,7 +38,7 @@ pub struct GameLobby {
|
|
|
|
|
|
impl Actor for GameLobby {
|
|
|
type Context = Context<Self>;
|
|
|
- fn started(&mut self, ctx: &mut Self::Context) {
|
|
|
+ fn started(&mut self, _ctx: &mut Self::Context) {
|
|
|
self.lobby_state = LobbyState::Starting;
|
|
|
}
|
|
|
}
|
|
@@ -57,11 +55,11 @@ impl Handler<JoinRequest> for GameLobby {
|
|
|
LobbyJoined {
|
|
|
lobby: ctx.address(),
|
|
|
game_id: self.game_id.clone(),
|
|
|
- nick: jr.nick
|
|
|
+ nick: jr.nick.clone()
|
|
|
}
|
|
|
);
|
|
|
-
|
|
|
self.send_game_to_all();
|
|
|
+ info!("Player {} joined lobby {}", jr.nick, self.game_id);
|
|
|
}
|
|
|
else {
|
|
|
self.waiting_players.insert(jr.nick.clone(), jr.p);
|
|
@@ -74,6 +72,7 @@ impl Handler<LeaveMsg> for GameLobby {
|
|
|
fn handle(&mut self, lm: LeaveMsg, _ctx: &mut Self::Context) -> Self::Result {
|
|
|
self.waiting_players.remove(&lm.0);
|
|
|
self.connected_players.remove(&lm.0);
|
|
|
+ self.ready_players.retain(|p| p != &lm.0);
|
|
|
self.game.remove_player(&lm.0);
|
|
|
|
|
|
if self.connected_players.is_empty() {
|
|
@@ -88,6 +87,8 @@ impl Handler<ReadyMsg> for GameLobby {
|
|
|
if !self.ready_players.contains(&rm.0) {
|
|
|
self.ready_players.push(rm.0);
|
|
|
}
|
|
|
+ self.send_playerlist_to_all();
|
|
|
+
|
|
|
if self.ready_players.len() >= self.connected_players.len() {
|
|
|
self.set_state(LobbyState::Creating);
|
|
|
self.send_game_to_all();
|
|
@@ -95,6 +96,14 @@ impl Handler<ReadyMsg> for GameLobby {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+impl Handler<UnreadyMsg> for GameLobby {
|
|
|
+ type Result = ();
|
|
|
+ fn handle(&mut self, urm: UnreadyMsg, _ctx: &mut Self::Context) -> Self::Result {
|
|
|
+ self.ready_players.retain(|p| p != &urm.0);
|
|
|
+ self.send_playerlist_to_all();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
impl Handler<SubmitWordMsg> for GameLobby {
|
|
|
type Result = ();
|
|
|
fn handle(&mut self, swm: SubmitWordMsg, _ctx: &mut Self::Context) -> Self::Result {
|
|
@@ -104,6 +113,9 @@ impl Handler<SubmitWordMsg> for GameLobby {
|
|
|
self.game.next_state();
|
|
|
self.send_game_to_all();
|
|
|
}
|
|
|
+ else {
|
|
|
+ self.send_playerlist_to_all();
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -125,6 +137,9 @@ impl Handler<SubmitGuessMsg> for GameLobby {
|
|
|
self.game.next_state();
|
|
|
self.send_game_to_all();
|
|
|
}
|
|
|
+ else {
|
|
|
+ self.send_playerlist_to_all();
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -151,7 +166,6 @@ impl GameLobby {
|
|
|
self.game.player_join(nick.clone());
|
|
|
}
|
|
|
self.connected_players.append(&mut self.waiting_players);
|
|
|
- self.ready_players.clear();
|
|
|
},
|
|
|
LobbyState::Creating => {
|
|
|
let s = &mut self.shuffler;
|
|
@@ -160,6 +174,7 @@ impl GameLobby {
|
|
|
},
|
|
|
_ => {}
|
|
|
}
|
|
|
+ self.ready_players.clear();
|
|
|
self.lobby_state = new_state;
|
|
|
}
|
|
|
|
|
@@ -182,6 +197,13 @@ impl GameLobby {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ pub fn send_playerlist_to_all(&self) {
|
|
|
+ let player_list = self.create_playerlist();
|
|
|
+ for (_nick, player) in &self.connected_players {
|
|
|
+ player.do_send(PlayerListUpdate{ player_list: player_list.clone() });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
pub fn create_result_data(&self) -> RoundResultData {
|
|
|
let (guesses, point_list) = self.game.create_results();
|
|
|
|
|
@@ -212,14 +234,40 @@ impl GameLobby {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ ///
|
|
|
+ /// determines if a player is ready to progress into the next game state
|
|
|
+ ///
|
|
|
+ fn player_is_ready(&self, nick: &str) -> bool {
|
|
|
+ match self.lobby_state {
|
|
|
+ LobbyState::Starting => self.ready_players.iter().any(|p| p == nick),
|
|
|
+ LobbyState::Creating => self.game.get_player(nick)
|
|
|
+ .map(|p| p.has_submitted_word())
|
|
|
+ .unwrap_or(false),
|
|
|
+ LobbyState::Guessing => self.game.get_player(nick)
|
|
|
+ .map(|p| p.has_submitted_guess())
|
|
|
+ .unwrap_or(false),
|
|
|
+ LobbyState::Revealing => self.ready_players.iter().any(|p| p == nick)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ fn create_playerlist(&self) -> Vec<PlayerData> {
|
|
|
+ self.game.players.iter()
|
|
|
+ .map(|p|
|
|
|
+ PlayerData {
|
|
|
+ nick: p.nick.clone(),
|
|
|
+ points: self.get_player_points(&p.nick),
|
|
|
+ ready: self.player_is_ready(&p.nick),
|
|
|
+ })
|
|
|
+ .collect::<Vec<_>>()
|
|
|
+ }
|
|
|
+
|
|
|
pub fn create_opaque_message(&self, nick: &str) -> GameData {
|
|
|
|
|
|
let player = self.game.players.iter()
|
|
|
.find(|p| p.nick == nick);
|
|
|
GameData {
|
|
|
- players: self.game.players.iter()
|
|
|
- .map(|p| websocket::PlayerData{ nick: p.nick.clone(), points: self.get_player_points(&p.nick) })
|
|
|
- .collect::<Vec<_>>(),
|
|
|
+ players: self.create_playerlist(),
|
|
|
state_data:
|
|
|
match self.game.state {
|
|
|
game::GameState::Starting => {
|