浏览代码

improving

Nicolas Winkler 4 年之前
父节点
当前提交
3cca2dd07f
共有 4 个文件被更改,包括 73 次插入36 次删除
  1. 7 11
      src/game.rs
  2. 50 23
      src/server.rs
  3. 15 1
      src/websocket.rs
  4. 1 1
      static/index.html

+ 7 - 11
src/game.rs

@@ -23,23 +23,19 @@ pub struct Round {
 
 #[derive(Serialize, Clone)]
 pub struct Player {
-    nick: String,
-
-    #[serde(skip_serializing)]
-    actor: Addr<server::GameConnection>,
-
+    pub nick: String,
     submitted_word: Option<String>,
 }
 
 #[derive(Serialize, Clone)]
 pub struct Game {
-    players: Vec<Player>,
-    round_number: i32,
+    pub players: Vec<Player>,
+    pub round_number: i32,
 
     #[serde(skip_serializing)]
-    round: Round,
+    pub round: Round,
 
-    state: GameState,
+    pub state: GameState,
 }
 
 
@@ -88,8 +84,8 @@ impl Game {
         }
     }
 
-    pub fn player_join(&mut self, nick: &str, actor: Addr<server::GameConnection>) {
-        self.players.push(Player{ nick: nick.to_owned(), actor, submitted_word: None });
+    pub fn player_join(&mut self, nick: String) {
+        self.players.push(Player{ nick: nick, submitted_word: None });
     }
 }
 

+ 50 - 23
src/server.rs

@@ -6,16 +6,15 @@ use actix::dev::{MessageResponse, ResponseChannel};
 use actix::prelude::*;
 use actix_web::{web, Error, HttpRequest, HttpResponse};
 use actix_web_actors::ws;
-use futures::executor::block_on;
 use crate::game;
-use crate::websocket::{ClientMessage, UpdateMessage};
+use crate::websocket::*;
 
 const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
 const CLIENT_TIMEOUT: Duration = Duration::from_secs(10);
 
 #[derive(Message)]
 #[rtype(result = "Answer")]
-struct JoinRequest{ lobby_id: String, p: Addr<GameConnection> }
+struct JoinRequest{ lobby_id: String, nick: String, p: Addr<GameConnection> }
 
 
 #[derive(Message)]
@@ -23,9 +22,13 @@ struct JoinRequest{ lobby_id: String, p: Addr<GameConnection> }
 struct CreateLobbyRequest{ lobby_id: String, p: Addr<GameConnection> }
 
 #[derive(Message)]
-#[rtype(result = "game::Game")]
+#[rtype(result = "Result<game::Game, ()>")]
 struct GetGame;
 
+#[derive(Message)]
+#[rtype(result = "()")]
+struct GameUpdate{ game_data: GameData }
+
 enum Answer {
     LobbyJoined(Addr<GameLobby>),
     LobbyCreated(Addr<GameLobby>),
@@ -75,7 +78,7 @@ impl Handler<JoinRequest> for Server {
         let mb_lobby = self.lobbies.get(&jr.lobby_id);
         match mb_lobby {
             Some(lobby) => {
-                let _sent = lobby.send(jr);
+                let _sent = lobby.do_send(jr);
                 Answer::LobbyJoined(lobby.clone())
             },
             None => Answer::NoSuchLobby
@@ -92,7 +95,7 @@ impl Handler<CreateLobbyRequest> for Server {
             None => {
                 let lobby = GameLobby::new(clr.lobby_id.clone());
                 let lobby_addr = lobby.start();
-                self.lobbies.insert(clr.lobby_id, lobby_addr.clone());
+                self.lobbies.insert(clr.lobby_id.clone(), lobby_addr.clone());
                 Answer::LobbyCreated(lobby_addr)
             }
         }
@@ -100,7 +103,7 @@ impl Handler<CreateLobbyRequest> for Server {
 }
 
 pub struct GameLobby {
-    connected_players: Vec<Addr<GameConnection>>,
+    connected_players: BTreeMap<String, Addr<GameConnection>>,
     game_id: String,
     game: game::Game,
 }
@@ -114,26 +117,43 @@ impl Actor for GameLobby {
 impl Handler<JoinRequest> for GameLobby {
     type Result = Answer;
     fn handle(&mut self, jr: JoinRequest, ctx: &mut Self::Context) -> Self::Result {
-        self.connected_players.push(jr.p);
-        Answer::NoSuchLobby
+        self.connected_players.insert(jr.nick.clone(), jr.p);
+        self.game.player_join(jr.nick);
+        self.send_game_to_all();
+
+        Answer::LobbyJoined(ctx.address())
     }
 }
 
 impl Handler<GetGame> for GameLobby {
-    type Result = game::Game;
+    type Result = Result<game::Game, ()>;
     fn handle(&mut self, gg: GetGame, ctx: &mut Self::Context) -> Self::Result {
-        self.game.clone()
+        Ok(self.game.clone())
     }
 }
 
 impl GameLobby {
     pub fn new(gi: String) -> Self {
         GameLobby {
-            connected_players: vec![],
+            connected_players: BTreeMap::new(),
             game_id: gi,
             game: game::Game::new()
         }
     }
+
+    pub fn send_game_to_all(&self) {
+        for (nick, player) in &self.connected_players {
+            let game_state = self.create_opaque_message(nick);
+            player.do_send(GameUpdate{ game_data: game_state });
+        }
+    }
+
+    pub fn create_opaque_message(&self, nick: &str) -> GameData {
+        GameData {
+            players: self.game.players.iter().map(|p| p.nick.clone()).collect::<Vec<_>>(),
+            state_data: GameStateData::Creating{ available_chars: vec!['a', 'b', 'c'] }
+        }
+    }
 }
 
 ///
@@ -155,6 +175,13 @@ impl Actor for GameConnection {
     }
 }
 
+impl Handler<GameUpdate> for GameConnection {
+    type Result = ();
+    fn handle(&mut self, gu: GameUpdate, ctx: &mut Self::Context) -> Self::Result {
+        self.send_message(&UpdateMessage::GameState(gu.game_data), ctx);
+    }
+}
+
 impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for GameConnection {
     fn handle(
         &mut self,
@@ -172,7 +199,7 @@ impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for GameConnection {
             }
             Ok(ws::Message::Text(text)) => {
                 println!("hmmm: {:?}", text);
-                self.handle_message(&text, ctx);
+                self.received_message(&text, ctx);
             },
             Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
             Ok(ws::Message::Close(reason)) => {
@@ -212,7 +239,7 @@ impl GameConnection {
         ctx.text(txt);
     }
 
-    pub fn handle_message(&mut self, text: &str, ctx: &mut <Self as Actor>::Context) {
+    pub fn received_message(&mut self, text: &str, ctx: &mut <Self as Actor>::Context) {
         println!("hm: {:?}", text);
         let parsed: Result<ClientMessage, _> = serde_json::from_str(text);
         if let Ok(msg) = parsed {
@@ -220,36 +247,36 @@ impl GameConnection {
                 ClientMessage::CreateGame{game_id, nick} => {
                     self.game_id = Some(game_id.clone());
                     self.nick = Some(nick);
-                    let lobby_addr = block_on(self.server.send(CreateLobbyRequest{ lobby_id: game_id.clone(), p: ctx.address() }));
-                    match lobby_addr {
+                    let lobby_addr = self.server.do_send(CreateLobbyRequest{ lobby_id: game_id.clone(), p: ctx.address() });
+                    /*match lobby_addr {
                         Ok(Answer::LobbyAlreadyExists) => {
                             self.send_message(&UpdateMessage::GameAlreadyExists{ game_id: game_id.clone() }, ctx);
                         },
                         Ok(Answer::LobbyCreated(lobby_addr)) => {
-                            let gm = block_on(lobby_addr.send(GetGame));
+                            let gm = lobby_addr.do_send(GetGame);
                             self.send_message(&UpdateMessage::GameState(gm.unwrap()), ctx);
                         },
                         _ => {
                             println!("internal error creating lobby");
                         }
-                    }
+                    }*/
                 },
                 ClientMessage::Join{game_id, nick} => {
+                    let lobby_addr = self.server.do_send(JoinRequest{ lobby_id: game_id.clone(), nick: nick.clone(), p: ctx.address() });
                     self.game_id = Some(game_id.clone());
                     self.nick = Some(nick);
-                    let lobby_addr = block_on(self.server.send(JoinRequest{ lobby_id: game_id.clone(), p: ctx.address() }));
-                    match lobby_addr {
+                    /*match lobby_addr {
                         Ok(Answer::NoSuchLobby) => {
                             self.send_message(&UpdateMessage::GameNotFound{ game_id: game_id.clone() }, ctx);
                         },
                         Ok(Answer::LobbyJoined(lobby_addr)) => {
-                            let gm = block_on(lobby_addr.send(GetGame));
-                            self.send_message(&UpdateMessage::GameState(gm.unwrap()), ctx);
+                            //let gm = lobby_addr.send(GetGame));
+                            //self.send_message(&UpdateMessage::GameState(gm.unwrap()), ctx);
                         },
                         _ => {
                             println!("internal error joining lobby");
                         }
-                    }
+                    }*/
                 },
             }
         }

+ 15 - 1
src/websocket.rs

@@ -22,12 +22,26 @@ pub enum ClientMessage {
     Join{ game_id: String, nick: String },
 }
 
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum GameStateData {
+    Creating{ available_chars: Vec<char> },
+    Guessing()
+}
+
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub struct GameData {
+    pub players: Vec<String>,
+    pub state_data: GameStateData
+}
+
 #[derive(Serialize)]
 #[serde(rename_all = "snake_case")]
 pub enum UpdateMessage {
     GameNotFound{ game_id: String },
     GameAlreadyExists{ game_id: String },
-    GameState(game::Game)
+    GameState(GameData)
 }
 
 

+ 1 - 1
static/index.html

@@ -65,7 +65,7 @@
                 else if (obj.game_state != null) {
                     playerlist = "";
                     for (var i = 0; i < obj.game_state.players.length; i++) {
-                        playerlist = playerlist + ", " + obj.game_state.players[i].nick;
+                        playerlist = playerlist + ", " + obj.game_state.players[i];
                     }
                     $('#status').html("Players: " + playerlist);
                 }