rust/hedgewars-server/src/server/handlers/common.rs
changeset 14688 4569d8d50286
parent 14687 5122c584804e
child 14689 aae29ba56aec
equal deleted inserted replaced
14687:5122c584804e 14688:4569d8d50286
     1 use crate::protocol::messages::server_chat;
       
     2 use crate::server::client::HWClient;
       
     3 use crate::server::coretypes::ClientId;
       
     4 use crate::server::coretypes::GameCfg;
       
     5 use crate::server::coretypes::RoomId;
       
     6 use crate::server::coretypes::Vote;
       
     7 use crate::server::coretypes::VoteType;
       
     8 use crate::server::room::HWRoom;
       
     9 use crate::utils::to_engine_msg;
       
    10 use crate::{
     1 use crate::{
       
     2     protocol::messages::server_chat,
    11     protocol::messages::{
     3     protocol::messages::{
    12         HWProtocolMessage::{self, Rnd},
     4         HWProtocolMessage::{self, Rnd},
    13         HWServerMessage::{
     5         HWServerMessage::{self, *},
    14             self, Bye, ChatMsg, ClientFlags, ForwardEngineMessage, HedgehogsNumber, Kicked,
       
    15             LobbyJoined, LobbyLeft, Notice, RoomLeft, RoomRemove, RoomUpdated, Rooms,
       
    16             ServerMessage, TeamRemove,
       
    17         },
       
    18     },
     6     },
    19     server::{actions::Action, core::HWServer},
     7     server::{
       
     8         actions::Action,
       
     9         client::HWClient,
       
    10         core::HWServer,
       
    11         coretypes::{ClientId, GameCfg, RoomId, Vote, VoteType},
       
    12         room::HWRoom,
       
    13     },
       
    14     utils::to_engine_msg,
    20 };
    15 };
       
    16 
       
    17 use super::Response;
       
    18 
    21 use rand::{self, thread_rng, Rng};
    19 use rand::{self, thread_rng, Rng};
    22 use std::iter::once;
    20 use std::{iter::once, mem::replace};
    23 use std::mem::replace;
       
    24 
    21 
    25 pub fn rnd_reply(options: &[String]) -> HWServerMessage {
    22 pub fn rnd_reply(options: &[String]) -> HWServerMessage {
    26     let mut rng = thread_rng();
    23     let mut rng = thread_rng();
    27     let reply = if options.is_empty() {
    24     let reply = if options.is_empty() {
    28         (*rng.choose(&["heads", "tails"]).unwrap()).to_owned()
    25         (*rng.choose(&["heads", "tails"]).unwrap()).to_owned()
    34         nick: "[random]".to_owned(),
    31         nick: "[random]".to_owned(),
    35         msg: reply.clone(),
    32         msg: reply.clone(),
    36     }
    33     }
    37 }
    34 }
    38 
    35 
    39 pub fn process_login(server: &mut HWServer, response: &mut super::Response) {
    36 pub fn process_login(server: &mut HWServer, response: &mut Response) {
    40     let client_id = response.client_id();
    37     let client_id = response.client_id();
    41     let nick = server.clients[client_id].nick.clone();
    38     let nick = server.clients[client_id].nick.clone();
    42 
    39 
    43     let has_nick_clash = server
    40     let has_nick_clash = server
    44         .clients
    41         .clients
    95 
    92 
    96 pub fn remove_teams(
    93 pub fn remove_teams(
    97     room: &mut HWRoom,
    94     room: &mut HWRoom,
    98     team_names: Vec<String>,
    95     team_names: Vec<String>,
    99     is_in_game: bool,
    96     is_in_game: bool,
   100     response: &mut super::Response,
    97     response: &mut Response,
   101 ) {
    98 ) {
   102     if let Some(ref mut info) = room.game_info {
    99     if let Some(ref mut info) = room.game_info {
   103         for team_name in &team_names {
   100         for team_name in &team_names {
   104             info.left_teams.push(team_name.clone());
   101             info.left_teams.push(team_name.clone());
   105 
   102 
   138         room.remove_team(&team_name);
   135         room.remove_team(&team_name);
   139         response.add(TeamRemove(team_name).send_all().in_room(room.id));
   136         response.add(TeamRemove(team_name).send_all().in_room(room.id));
   140     }
   137     }
   141 }
   138 }
   142 
   139 
   143 pub fn exit_room(client: &HWClient, room: &mut HWRoom, response: &mut super::Response, msg: &str) {
   140 pub fn exit_room(client: &HWClient, room: &mut HWRoom, response: &mut Response, msg: &str) {
   144     if room.players_number > 1 || room.is_fixed() {
   141     if room.players_number > 1 || room.is_fixed() {
   145         room.players_number -= 1;
   142         room.players_number -= 1;
   146         if client.is_ready() && room.ready_players_number > 0 {
   143         if client.is_ready() && room.ready_players_number > 0 {
   147             room.ready_players_number -= 1;
   144             room.ready_players_number -= 1;
   148         }
   145         }
   173     response.add(update_msg.send_all().with_protocol(room.protocol_number));
   170     response.add(update_msg.send_all().with_protocol(room.protocol_number));
   174 
   171 
   175     response.add(ClientFlags("-i".to_string(), vec![client.nick.clone()]).send_all());
   172     response.add(ClientFlags("-i".to_string(), vec![client.nick.clone()]).send_all());
   176 }
   173 }
   177 
   174 
   178 pub fn remove_client(server: &mut HWServer, response: &mut super::Response, msg: String) {
   175 pub fn remove_client(server: &mut HWServer, response: &mut Response, msg: String) {
   179     let client_id = response.client_id();
   176     let client_id = response.client_id();
   180     let lobby_id = server.lobby_id;
   177     let lobby_id = server.lobby_id;
   181     let client = &mut server.clients[client_id];
   178     let client = &mut server.clients[client_id];
   182     let (nick, room_id) = (client.nick.clone(), client.room_id);
   179     let (nick, room_id) = (client.nick.clone(), client.room_id);
   183 
   180 
   195 
   192 
   196 pub fn get_room_update(
   193 pub fn get_room_update(
   197     room_name: Option<String>,
   194     room_name: Option<String>,
   198     room: &HWRoom,
   195     room: &HWRoom,
   199     master: Option<&HWClient>,
   196     master: Option<&HWClient>,
   200     response: &mut super::Response,
   197     response: &mut Response,
   201 ) {
   198 ) {
   202     let update_msg = RoomUpdated(room_name.unwrap_or(room.name.clone()), room.info(master));
   199     let update_msg = RoomUpdated(room_name.unwrap_or(room.name.clone()), room.info(master));
   203     response.add(update_msg.send_all().with_protocol(room.protocol_number));
   200     response.add(update_msg.send_all().with_protocol(room.protocol_number));
   204 }
   201 }
   205 
   202 
   206 pub fn apply_voting_result(
   203 pub fn apply_voting_result(
   207     server: &mut HWServer,
   204     server: &mut HWServer,
   208     room_id: RoomId,
   205     room_id: RoomId,
   209     response: &mut super::Response,
   206     response: &mut Response,
   210     kind: VoteType,
   207     kind: VoteType,
   211 ) {
   208 ) {
   212     let client_id = response.client_id;
   209     let client_id = response.client_id;
   213 
   210 
   214     match kind {
   211     match kind {
   232                 response.add(
   229                 response.add(
   233                     server_chat(location.to_string())
   230                     server_chat(location.to_string())
   234                         .send_all()
   231                         .send_all()
   235                         .in_room(room_id),
   232                         .in_room(room_id),
   236                 );
   233                 );
   237                 get_room_update(
   234                 let room = &server.rooms[room_id];
   238                     None,
   235                 let room_master = if let Some(id) = room.master_id {
   239                     &server.rooms[room_id],
   236                     Some(&server.clients[id])
   240                     Some(&server.clients[client_id]),
   237                 } else {
   241                     response,
   238                     None
   242                 );
   239                 };
       
   240                 get_room_update(None, room, room_master, response);
   243 
   241 
   244                 for (_, c) in server.clients.iter() {
   242                 for (_, c) in server.clients.iter() {
   245                     if c.room_id == Some(room_id) {
   243                     if c.room_id == Some(room_id) {
   246                         /*SendRoomData {
   244                         /*SendRoomData {
   247                             to: c.id,
   245                             to: c.id,
   285             );
   283             );
   286         }
   284         }
   287     }
   285     }
   288 }
   286 }
   289 
   287 
   290 fn add_vote(room: &mut HWRoom, response: &mut super::Response, vote: Vote) -> Option<bool> {
   288 fn add_vote(room: &mut HWRoom, response: &mut Response, vote: Vote) -> Option<bool> {
   291     let client_id = response.client_id;
   289     let client_id = response.client_id;
   292     let mut result = None;
   290     let mut result = None;
   293 
   291 
   294     if let Some(ref mut voting) = room.voting {
   292     if let Some(ref mut voting) = room.voting {
   295         if vote.is_forced || voting.votes.iter().all(|(id, _)| client_id != *id) {
   293         if vote.is_forced || voting.votes.iter().all(|(id, _)| client_id != *id) {
   313     }
   311     }
   314 
   312 
   315     result
   313     result
   316 }
   314 }
   317 
   315 
   318 pub fn submit_vote(server: &mut HWServer, vote: Vote, response: &mut super::Response) {
   316 pub fn submit_vote(server: &mut HWServer, vote: Vote, response: &mut Response) {
   319     let client_id = response.client_id;
   317     let client_id = response.client_id;
   320     let client = &server.clients[client_id];
   318     let client = &server.clients[client_id];
   321 
   319 
   322     if let Some(room_id) = client.room_id {
   320     if let Some(room_id) = client.room_id {
   323         let room = &mut server.rooms[room_id];
   321         let room = &mut server.rooms[room_id];
   334             }
   332             }
   335         }
   333         }
   336     }
   334     }
   337 }
   335 }
   338 
   336 
       
   337 pub fn start_game(server: &mut HWServer, room_id: RoomId, response: &mut Response) {
       
   338     let (room_clients, room_nicks): (Vec<_>, Vec<_>) = server
       
   339         .clients
       
   340         .iter()
       
   341         .map(|(id, c)| (id, c.nick.clone()))
       
   342         .unzip();
       
   343     let room = &mut server.rooms[room_id];
       
   344 
       
   345     if !room.has_multiple_clans() {
       
   346         response.add(
       
   347             Warning("The game can't be started with less than two clans!".to_string()).send_self(),
       
   348         );
       
   349     } else if room.protocol_number <= 43 && room.players_number != room.ready_players_number {
       
   350         response.add(Warning("Not all players are ready".to_string()).send_self());
       
   351     } else if room.game_info.is_some() {
       
   352         response.add(Warning("The game is already in progress".to_string()).send_self());
       
   353     } else {
       
   354         room.start_round();
       
   355         for id in room_clients {
       
   356             let c = &mut server.clients[id];
       
   357             c.set_is_in_game(false);
       
   358             c.team_indices = room.client_team_indices(c.id);
       
   359         }
       
   360         response.add(RunGame.send_all().in_room(room.id));
       
   361         response.add(
       
   362             ClientFlags("+g".to_string(), room_nicks)
       
   363                 .send_all()
       
   364                 .in_room(room.id),
       
   365         );
       
   366 
       
   367         let room_master = if let Some(id) = room.master_id {
       
   368             Some(&server.clients[id])
       
   369         } else {
       
   370             None
       
   371         };
       
   372         get_room_update(None, room, room_master, response);
       
   373     }
       
   374 }
       
   375 
       
   376 pub fn end_game(server: &mut HWServer, room_id: RoomId, response: &mut Response) {
       
   377     let room = &mut server.rooms[room_id];
       
   378     room.ready_players_number = 1;
       
   379     let room_master = if let Some(id) = room.master_id {
       
   380         Some(&server.clients[id])
       
   381     } else {
       
   382         None
       
   383     };
       
   384     get_room_update(None, room, room_master, response);
       
   385     response.add(RoundFinished.send_all().in_room(room_id));
       
   386 
       
   387     if let Some(info) = replace(&mut room.game_info, None) {
       
   388         for (_, client) in server.clients.iter() {
       
   389             if client.room_id == Some(room_id) && client.is_joined_mid_game() {
       
   390                 //SendRoomData { to: client.id, teams: false, config: true, flags: false}
       
   391 
       
   392                 response.extend(
       
   393                     info.left_teams
       
   394                         .iter()
       
   395                         .map(|name| TeamRemove(name.clone()).send(client.id)),
       
   396                 );
       
   397             }
       
   398         }
       
   399     }
       
   400 
       
   401     let nicks: Vec<_> = server
       
   402         .clients
       
   403         .iter_mut()
       
   404         .filter(|(_, c)| c.room_id == Some(room_id))
       
   405         .map(|(_, c)| {
       
   406             c.set_is_ready(c.is_master());
       
   407             c.set_is_joined_mid_game(false);
       
   408             c
       
   409         })
       
   410         .filter_map(|c| {
       
   411             if !c.is_master() {
       
   412                 Some(c.nick.clone())
       
   413             } else {
       
   414                 None
       
   415             }
       
   416         })
       
   417         .collect();
       
   418 
       
   419     if !nicks.is_empty() {
       
   420         let msg = if room.protocol_number < 38 {
       
   421             LegacyReady(false, nicks)
       
   422         } else {
       
   423             ClientFlags("-r".to_string(), nicks)
       
   424         };
       
   425         response.add(msg.send_all().in_room(room_id));
       
   426     }
       
   427 }
       
   428 
   339 #[cfg(test)]
   429 #[cfg(test)]
   340 mod tests {
   430 mod tests {
   341     use super::*;
   431     use super::*;
   342     use crate::protocol::messages::HWServerMessage::ChatMsg;
   432     use crate::protocol::messages::HWServerMessage::ChatMsg;
   343     use crate::server::actions::PendingMessage;
   433     use crate::server::actions::PendingMessage;