gameServer2/src/server/handlers/inroom.rs
changeset 13423 87a6cad20c90
parent 13422 5fb27f94fc3b
child 13424 d8354cb98b98
equal deleted inserted replaced
13422:5fb27f94fc3b 13423:87a6cad20c90
    10     room::HWRoom,
    10     room::HWRoom,
    11     actions::{Action, Action::*}
    11     actions::{Action, Action::*}
    12 };
    12 };
    13 use utils::is_name_illegal;
    13 use utils::is_name_illegal;
    14 use std::mem::swap;
    14 use std::mem::swap;
       
    15 use base64::{encode, decode};
       
    16 
       
    17 #[derive(Clone)]
       
    18 struct ByMsg<'a> {
       
    19     messages: &'a[u8]
       
    20 }
       
    21 
       
    22 impl <'a> Iterator for ByMsg<'a> {
       
    23     type Item = &'a[u8];
       
    24 
       
    25     fn next(&mut self) -> Option<<Self as Iterator>::Item> {
       
    26         if let Some(size) = self.messages.get(0) {
       
    27             let (msg, next) = self.messages.split_at(*size as usize + 1);
       
    28             self.messages = next;
       
    29             Some(msg)
       
    30         } else {
       
    31             None
       
    32         }
       
    33     }
       
    34 }
       
    35 
       
    36 fn by_msg(source: &Vec<u8>) -> ByMsg {
       
    37     ByMsg {messages: &source[..]}
       
    38 }
       
    39 
       
    40 const VALID_MESSAGES: &[u8] =
       
    41     b"M#+LlRrUuDdZzAaSjJ,NpPwtgfhbc12345\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A";
       
    42 const NON_TIMED_MESSAGES: &[u8] = b"M#hb";
       
    43 
       
    44 fn is_msg_valid(msg: &[u8], team_indices: &[u8]) -> bool {
       
    45     if let [size, typ, body..] = msg {
       
    46         VALID_MESSAGES.contains(typ) &&
       
    47             match body {
       
    48                 [1...8, team, ..] if *typ == b'h' => team_indices.contains(team),
       
    49                 _ => *typ != b'h'
       
    50             }
       
    51     } else {
       
    52         false
       
    53     }
       
    54 }
       
    55 
       
    56 fn is_msg_empty(msg: &[u8]) -> bool {
       
    57     match msg {
       
    58         [_, b'+', ..] => true,
       
    59         _ => false
       
    60     }
       
    61 }
    15 
    62 
    16 pub fn handle(server: &mut HWServer, client_id: ClientId, message: HWProtocolMessage) {
    63 pub fn handle(server: &mut HWServer, client_id: ClientId, message: HWProtocolMessage) {
    17     use protocol::messages::HWProtocolMessage::*;
    64     use protocol::messages::HWProtocolMessage::*;
    18     match message {
    65     match message {
    19         Part(None) => server.react(client_id, vec![
    66         Part(None) => server.react(client_id, vec![
    74                     actions.push(Warn("Too many teams!".to_string()))
   121                     actions.push(Warn("Too many teams!".to_string()))
    75                 } else if r.addable_hedgehogs() == 0 {
   122                 } else if r.addable_hedgehogs() == 0 {
    76                     actions.push(Warn("Too many hedgehogs!".to_string()))
   123                     actions.push(Warn("Too many hedgehogs!".to_string()))
    77                 } else if r.find_team(|t| t.name == info.name) != None {
   124                 } else if r.find_team(|t| t.name == info.name) != None {
    78                     actions.push(Warn("There's already a team with same name in the list.".to_string()))
   125                     actions.push(Warn("There's already a team with same name in the list.".to_string()))
    79                 } else if r.game_info != None {
   126                 } else if r.game_info.is_some() {
    80                     actions.push(Warn("Joining not possible: Round is in progress.".to_string()))
   127                     actions.push(Warn("Joining not possible: Round is in progress.".to_string()))
    81                 } else {
   128                 } else {
    82                     let team = r.add_team(c.id, info);
   129                     let team = r.add_team(c.id, info);
    83                     c.teams_in_game += 1;
   130                     c.teams_in_game += 1;
    84                     c.clan = Some(team.color);
   131                     c.clan = Some(team.color);
   176             } else {
   223             } else {
   177                 Vec::new()
   224                 Vec::new()
   178             };
   225             };
   179             server.react(client_id, actions);
   226             server.react(client_id, actions);
   180         }
   227         }
       
   228         StartGame => {
       
   229             let actions = if let (_, Some(r)) = server.client_and_room(client_id) {
       
   230                 vec![StartRoomGame(r.id)]
       
   231             } else {
       
   232                 Vec::new()
       
   233             };
       
   234             server.react(client_id, actions);
       
   235         }
       
   236         EngineMessage(em) => {
       
   237             let mut actions = Vec::new();
       
   238             if let (c, Some(r)) = server.client_and_room(client_id) {
       
   239                 if c.teams_in_game > 0 {
       
   240                     let decoding = decode(&em[..]).unwrap();
       
   241                     let messages = by_msg(&decoding);
       
   242                     let valid = messages.clone().filter(|m| is_msg_valid(m, &c.team_indices));
       
   243                     let _non_empty = messages.filter(|m| !is_msg_empty(m));
       
   244                     let _last_valid_timed_msg = valid.clone().scan(None, |res, msg| match msg {
       
   245                         [_, b'+', ..] => Some(msg),
       
   246                         [_, typ, ..] if NON_TIMED_MESSAGES.contains(typ) => *res,
       
   247                         _ => None
       
   248                     }).next();
       
   249 
       
   250                     let em_response = encode(&valid.flat_map(|msg| msg).cloned().collect::<Vec<_>>());
       
   251                     if !em_response.is_empty() {
       
   252                         actions.push(ForwardEngineMessage(em_response)
       
   253                             .send_all().in_room(r.id).but_self().action());
       
   254                     }
       
   255                 }
       
   256             }
       
   257             server.react(client_id, actions)
       
   258         }
       
   259         RoundFinished => {
       
   260             let mut actions = Vec::new();
       
   261             if let (c, Some(r)) = server.client_and_room(client_id) {
       
   262                 if c.is_in_game {
       
   263                     c.is_in_game = false;
       
   264                     actions.push(ClientFlags("-g".to_string(), vec![c.nick.clone()]).
       
   265                         send_all().in_room(r.id).action());
       
   266                     for team in r.client_teams(c.id) {
       
   267                         actions.push(SendTeamRemovalMessage(team.name.clone()));
       
   268                     }
       
   269                 }
       
   270             }
       
   271             server.react(client_id, actions)
       
   272         }
   181         _ => warn!("Unimplemented!")
   273         _ => warn!("Unimplemented!")
   182     }
   274     }
   183 }
   275 }