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 } |