gameServer2/src/server/handlers/inroom.rs
changeset 13428 87a6cad20c90
parent 13427 5fb27f94fc3b
child 13429 d8354cb98b98
--- a/gameServer2/src/server/handlers/inroom.rs	Tue Jun 26 23:22:38 2018 +0300
+++ b/gameServer2/src/server/handlers/inroom.rs	Wed Jun 27 02:34:46 2018 +0300
@@ -12,6 +12,53 @@
 };
 use utils::is_name_illegal;
 use std::mem::swap;
+use base64::{encode, decode};
+
+#[derive(Clone)]
+struct ByMsg<'a> {
+    messages: &'a[u8]
+}
+
+impl <'a> Iterator for ByMsg<'a> {
+    type Item = &'a[u8];
+
+    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
+        if let Some(size) = self.messages.get(0) {
+            let (msg, next) = self.messages.split_at(*size as usize + 1);
+            self.messages = next;
+            Some(msg)
+        } else {
+            None
+        }
+    }
+}
+
+fn by_msg(source: &Vec<u8>) -> ByMsg {
+    ByMsg {messages: &source[..]}
+}
+
+const VALID_MESSAGES: &[u8] =
+    b"M#+LlRrUuDdZzAaSjJ,NpPwtgfhbc12345\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A";
+const NON_TIMED_MESSAGES: &[u8] = b"M#hb";
+
+fn is_msg_valid(msg: &[u8], team_indices: &[u8]) -> bool {
+    if let [size, typ, body..] = msg {
+        VALID_MESSAGES.contains(typ) &&
+            match body {
+                [1...8, team, ..] if *typ == b'h' => team_indices.contains(team),
+                _ => *typ != b'h'
+            }
+    } else {
+        false
+    }
+}
+
+fn is_msg_empty(msg: &[u8]) -> bool {
+    match msg {
+        [_, b'+', ..] => true,
+        _ => false
+    }
+}
 
 pub fn handle(server: &mut HWServer, client_id: ClientId, message: HWProtocolMessage) {
     use protocol::messages::HWProtocolMessage::*;
@@ -76,7 +123,7 @@
                     actions.push(Warn("Too many hedgehogs!".to_string()))
                 } else if r.find_team(|t| t.name == info.name) != None {
                     actions.push(Warn("There's already a team with same name in the list.".to_string()))
-                } else if r.game_info != None {
+                } else if r.game_info.is_some() {
                     actions.push(Warn("Joining not possible: Round is in progress.".to_string()))
                 } else {
                     let team = r.add_team(c.id, info);
@@ -178,6 +225,51 @@
             };
             server.react(client_id, actions);
         }
+        StartGame => {
+            let actions = if let (_, Some(r)) = server.client_and_room(client_id) {
+                vec![StartRoomGame(r.id)]
+            } else {
+                Vec::new()
+            };
+            server.react(client_id, actions);
+        }
+        EngineMessage(em) => {
+            let mut actions = Vec::new();
+            if let (c, Some(r)) = server.client_and_room(client_id) {
+                if c.teams_in_game > 0 {
+                    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 {
+                        [_, b'+', ..] => Some(msg),
+                        [_, typ, ..] if NON_TIMED_MESSAGES.contains(typ) => *res,
+                        _ => None
+                    }).next();
+
+                    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());
+                    }
+                }
+            }
+            server.react(client_id, actions)
+        }
+        RoundFinished => {
+            let mut actions = Vec::new();
+            if let (c, Some(r)) = server.client_and_room(client_id) {
+                if c.is_in_game {
+                    c.is_in_game = false;
+                    actions.push(ClientFlags("-g".to_string(), vec![c.nick.clone()]).
+                        send_all().in_room(r.id).action());
+                    for team in r.client_teams(c.id) {
+                        actions.push(SendTeamRemovalMessage(team.name.clone()));
+                    }
+                }
+            }
+            server.react(client_id, actions)
+        }
         _ => warn!("Unimplemented!")
     }
 }