Send more data on room joining
authoralfadur
Wed, 27 Jun 2018 23:26:29 +0300
changeset 13427 6f6a866c86a2
parent 13426 f091f69d59e4
child 13428 c8425fbcf1d9
Send more data on room joining
gameServer2/src/server/actions.rs
gameServer2/src/server/handlers/inroom.rs
gameServer2/src/server/handlers/lobby.rs
gameServer2/src/server/room.rs
--- a/gameServer2/src/server/actions.rs	Wed Jun 27 17:58:33 2018 +0300
+++ b/gameServer2/src/server/actions.rs	Wed Jun 27 23:26:29 2018 +0300
@@ -222,14 +222,56 @@
                     c.is_ready = false;
                     c.is_master = false;
                 }
-                let flags_msg = ClientFlags("+i".to_string(), vec![c.nick.clone()]);
 
                 let mut v = vec![
                     RoomJoined(vec![c.nick.clone()]).send_all().in_room(room_id).action(),
-                    flags_msg.send_all().action(),
+                    ClientFlags("+i".to_string(), vec![c.nick.clone()]).send_all().action(),
                     SendRoomUpdate(None)];
                 if !c.is_master {
+                    let team_names: Vec<_>;
+                    if let Some(ref mut info) = r.game_info {
+                        c.is_in_game = true;
+                        c.is_joined_mid_game = true;
+
+                        {
+                            let teams = info.client_teams(c.id);
+                            c.teams_in_game = teams.clone().count() as u8;
+                            c.clan = teams.clone().next().map(|t| t.color);
+                            team_names = teams.map(|t| t.name.clone()).collect();
+                        }
+
+                        if !team_names.is_empty() {
+                            info.left_teams.retain(|name|
+                                !team_names.contains(&name));
+                            info.teams_in_game += team_names.len() as u8;
+                            r.teams = info.teams_at_start.iter()
+                                .filter(|(_, t)| !team_names.contains(&t.name))
+                                .cloned().collect();
+                        }
+                    } else {
+                        team_names = Vec::new();
+                    }
+
                     v.push(SendRoomData{ to: client_id, teams: true, config: true, flags: true});
+
+                    if let Some(ref info) = r.game_info {
+                        v.push(RunGame.send_self().action());
+                        v.push(ClientFlags("+g".to_string(), vec![c.nick.clone()])
+                            .send_all().in_room(r.id).action());
+                        v.push(ForwardEngineMessage(
+                            to_engine_msg("e$spectate 1".bytes()) + &info.msg_log)
+                            .send_self().action());
+
+                        for name in team_names.iter() {
+                            v.push(ForwardEngineMessage(
+                                to_engine_msg(once(b'G').chain(name.bytes())))
+                                .send_all().in_room(r.id).action());
+                        }
+                        if info.is_paused {
+                            v.push(ForwardEngineMessage(to_engine_msg(once(b'I')))
+                                .send_all().in_room(r.id).action())
+                        }
+                    }
                 }
                 v
             };
@@ -247,9 +289,17 @@
                     }
                 }
                 if teams {
-                    for (owner_id, team) in r.teams.iter() {
+                    let current_teams = match r.game_info {
+                        Some(ref info) => &info.teams_at_start,
+                        None => &r.teams
+                    };
+                    for (owner_id, team) in current_teams.iter() {
                         actions.push(TeamAdd(HWRoom::team_info(&server.clients[*owner_id], &team))
                             .send(to).action());
+                        actions.push(TeamColor(team.name.clone(), team.color)
+                            .send(to).action());
+                        actions.push(HedgehogsNumber(team.name.clone(), team.hedgehogs_number)
+                            .send(to).action());
                     }
                 }
                 if flags {
@@ -368,7 +418,7 @@
                 } else if room.game_info.is_some() {
                     vec![Warn("The game is already in progress".to_string())]
                 } else {
-                    room.game_info = Some(GameInfo::new(room.teams.len() as u8));
+                    room.start_round();
                     for id in room_clients {
                         let c = &mut server.clients[id];
                         c.is_in_game = true;
@@ -393,6 +443,13 @@
                     if info.teams_in_game == 0 {
                         actions.push(FinishRoomGame(r.id));
                     }
+                    let remove_msg = to_engine_msg(once(b'F').chain(team_name.bytes()));
+                    match &info.last_msg {
+                        Some(m) => info.msg_log.push_str(&m),
+                        None => info.msg_log.push_str(&remove_msg)
+                    }
+                    actions.push(ForwardEngineMessage(remove_msg)
+                        .send_all().in_room(r.id).but_self().action());
                 }
             }
             server.react(client_id, actions);
--- a/gameServer2/src/server/handlers/inroom.rs	Wed Jun 27 17:58:33 2018 +0300
+++ b/gameServer2/src/server/handlers/inroom.rs	Wed Jun 27 23:26:29 2018 +0300
@@ -239,18 +239,25 @@
                     let decoding = decode(&em[..]).unwrap();
                     let messages = by_msg(&decoding);
                     let valid = messages.clone().filter(|m| is_msg_valid(m, &c.team_indices));
-                    let _non_empty = messages.filter(|m| !is_msg_empty(m));
-                    let _last_valid_timed_msg = valid.clone().scan(None, |res, msg| match msg {
+                    let non_empty = messages.filter(|m| !is_msg_empty(m));
+                    let last_msg = valid.clone().scan(None, |res, msg| match msg {
                         [_, b'+', ..] => Some(msg),
                         [_, typ, ..] if NON_TIMED_MESSAGES.contains(typ) => *res,
                         _ => None
-                    }).next();
+                    }).next().map(|s| encode(s));
 
                     let em_response = encode(&valid.flat_map(|msg| msg).cloned().collect::<Vec<_>>());
                     if !em_response.is_empty() {
                         actions.push(ForwardEngineMessage(em_response)
                             .send_all().in_room(r.id).but_self().action());
                     }
+                    let em_log = encode(&non_empty.flat_map(|msg| msg).cloned().collect::<Vec<_>>());
+                    if let Some(ref mut info) = r.game_info {
+                        info.msg_log.push_str(&em_log);
+                        if last_msg.is_some() {
+                            info.last_msg = last_msg;
+                        }
+                    }
                 }
             }
             server.react(client_id, actions)
--- a/gameServer2/src/server/handlers/lobby.rs	Wed Jun 27 17:58:33 2018 +0300
+++ b/gameServer2/src/server/handlers/lobby.rs	Wed Jun 27 23:26:29 2018 +0300
@@ -43,16 +43,16 @@
                     .map(|(_, c)| c.nick.clone())
                     .collect();
                 let c = &mut server.clients[client_id];
-                actions = match room {
-                    None => vec![Warn("No such room.".to_string())],
-                    Some((_, r)) => {
-                        if c.protocol_number != r.protocol_number {
-                            vec![Warn("Room version incompatible to your Hedgewars version!".to_string())]
-                        } else {
-                            vec![MoveToRoom(r.id),
-                                 RoomJoined(nicks).send_self().action()]
-                        }
+
+                actions = if let Some((_, r)) = room {
+                    if c.protocol_number != r.protocol_number {
+                        vec![Warn("Room version incompatible to your Hedgewars version!".to_string())]
+                    } else {
+                        vec![MoveToRoom(r.id),
+                             RoomJoined(nicks).send_self().action()]
                     }
+                } else {
+                    vec![Warn("No such room.".to_string())]
                 };
             }
             server.react(client_id, actions);
--- a/gameServer2/src/server/room.rs	Wed Jun 27 17:58:33 2018 +0300
+++ b/gameServer2/src/server/room.rs	Wed Jun 27 23:26:29 2018 +0300
@@ -7,16 +7,19 @@
 const MAX_HEDGEHOGS_IN_ROOM: u8 = 48;
 pub type RoomId = usize;
 
+#[derive(Clone)]
 struct Ammo {
     name: String,
     settings: Option<String>
 }
 
+#[derive(Clone)]
 struct Scheme {
     name: String,
     settings: Option<Vec<String>>
 }
 
+#[derive(Clone)]
 struct RoomConfig {
     feature_size: u32,
     map_type: String,
@@ -51,18 +54,57 @@
     }
 }
 
+fn client_teams_impl(teams: &Vec<(ClientId, TeamInfo)>, client_id: ClientId)
+    -> impl Iterator<Item = &TeamInfo> + Clone
+{
+    teams.iter().filter(move |(id, _)| *id == client_id).map(|(_, t)| t)
+}
+
+fn map_config_from(c: &RoomConfig) -> Vec<String> {
+    vec![c.feature_size.to_string(), c.map_type.to_string(),
+         c.map_generator.to_string(), c.maze_size.to_string(),
+         c.seed.to_string(), c.template.to_string()]
+}
+
+fn game_config_from(c: &RoomConfig) -> Vec<GameCfg> {
+    use server::coretypes::GameCfg::*;
+    let mut v = vec![
+        Ammo(c.ammo.name.to_string(), c.ammo.settings.clone()),
+        Scheme(c.scheme.name.to_string(), c.scheme.settings.clone()),
+        Script(c.script.to_string()),
+        Theme(c.theme.to_string())];
+    if let Some(ref m) = c.drawn_map {
+        v.push(DrawnMap(m.to_string()))
+    }
+    v
+}
+
 pub struct GameInfo {
     pub teams_in_game: u8,
-    pub left_teams: Vec<String>
+    pub teams_at_start: Vec<(ClientId, TeamInfo)>,
+    pub left_teams: Vec<String>,
+    pub msg_log: String,
+    pub last_msg: Option<String>,
+    pub is_paused: bool,
+    config: RoomConfig
 }
 
 impl GameInfo {
-    pub fn new(teams_number: u8) -> GameInfo {
+    fn new(teams: Vec<(ClientId, TeamInfo)>, config: RoomConfig) -> GameInfo {
         GameInfo {
-            teams_in_game: teams_number,
-            left_teams: Vec::new()
+            left_teams: Vec::new(),
+            msg_log: String::new(),
+            last_msg: None,
+            is_paused: false,
+            teams_in_game: teams.len() as u8,
+            teams_at_start: teams,
+            config
         }
     }
+
+    pub fn client_teams(&self, client_id: ClientId) -> impl Iterator<Item = &TeamInfo> + Clone {
+        client_teams_impl(&self.teams_at_start, client_id)
+    }
 }
 
 pub struct HWRoom {
@@ -138,7 +180,7 @@
     }
 
     pub fn client_teams(&self, client_id: ClientId) -> impl Iterator<Item = &TeamInfo> {
-        self.teams.iter().filter(move |(id, _)| *id == client_id).map(|(_, t)| t)
+        client_teams_impl(&self.teams, client_id)
     }
 
     pub fn client_team_indices(&self, client_id: ClientId) -> Vec<u8> {
@@ -179,6 +221,13 @@
         };
     }
 
+    pub fn start_round(&mut self) {
+        if self.game_info.is_none() {
+            self.game_info = Some(GameInfo::new(
+                self.teams.clone(), self.config.clone()));
+        }
+    }
+
     pub fn info(&self, master: Option<&HWClient>) -> Vec<String> {
         let flags = "-".to_string();
         let c = &self.config;
@@ -196,24 +245,17 @@
     }
 
     pub fn map_config(&self) -> Vec<String> {
-        let c = &self.config;
-        vec![c.feature_size.to_string(), c.map_type.to_string(),
-             c.map_generator.to_string(), c.maze_size.to_string(),
-             c.seed.to_string(), c.template.to_string()]
+        match self.game_info {
+            Some(ref info) => map_config_from(&info.config),
+            None => map_config_from(&self.config)
+        }
     }
 
     pub fn game_config(&self) -> Vec<GameCfg> {
-        use server::coretypes::GameCfg::*;
-        let c = &self.config;
-        let mut v = vec![
-            Ammo(c.ammo.name.to_string(), c.ammo.settings.clone()),
-            Scheme(c.scheme.name.to_string(), c.scheme.settings.clone()),
-            Script(c.script.to_string()),
-            Theme(c.theme.to_string())];
-        if let Some(ref m) = c.drawn_map {
-            v.push(DrawnMap(m.to_string()))
+        match self.game_info {
+            Some(ref info) => game_config_from(&info.config),
+            None => game_config_from(&self.config)
         }
-        v
     }
 
     pub fn team_info(owner: &HWClient, team: &TeamInfo) -> Vec<String> {