server.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. use std::collections::BTreeMap;
  2. use std::collections::BTreeSet;
  3. use std::time::{Duration, Instant};
  4. use std::sync::{Mutex, RwLock, Arc};
  5. use actix::dev::{MessageResponse, ResponseChannel};
  6. use actix::prelude::*;
  7. use actix_web::{web, Error, HttpRequest, HttpResponse};
  8. use actix_web_actors::ws;
  9. use rand::thread_rng;
  10. use rand::seq::SliceRandom;
  11. use crate::game;
  12. use crate::websocket;
  13. use crate::websocket::*;
  14. const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
  15. const CLIENT_TIMEOUT: Duration = Duration::from_secs(10);
  16. #[derive(Message)]
  17. #[rtype(result = "Answer")]
  18. struct JoinRequest{ lobby_id: String, nick: String, p: Addr<GameConnection> }
  19. #[derive(Message)]
  20. #[rtype(result = "Answer")]
  21. struct CreateLobbyRequest{ lobby_id: String, p: Addr<GameConnection> }
  22. #[derive(Message)]
  23. #[rtype(result = "()")]
  24. struct ReadyMsg(String);
  25. #[derive(Message)]
  26. #[rtype(result = "()")]
  27. struct SubmitWordMsg{ word: String, nick: String }
  28. #[derive(Message)]
  29. #[rtype(result = "()")]
  30. struct SubmitGuessMsg{ guesses: Vec<(String, String)>, nick: String }
  31. #[derive(Message)]
  32. #[rtype(result = "()")]
  33. struct ResultMsg{ results: RoundResultData }
  34. #[derive(Message)]
  35. #[rtype(result = "Result<game::Game, ()>")]
  36. struct GetGame;
  37. #[derive(Message)]
  38. #[rtype(result = "()")]
  39. struct NoSuchLobby(String);
  40. #[derive(Message)]
  41. #[rtype(result = "()")]
  42. struct LobbyJoined(Addr<GameLobby>);
  43. #[derive(Message)]
  44. #[rtype(result = "()")]
  45. struct GameUpdate{ game_data: GameData }
  46. enum Answer {
  47. LobbyJoined(Addr<GameLobby>),
  48. LobbyCreated(Addr<GameLobby>),
  49. LobbyAlreadyExists,
  50. NoSuchLobby,
  51. }
  52. impl<A, M> MessageResponse<A, M> for Answer
  53. where
  54. A: Actor,
  55. M: Message<Result = Answer>,
  56. {
  57. fn handle<R: ResponseChannel<M>>(self, _: &mut A::Context, tx: Option<R>) {
  58. if let Some(tx) = tx {
  59. tx.send(self);
  60. }
  61. }
  62. }
  63. impl<A, M> MessageResponse<A, M> for game::Game
  64. where
  65. A: Actor,
  66. M: Message<Result = game::Game>,
  67. {
  68. fn handle<R: ResponseChannel<M>>(self, _: &mut A::Context, tx: Option<R>) {
  69. if let Some(tx) = tx {
  70. tx.send(self);
  71. }
  72. }
  73. }
  74. pub struct Server {
  75. pub lobbies: BTreeMap<String, Addr<GameLobby>>,
  76. }
  77. impl Actor for Server {
  78. type Context = Context<Self>;
  79. fn started(&mut self, ctx: &mut Self::Context) {
  80. }
  81. }
  82. impl Handler<JoinRequest> for Server {
  83. type Result = Answer;
  84. fn handle(&mut self, jr: JoinRequest, ctx: &mut Self::Context) -> Self::Result {
  85. let mb_lobby = self.lobbies.get(&jr.lobby_id);
  86. match mb_lobby {
  87. Some(lobby) => {
  88. let _sent = lobby.do_send(jr);
  89. Answer::LobbyJoined(lobby.clone())
  90. },
  91. None => {
  92. jr.p.do_send(NoSuchLobby(jr.lobby_id));
  93. Answer::NoSuchLobby
  94. }
  95. }
  96. }
  97. }
  98. impl Handler<CreateLobbyRequest> for Server {
  99. type Result = Answer;
  100. fn handle(&mut self, clr: CreateLobbyRequest, ctx: &mut Self::Context) -> Self::Result {
  101. let existing_lobby = self.lobbies.get(&clr.lobby_id);
  102. match existing_lobby {
  103. Some(_) => Answer::LobbyAlreadyExists,
  104. None => {
  105. let lobby = GameLobby::new(clr.lobby_id.clone());
  106. let lobby_addr = lobby.start();
  107. self.lobbies.insert(clr.lobby_id.clone(), lobby_addr.clone());
  108. Answer::LobbyCreated(lobby_addr)
  109. }
  110. }
  111. }
  112. }
  113. #[derive(PartialEq)]
  114. enum LobbyState {
  115. Starting,
  116. Creating,
  117. Guessing,
  118. Revealing
  119. }
  120. pub struct GameLobby {
  121. connected_players: BTreeMap<String, Addr<GameConnection>>,
  122. game_id: String,
  123. game: game::Game,
  124. waiting_players: BTreeMap<String, Addr<GameConnection>>,
  125. ready_players: Vec<String>,
  126. lobby_state: LobbyState
  127. }
  128. impl Actor for GameLobby {
  129. type Context = Context<Self>;
  130. fn started(&mut self, ctx: &mut Self::Context) {
  131. self.lobby_state = LobbyState::Starting;
  132. }
  133. }
  134. impl Handler<JoinRequest> for GameLobby {
  135. type Result = Answer;
  136. fn handle(&mut self, jr: JoinRequest, ctx: &mut Self::Context) -> Self::Result {
  137. if self.lobby_state == LobbyState::Starting {
  138. jr.p.do_send(LobbyJoined(ctx.address()));
  139. self.connected_players.insert(jr.nick.clone(), jr.p);
  140. self.game.player_join(jr.nick);
  141. self.send_game_to_all();
  142. Answer::LobbyJoined(ctx.address())
  143. }
  144. else {
  145. self.waiting_players.insert(jr.nick.clone(), jr.p);
  146. Answer::NoSuchLobby
  147. }
  148. }
  149. }
  150. impl Handler<ReadyMsg> for GameLobby {
  151. type Result = ();
  152. fn handle(&mut self, rm: ReadyMsg, ctx: &mut Self::Context) -> Self::Result {
  153. if !self.ready_players.contains(&rm.0) {
  154. self.ready_players.push(rm.0);
  155. }
  156. if self.ready_players.len() >= self.connected_players.len() {
  157. self.set_state(LobbyState::Creating);
  158. self.send_game_to_all();
  159. }
  160. }
  161. }
  162. impl Handler<GetGame> for GameLobby {
  163. type Result = Result<game::Game, ()>;
  164. fn handle(&mut self, gg: GetGame, ctx: &mut Self::Context) -> Self::Result {
  165. Ok(self.game.clone())
  166. }
  167. }
  168. impl Handler<SubmitWordMsg> for GameLobby {
  169. type Result = ();
  170. fn handle(&mut self, swm: SubmitWordMsg, ctx: &mut Self::Context) -> Self::Result {
  171. let correct = self.game.submit_creation(&swm.nick, swm.word);
  172. if self.game.all_words_submitted() {
  173. self.set_state(LobbyState::Guessing);
  174. self.game.next_state();
  175. self.send_game_to_all();
  176. }
  177. }
  178. }
  179. impl Handler<SubmitGuessMsg> for GameLobby {
  180. type Result = ();
  181. fn handle(&mut self, sgm: SubmitGuessMsg, ctx: &mut Self::Context) -> Self::Result {
  182. self.game.submit_guess(&sgm.nick, sgm.guesses);
  183. if self.game.all_guesses_submitted() {
  184. self.set_state(LobbyState::Revealing);
  185. let results = self.create_result_data();
  186. self.broadcast_results(results);
  187. self.game.next_state();
  188. self.send_game_to_all();
  189. }
  190. }
  191. }
  192. impl GameLobby {
  193. pub fn new(gi: String) -> Self {
  194. GameLobby {
  195. connected_players: BTreeMap::new(),
  196. game_id: gi,
  197. game: game::Game::new(),
  198. waiting_players: BTreeMap::new(),
  199. ready_players: Vec::new(),
  200. lobby_state: LobbyState::Starting,
  201. }
  202. }
  203. fn set_state(&mut self, new_state: LobbyState) {
  204. match new_state {
  205. LobbyState::Starting => {
  206. for (nick, _addr) in &self.waiting_players {
  207. self.game.player_join(nick.clone());
  208. }
  209. self.connected_players.append(&mut self.waiting_players);
  210. self.ready_players.clear();
  211. },
  212. LobbyState::Creating => {
  213. self.game.start_round();
  214. },
  215. _ => {}
  216. }
  217. self.lobby_state = new_state;
  218. }
  219. pub fn send_game_to_all(&self) {
  220. for (nick, player) in &self.connected_players {
  221. let game_state = self.create_opaque_message(nick);
  222. player.do_send(GameUpdate{ game_data: game_state });
  223. }
  224. }
  225. pub fn create_result_data(&self) -> RoundResultData {
  226. let results_table = self.game.create_results();
  227. let words = self.game.players.iter()
  228. .map(|p| p.submitted_word.clone().unwrap())
  229. .collect::<Vec<_>>();
  230. let questions = self.game.players.iter()
  231. .map(|x| x.creating_exercise.as_ref().unwrap())
  232. .chain(self.game.additional_questions.iter())
  233. .map(|x| x.question.clone())
  234. .collect::<Vec<_>>();
  235. let solutions = words.iter()
  236. .map(|x| x.clone())
  237. .zip(questions.iter().map(|x| x.clone()))
  238. .collect::<Vec<_>>();
  239. let guesses = self.game.create_results();
  240. RoundResultData {
  241. words,
  242. questions,
  243. solutions,
  244. guesses
  245. }
  246. }
  247. pub fn broadcast_results(&self, results: RoundResultData) {
  248. for (_nick, player) in &self.connected_players {
  249. player.do_send(ResultMsg{ results: results.clone() });
  250. }
  251. }
  252. pub fn create_opaque_message(&self, nick: &str) -> GameData {
  253. let player = self.game.players.iter()
  254. .find(|p| p.nick == nick);
  255. GameData {
  256. players: self.game.players.iter()
  257. .map(|p| websocket::PlayerData{ nick: p.nick.clone(), points: 0 })
  258. .collect::<Vec<_>>(),
  259. state_data:
  260. match self.game.state {
  261. game::GameState::Starting => {
  262. GameStateData::Starting
  263. },
  264. game::GameState::Creating => {
  265. GameStateData::Creating{
  266. question: player.unwrap().creating_exercise.as_ref().unwrap().question.clone(),
  267. available_chars: player.unwrap().creating_exercise.as_ref().unwrap().letters.clone()
  268. }
  269. },
  270. game::GameState::Guessing => {
  271. self.create_guessing()
  272. },
  273. }
  274. }
  275. }
  276. pub fn check_optionals(&self) {
  277. for p in &self.game.players {
  278. println!("{:?}", p);
  279. }
  280. }
  281. pub fn create_guessing(&self) -> GameStateData {
  282. self.check_optionals();
  283. let words_with_chars = self.game.players.iter()
  284. .map(|p|
  285. (p.submitted_word.clone().unwrap(),
  286. p.creating_exercise.clone().unwrap().letters))
  287. .collect::<Vec<_>>();
  288. let mut questions = self.game.players.iter()
  289. .map(|p| p.creating_exercise.clone().unwrap().question)
  290. .collect::<Vec<_>>();
  291. questions.append(&mut self.game.additional_questions.iter()
  292. .map(|x| x.question.clone())
  293. .collect::<Vec<_>>()
  294. );
  295. questions.shuffle(&mut thread_rng());
  296. GameStateData::Guessing {
  297. submitted_words: words_with_chars,
  298. questions: questions
  299. }
  300. }
  301. }
  302. ///
  303. /// connection to one single client
  304. ///
  305. pub struct GameConnection {
  306. heartbeat: Instant,
  307. nick: Option<String>,
  308. game_id: Option<String>,
  309. server: Addr<Server>,
  310. game_lobby: Option<Addr<GameLobby>>
  311. }
  312. impl Actor for GameConnection {
  313. type Context = ws::WebsocketContext<Self>;
  314. fn started(&mut self, ctx: &mut Self::Context) {
  315. self.initiate_heartbeat(ctx);
  316. }
  317. }
  318. impl Handler<LobbyJoined> for GameConnection {
  319. type Result = ();
  320. fn handle(&mut self, gu: LobbyJoined, ctx: &mut Self::Context) -> Self::Result {
  321. self.game_lobby = Some(gu.0);
  322. }
  323. }
  324. impl Handler<NoSuchLobby> for GameConnection {
  325. type Result = ();
  326. fn handle(&mut self, nsl: NoSuchLobby, ctx: &mut Self::Context) -> Self::Result {
  327. self.send_message(&UpdateMessage::GameNotFound{ game_id: nsl.0 }, ctx);
  328. }
  329. }
  330. impl Handler<GameUpdate> for GameConnection {
  331. type Result = ();
  332. fn handle(&mut self, gu: GameUpdate, ctx: &mut Self::Context) -> Self::Result {
  333. self.send_message(&UpdateMessage::GameState(gu.game_data), ctx);
  334. }
  335. }
  336. impl Handler<ResultMsg> for GameConnection {
  337. type Result = ();
  338. fn handle(&mut self, rm: ResultMsg, ctx: &mut Self::Context) -> Self::Result {
  339. self.send_message(&UpdateMessage::RoundResult(rm.results), ctx);
  340. }
  341. }
  342. impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for GameConnection {
  343. fn handle(
  344. &mut self,
  345. msg: Result<ws::Message, ws::ProtocolError>,
  346. ctx: &mut Self::Context,
  347. ) {
  348. match msg {
  349. Ok(ws::Message::Ping(msg)) => {
  350. self.heartbeat = Instant::now();
  351. ctx.pong(&msg);
  352. }
  353. Ok(ws::Message::Pong(_)) => {
  354. self.heartbeat = Instant::now();
  355. }
  356. Ok(ws::Message::Text(text)) => {
  357. println!("hmmm: {:?}", text);
  358. self.received_message(&text, ctx);
  359. },
  360. Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
  361. Ok(ws::Message::Close(reason)) => {
  362. ctx.close(reason);
  363. ctx.stop();
  364. }
  365. _ => ctx.stop(),
  366. }
  367. }
  368. }
  369. impl GameConnection {
  370. pub fn new(server_addr: Addr<Server>) -> Self {
  371. GameConnection {
  372. heartbeat: Instant::now(),
  373. nick: None,
  374. game_id: None,
  375. server: server_addr,
  376. game_lobby: None
  377. }
  378. }
  379. pub fn initiate_heartbeat(&self, ctx: &mut <Self as Actor>::Context) {
  380. ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| {
  381. if Instant::now().duration_since(act.heartbeat) > CLIENT_TIMEOUT {
  382. //println!("Websocket Client heartbeat failed, disconnecting!");
  383. ctx.stop();
  384. return;
  385. }
  386. ctx.ping(b"");
  387. });
  388. }
  389. pub fn send_message(&self, m: &UpdateMessage, ctx: &mut <Self as Actor>::Context) {
  390. let txt = serde_json::to_string(m).unwrap();
  391. println!("{:?}", txt);
  392. ctx.text(txt);
  393. }
  394. pub fn received_message(&mut self, text: &str, ctx: &mut <Self as Actor>::Context) {
  395. let parsed: Result<ClientMessage, _> = serde_json::from_str(text);
  396. if let Ok(msg) = parsed {
  397. match msg {
  398. ClientMessage::CreateGame{game_id, nick} => {
  399. self.game_id = Some(game_id.clone());
  400. self.nick = Some(nick);
  401. self.server.do_send(CreateLobbyRequest{ lobby_id: game_id.clone(), p: ctx.address() });
  402. },
  403. ClientMessage::Join{game_id, nick} => {
  404. self.server.do_send(JoinRequest{ lobby_id: game_id.clone(), nick: nick.clone(), p: ctx.address() });
  405. self.game_id = Some(game_id.clone());
  406. self.nick = Some(nick);
  407. },
  408. ClientMessage::Ready => {
  409. if let Some(lobby) = &self.game_lobby {
  410. if let Some(nick) = &self.nick {
  411. lobby.do_send(ReadyMsg(nick.clone()));
  412. }
  413. }
  414. },
  415. ClientMessage::SubmitWord{ word } => {
  416. if let Some(lobby) = &self.game_lobby {
  417. if let Some(nick) = &self.nick {
  418. lobby.do_send(SubmitWordMsg{ word: word, nick: nick.clone() });
  419. }
  420. }
  421. },
  422. ClientMessage::SubmitGuess{ guesses } => {
  423. if let Some(lobby) = &self.game_lobby {
  424. if let Some(nick) = &self.nick {
  425. lobby.do_send(SubmitGuessMsg{ guesses: guesses, nick: nick.clone() });
  426. }
  427. }
  428. }
  429. }
  430. }
  431. else {
  432. println!("error parsing json");
  433. }
  434. }
  435. }