29 pub destination: Destination, |
31 pub destination: Destination, |
30 pub message: HWServerMessage |
32 pub message: HWServerMessage |
31 } |
33 } |
32 |
34 |
33 impl PendingMessage { |
35 impl PendingMessage { |
|
36 pub fn send(message: HWServerMessage, client_id: ClientId) -> PendingMessage { |
|
37 PendingMessage{ destination: Destination::ToId(client_id), message} |
|
38 } |
|
39 |
34 pub fn send_self(message: HWServerMessage) -> PendingMessage { |
40 pub fn send_self(message: HWServerMessage) -> PendingMessage { |
35 PendingMessage{ destination: Destination::ToSelf, message } |
41 PendingMessage{ destination: Destination::ToSelf, message } |
36 } |
42 } |
37 |
43 |
38 pub fn send_all(message: HWServerMessage) -> PendingMessage { |
44 pub fn send_all(message: HWServerMessage) -> PendingMessage { |
71 impl Into<Action> for PendingMessage { |
77 impl Into<Action> for PendingMessage { |
72 fn into(self) -> Action { self.action() } |
78 fn into(self) -> Action { self.action() } |
73 } |
79 } |
74 |
80 |
75 impl HWServerMessage { |
81 impl HWServerMessage { |
|
82 pub fn send(self, client_id: ClientId) -> PendingMessage { PendingMessage::send(self, client_id) } |
76 pub fn send_self(self) -> PendingMessage { PendingMessage::send_self(self) } |
83 pub fn send_self(self) -> PendingMessage { PendingMessage::send_self(self) } |
77 pub fn send_all(self) -> PendingMessage { PendingMessage::send_all(self) } |
84 pub fn send_all(self) -> PendingMessage { PendingMessage::send_all(self) } |
78 } |
85 } |
79 |
86 |
80 pub enum Action { |
87 pub enum Action { |
93 RemoveClientTeams, |
100 RemoveClientTeams, |
94 SendRoomUpdate(Option<String>), |
101 SendRoomUpdate(Option<String>), |
95 StartRoomGame(RoomId), |
102 StartRoomGame(RoomId), |
96 SendTeamRemovalMessage(String), |
103 SendTeamRemovalMessage(String), |
97 FinishRoomGame(RoomId), |
104 FinishRoomGame(RoomId), |
98 SendRoomData{teams: bool, config: bool, flags: bool}, |
105 SendRoomData{to: ClientId, teams: bool, config: bool, flags: bool}, |
99 Warn(String), |
106 Warn(String), |
100 ProtocolError(String) |
107 ProtocolError(String) |
101 } |
108 } |
102 |
109 |
103 use self::Action::*; |
110 use self::Action::*; |
220 let mut v = vec![ |
227 let mut v = vec![ |
221 RoomJoined(vec![c.nick.clone()]).send_all().in_room(room_id).action(), |
228 RoomJoined(vec![c.nick.clone()]).send_all().in_room(room_id).action(), |
222 flags_msg.send_all().action(), |
229 flags_msg.send_all().action(), |
223 SendRoomUpdate(None)]; |
230 SendRoomUpdate(None)]; |
224 if !c.is_master { |
231 if !c.is_master { |
225 v.push(SendRoomData{ teams: true, config: true, flags: true}); |
232 v.push(SendRoomData{ to: client_id, teams: true, config: true, flags: true}); |
226 } |
233 } |
227 v |
234 v |
228 }; |
235 }; |
229 server.react(client_id, actions); |
236 server.react(client_id, actions); |
230 } |
237 } |
231 SendRoomData {teams, config, flags} => { |
238 SendRoomData {to, teams, config, flags} => { |
232 let mut actions = Vec::new(); |
239 let mut actions = Vec::new(); |
233 let room_id = server.clients[client_id].room_id; |
240 let room_id = server.clients[client_id].room_id; |
234 if let Some(r) = room_id.and_then(|id| server.rooms.get(id)) { |
241 if let Some(r) = room_id.and_then(|id| server.rooms.get(id)) { |
235 if config { |
242 if config { |
236 actions.push(ConfigEntry("FULLMAPCONFIG".to_string(), r.map_config()) |
243 actions.push(ConfigEntry("FULLMAPCONFIG".to_string(), r.map_config()) |
237 .send_self().action()); |
244 .send(to).action()); |
238 for cfg in r.game_config().into_iter() { |
245 for cfg in r.game_config().into_iter() { |
239 actions.push(cfg.into_server_msg().send_self().action()); |
246 actions.push(cfg.into_server_msg().send(to).action()); |
240 } |
247 } |
241 } |
248 } |
242 if teams { |
249 if teams { |
243 for (owner_id, team) in r.teams.iter() { |
250 for (owner_id, team) in r.teams.iter() { |
244 actions.push(TeamAdd(HWRoom::team_info(&server.clients[*owner_id], &team)) |
251 actions.push(TeamAdd(HWRoom::team_info(&server.clients[*owner_id], &team)) |
245 .send_self().action()); |
252 .send(to).action()); |
246 } |
253 } |
247 } |
254 } |
248 if flags { |
255 if flags { |
249 if let Some(id) = r.master_id { |
256 if let Some(id) = r.master_id { |
250 actions.push(ClientFlags("+h".to_string(), vec![server.clients[id].nick.clone()]) |
257 actions.push(ClientFlags("+h".to_string(), vec![server.clients[id].nick.clone()]) |
251 .send_self().action()); |
258 .send(to).action()); |
252 } |
259 } |
253 let nicks: Vec<_> = server.clients.iter() |
260 let nicks: Vec<_> = server.clients.iter() |
254 .filter(|(_, c)| c.room_id == Some(r.id) && c.is_ready) |
261 .filter(|(_, c)| c.room_id == Some(r.id) && c.is_ready) |
255 .map(|(_, c)| c.nick.clone()).collect(); |
262 .map(|(_, c)| c.nick.clone()).collect(); |
256 if !nicks.is_empty() { |
263 if !nicks.is_empty() { |
257 actions.push(ClientFlags("+r".to_string(), nicks) |
264 actions.push(ClientFlags("+r".to_string(), nicks) |
258 .send_self().action()); |
265 .send(to).action()); |
259 } |
266 } |
260 } |
267 } |
261 } |
268 } |
262 server.react(client_id, actions); |
269 server.react(client_id, actions); |
263 } |
270 } |
316 } |
323 } |
317 new_id.map(|id| server.clients[id].is_master = true); |
324 new_id.map(|id| server.clients[id].is_master = true); |
318 server.react(client_id, actions); |
325 server.react(client_id, actions); |
319 } |
326 } |
320 RemoveTeam(name) => { |
327 RemoveTeam(name) => { |
321 let actions = if let (_, Some(r)) = server.client_and_room(client_id) { |
328 let mut actions = Vec::new(); |
|
329 if let (c, Some(r)) = server.client_and_room(client_id) { |
322 r.remove_team(&name); |
330 r.remove_team(&name); |
323 vec![TeamRemove(name).send_all().in_room(r.id).action(), |
331 if let Some(ref mut info) = r.game_info { |
324 SendRoomUpdate(None)] |
332 info.left_teams.push(name.clone()); |
325 } else { |
333 } |
326 Vec::new() |
334 actions.push(TeamRemove(name.clone()).send_all().in_room(r.id).action()); |
327 }; |
335 actions.push(SendRoomUpdate(None)); |
|
336 if r.game_info.is_some() && c.is_in_game { |
|
337 actions.push(SendTeamRemovalMessage(name)); |
|
338 } |
|
339 } |
328 server.react(client_id, actions); |
340 server.react(client_id, actions); |
329 }, |
341 }, |
330 RemoveClientTeams => { |
342 RemoveClientTeams => { |
331 let actions = if let (c, Some(r)) = server.client_and_room(client_id) { |
343 let actions = if let (c, Some(r)) = server.client_and_room(client_id) { |
332 r.client_teams(c.id).map(|t| RemoveTeam(t.name.clone())).collect() |
344 r.client_teams(c.id).map(|t| RemoveTeam(t.name.clone())).collect() |
354 if !room.has_multiple_clans() { |
366 if !room.has_multiple_clans() { |
355 vec![Warn("The game can't be started with less than two clans!".to_string())] |
367 vec![Warn("The game can't be started with less than two clans!".to_string())] |
356 } else if room.game_info.is_some() { |
368 } else if room.game_info.is_some() { |
357 vec![Warn("The game is already in progress".to_string())] |
369 vec![Warn("The game is already in progress".to_string())] |
358 } else { |
370 } else { |
359 room.game_info = Some(GameInfo { |
371 room.game_info = Some(GameInfo::new(room.teams.len() as u8)); |
360 teams_in_game: room.teams.len() as u8 |
|
361 }); |
|
362 for id in room_clients { |
372 for id in room_clients { |
363 let c = &mut server.clients[id]; |
373 let c = &mut server.clients[id]; |
364 c.is_in_game = true; |
374 c.is_in_game = true; |
365 c.team_indices = room.client_team_indices(c.id); |
375 c.team_indices = room.client_team_indices(c.id); |
366 } |
376 } |
386 } |
396 } |
387 } |
397 } |
388 server.react(client_id, actions); |
398 server.react(client_id, actions); |
389 } |
399 } |
390 FinishRoomGame(room_id) => { |
400 FinishRoomGame(room_id) => { |
391 let actions = { |
401 let mut actions = Vec::new(); |
|
402 let mut old_info = None; |
|
403 { |
392 let r = &mut server.rooms[room_id]; |
404 let r = &mut server.rooms[room_id]; |
|
405 swap(&mut old_info, &mut r.game_info); |
393 r.game_info = None; |
406 r.game_info = None; |
394 r.ready_players_number = 0; |
407 r.ready_players_number = 1; |
395 vec![SendRoomUpdate(None), |
408 actions.push(SendRoomUpdate(None)); |
396 RoundFinished.send_all().in_room(r.id).action()] |
409 actions.push(RoundFinished.send_all().in_room(r.id).action()); |
397 }; |
410 } |
|
411 |
|
412 if let Some(info) = old_info { |
|
413 for (_, c) in server.clients.iter() { |
|
414 if c.room_id == Some(room_id) && c.is_joined_mid_game { |
|
415 actions.push(SendRoomData{ |
|
416 to: c.id, teams: false, |
|
417 config: true, flags: false}); |
|
418 for name in info.left_teams.iter() { |
|
419 actions.push(TeamRemove(name.clone()) |
|
420 .send(c.id).action()); |
|
421 } |
|
422 } |
|
423 } |
|
424 } |
|
425 |
|
426 let nicks: Vec<_> = server.clients.iter_mut() |
|
427 .filter(|(_, c)| c.room_id == Some(room_id)) |
|
428 .map(|(_, c)| { |
|
429 c.is_ready = c.is_master; |
|
430 c.is_joined_mid_game = false; |
|
431 c |
|
432 }).filter_map(|c| if !c.is_master { |
|
433 Some(c.nick.clone()) |
|
434 } else { |
|
435 None |
|
436 }).collect(); |
|
437 if !nicks.is_empty() { |
|
438 actions.push(ClientFlags("-r".to_string(), nicks) |
|
439 .send_all().in_room(room_id).action()); |
|
440 } |
398 server.react(client_id, actions); |
441 server.react(client_id, actions); |
399 } |
442 } |
400 Warn(msg) => { |
443 Warn(msg) => { |
401 run_action(server, client_id, Warning(msg).send_self().action()); |
444 run_action(server, client_id, Warning(msg).send_self().action()); |
402 } |
445 } |