gameServer2/src/server/actions.rs
changeset 13426 f091f69d59e4
parent 13424 d8354cb98b98
child 13427 6f6a866c86a2
equal deleted inserted replaced
13425:50f852e7ad82 13426:f091f69d59e4
     1 use std::{
     1 use std::{
     2     io, io::Write,
     2     io, io::Write,
     3     iter::once
     3     iter::once,
       
     4     mem::swap
     4 };
     5 };
     5 use super::{
     6 use super::{
     6     server::HWServer,
     7     server::HWServer,
     7     room::{RoomId, GameInfo},
     8     room::{RoomId, GameInfo},
     8     client::{ClientId, HWClient},
     9     client::{ClientId, HWClient},
    15     HWServerMessage::*
    16     HWServerMessage::*
    16 };
    17 };
    17 use utils::to_engine_msg;
    18 use utils::to_engine_msg;
    18 
    19 
    19 pub enum Destination {
    20 pub enum Destination {
       
    21     ToId(ClientId),
    20     ToSelf,
    22     ToSelf,
    21     ToAll {
    23     ToAll {
    22         room_id: Option<RoomId>,
    24         room_id: Option<RoomId>,
    23         protocol: Option<u32>,
    25         protocol: Option<u32>,
    24         skip_self: bool
    26         skip_self: bool
    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         }