diff -r 5fb27f94fc3b -r 87a6cad20c90 gameServer2/src/server/handlers/inroom.rs --- 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<::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) -> 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::>()); + 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!") } }