rust/hedgewars-server/src/server/handlers/inroom.rs
changeset 14697 f64e21f164a5
parent 14694 25c564f77b7d
child 14780 65861ba8b4e8
equal deleted inserted replaced
14696:8a45c90f4580 14697:f64e21f164a5
   106     client_id: ClientId,
   106     client_id: ClientId,
   107     response: &mut super::Response,
   107     response: &mut super::Response,
   108     room_id: RoomId,
   108     room_id: RoomId,
   109     message: HWProtocolMessage,
   109     message: HWProtocolMessage,
   110 ) {
   110 ) {
       
   111     let client = &mut server.clients[client_id];
       
   112     let room = &mut server.rooms[room_id];
       
   113 
   111     use crate::protocol::messages::HWProtocolMessage::*;
   114     use crate::protocol::messages::HWProtocolMessage::*;
   112     match message {
   115     match message {
   113         Part(msg) => {
   116         Part(msg) => {
   114             if let (client, Some(room)) = server.client_and_room(client_id) {
   117             let msg = match msg {
   115                 let msg = match msg {
   118                 Some(s) => format!("part: {}", s),
   116                     Some(s) => format!("part: {}", s),
   119                 None => "part".to_string(),
   117                     None => "part".to_string(),
   120             };
   118                 };
   121             super::common::exit_room(server, client_id, response, &msg);
   119                 super::common::exit_room(server, client_id, response, &msg);
       
   120             }
       
   121         }
   122         }
   122         Chat(msg) => {
   123         Chat(msg) => {
   123             let client = &mut server.clients[client_id];
       
   124             response.add(
   124             response.add(
   125                 ChatMsg {
   125                 ChatMsg {
   126                     nick: client.nick.clone(),
   126                     nick: client.nick.clone(),
   127                     msg,
   127                     msg,
   128                 }
   128                 }
   129                 .send_all()
   129                 .send_all()
   130                 .in_room(room_id),
   130                 .in_room(room_id),
   131             );
   131             );
   132         }
   132         }
   133         Fix => {
   133         Fix => {
   134             if let (client, Some(room)) = server.client_and_room(client_id) {
   134             if client.is_admin() {
   135                 if client.is_admin() {
   135                 room.set_is_fixed(true);
   136                     room.set_is_fixed(true);
   136                 room.set_join_restriction(false);
   137                     room.set_join_restriction(false);
   137                 room.set_team_add_restriction(false);
   138                     room.set_team_add_restriction(false);
   138                 room.set_unregistered_players_restriction(true);
   139                     room.set_unregistered_players_restriction(true);
       
   140                 }
       
   141             }
   139             }
   142         }
   140         }
   143         Unfix => {
   141         Unfix => {
   144             if let (client, Some(room)) = server.client_and_room(client_id) {
   142             if client.is_admin() {
   145                 if client.is_admin() {
   143                 room.set_is_fixed(false);
   146                     room.set_is_fixed(false)
       
   147                 }
       
   148             }
   144             }
   149         }
   145         }
   150         Greeting(text) => {
   146         Greeting(text) => {
   151             if let (clienr, Some(room)) = server.client_and_room(client_id) {
   147             if client.is_admin() || client.is_master() && !room.is_fixed() {
   152                 if clienr.is_admin() || clienr.is_master() && !room.is_fixed() {
   148                 room.greeting = text;
   153                     room.greeting = text
       
   154                 }
       
   155             }
   149             }
   156         }
   150         }
   157         RoomName(new_name) => {
   151         RoomName(new_name) => {
   158             if is_name_illegal(&new_name) {
   152             if is_name_illegal(&new_name) {
   159                 response.add(Warning("Illegal room name! A room name must be between 1-40 characters long, must not have a trailing or leading space and must not have any of these characters: $()*+?[]^{|}".to_string()).send_self());
   153                 response.add(Warning("Illegal room name! A room name must be between 1-40 characters long, must not have a trailing or leading space and must not have any of these characters: $()*+?[]^{|}".to_string()).send_self());
   172                     super::common::get_room_update(Some(old_name), room, Some(&client), response);
   166                     super::common::get_room_update(Some(old_name), room, Some(&client), response);
   173                 }
   167                 }
   174             }
   168             }
   175         }
   169         }
   176         ToggleReady => {
   170         ToggleReady => {
   177             if let (client, Some(room)) = server.client_and_room(client_id) {
   171             let flags = if client.is_ready() {
   178                 let flags = if client.is_ready() {
   172                 room.ready_players_number -= 1;
   179                     room.ready_players_number -= 1;
   173                 "-r"
   180                     "-r"
   174             } else {
   181                 } else {
   175                 room.ready_players_number += 1;
   182                     room.ready_players_number += 1;
   176                 "+r"
   183                     "+r"
   177             };
   184                 };
   178 
   185 
   179             let msg = if client.protocol_number < 38 {
   186                 let msg = if client.protocol_number < 38 {
   180                 LegacyReady(client.is_ready(), vec![client.nick.clone()])
   187                     LegacyReady(client.is_ready(), vec![client.nick.clone()])
   181             } else {
   188                 } else {
   182                 ClientFlags(flags.to_string(), vec![client.nick.clone()])
   189                     ClientFlags(flags.to_string(), vec![client.nick.clone()])
   183             };
   190                 };
   184             response.add(msg.send_all().in_room(room.id));
   191                 response.add(msg.send_all().in_room(room.id));
   185             client.set_is_ready(!client.is_ready());
   192                 client.set_is_ready(!client.is_ready());
   186 
   193 
   187             if room.is_fixed() && room.ready_players_number == room.players_number {
   194                 if room.is_fixed() && room.ready_players_number == room.players_number {
   188                 super::common::start_game(server, room_id, response);
   195                     super::common::start_game(server, room_id, response);
       
   196                 }
       
   197             }
   189             }
   198         }
   190         }
   199         AddTeam(info) => {
   191         AddTeam(info) => {
   200             let client = &mut server.clients[client_id];
       
   201             let room = &mut server.rooms[room_id];
       
   202             if room.teams.len() >= room.team_limit as usize {
   192             if room.teams.len() >= room.team_limit as usize {
   203                 response.add(Warning("Too many teams!".to_string()).send_self());
   193                 response.add(Warning("Too many teams!".to_string()).send_self());
   204             } else if room.addable_hedgehogs() == 0 {
   194             } else if room.addable_hedgehogs() == 0 {
   205                 response.add(Warning("Too many hedgehogs!".to_string()).send_self());
   195                 response.add(Warning("Too many hedgehogs!".to_string()).send_self());
   206             } else if room.find_team(|t| t.name == info.name) != None {
   196             } else if room.find_team(|t| t.name == info.name) != None {
   245                     None
   235                     None
   246                 };
   236                 };
   247                 super::common::get_room_update(None, room, room_master, response);
   237                 super::common::get_room_update(None, room, room_master, response);
   248             }
   238             }
   249         }
   239         }
   250         RemoveTeam(name) => {
   240         RemoveTeam(name) => match room.find_team_owner(&name) {
   251             let client = &mut server.clients[client_id];
   241             None => response.add(
   252             let room = &mut server.rooms[room_id];
   242                 Warning("Error: The team you tried to remove does not exist.".to_string())
   253             match room.find_team_owner(&name) {
   243                     .send_self(),
   254                 None => response.add(
   244             ),
   255                     Warning("Error: The team you tried to remove does not exist.".to_string())
   245             Some((id, _)) if id != client_id => response
   256                         .send_self(),
   246                 .add(Warning("You can't remove a team you don't own.".to_string()).send_self()),
   257                 ),
   247             Some((_, name)) => {
   258                 Some((id, _)) if id != client_id => response
   248                 client.teams_in_game -= 1;
   259                     .add(Warning("You can't remove a team you don't own.".to_string()).send_self()),
   249                 client.clan = room.find_team_color(client.id);
   260                 Some((_, name)) => {
   250                 super::common::remove_teams(
   261                     client.teams_in_game -= 1;
   251                     room,
   262                     client.clan = room.find_team_color(client.id);
   252                     vec![name.to_string()],
   263                     super::common::remove_teams(
   253                     client.is_in_game(),
   264                         room,
   254                     response,
   265                         vec![name.to_string()],
   255                 );
   266                         client.is_in_game(),
   256 
   267                         response,
   257                 match room.game_info {
       
   258                     Some(ref info) if info.teams_in_game == 0 => {
       
   259                         super::common::end_game(server, room_id, response)
       
   260                     }
       
   261                     _ => (),
       
   262                 }
       
   263             }
       
   264         },
       
   265         SetHedgehogsNumber(team_name, number) => {
       
   266             let addable_hedgehogs = room.addable_hedgehogs();
       
   267             if let Some((_, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) {
       
   268                 if !client.is_master() {
       
   269                     response.add(Error("You're not the room master!".to_string()).send_self());
       
   270                 } else if number < 1
       
   271                     || number > MAX_HEDGEHOGS_PER_TEAM
       
   272                     || number > addable_hedgehogs + team.hedgehogs_number
       
   273                 {
       
   274                     response
       
   275                         .add(HedgehogsNumber(team.name.clone(), team.hedgehogs_number).send_self());
       
   276                 } else {
       
   277                     team.hedgehogs_number = number;
       
   278                     response.add(
       
   279                         HedgehogsNumber(team.name.clone(), number)
       
   280                             .send_all()
       
   281                             .in_room(room_id)
       
   282                             .but_self(),
   268                     );
   283                     );
   269 
   284                 }
   270                     match room.game_info {
   285             } else {
   271                         Some(ref info) if info.teams_in_game == 0 => {
   286                 response.add(Warning("No such team.".to_string()).send_self());
   272                             super::common::end_game(server, room_id, response)
       
   273                         }
       
   274                         _ => (),
       
   275                     }
       
   276                 }
       
   277             }
       
   278         }
       
   279         SetHedgehogsNumber(team_name, number) => {
       
   280             if let (client, Some(room)) = server.client_and_room(client_id) {
       
   281                 let addable_hedgehogs = room.addable_hedgehogs();
       
   282                 if let Some((_, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) {
       
   283                     if !client.is_master() {
       
   284                         response.add(Error("You're not the room master!".to_string()).send_self());
       
   285                     } else if number < 1
       
   286                         || number > MAX_HEDGEHOGS_PER_TEAM
       
   287                         || number > addable_hedgehogs + team.hedgehogs_number
       
   288                     {
       
   289                         response.add(
       
   290                             HedgehogsNumber(team.name.clone(), team.hedgehogs_number).send_self(),
       
   291                         );
       
   292                     } else {
       
   293                         team.hedgehogs_number = number;
       
   294                         response.add(
       
   295                             HedgehogsNumber(team.name.clone(), number)
       
   296                                 .send_all()
       
   297                                 .in_room(room_id)
       
   298                                 .but_self(),
       
   299                         );
       
   300                     }
       
   301                 } else {
       
   302                     response.add(Warning("No such team.".to_string()).send_self());
       
   303                 }
       
   304             }
   287             }
   305         }
   288         }
   306         SetTeamColor(team_name, color) => {
   289         SetTeamColor(team_name, color) => {
   307             if let (client, Some(room)) = server.client_and_room(client_id) {
   290             if let Some((owner, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) {
   308                 if let Some((owner, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) {
   291                 if !client.is_master() {
   309                     if !client.is_master() {
       
   310                         response.add(Error("You're not the room master!".to_string()).send_self());
       
   311                     } else {
       
   312                         team.color = color;
       
   313                         response.add(
       
   314                             TeamColor(team.name.clone(), color)
       
   315                                 .send_all()
       
   316                                 .in_room(room_id)
       
   317                                 .but_self(),
       
   318                         );
       
   319                         server.clients[owner].clan = Some(color);
       
   320                     }
       
   321                 } else {
       
   322                     response.add(Warning("No such team.".to_string()).send_self());
       
   323                 }
       
   324             }
       
   325         }
       
   326         Cfg(cfg) => {
       
   327             if let (client, Some(room)) = server.client_and_room(client_id) {
       
   328                 if room.is_fixed() {
       
   329                     response.add(Warning("Access denied.".to_string()).send_self());
       
   330                 } else if !client.is_master() {
       
   331                     response.add(Error("You're not the room master!".to_string()).send_self());
   292                     response.add(Error("You're not the room master!".to_string()).send_self());
   332                 } else {
   293                 } else {
   333                     let cfg = match cfg {
   294                     team.color = color;
   334                         GameCfg::Scheme(name, mut values) => {
   295                     response.add(
   335                             if client.protocol_number == 49 && values.len() >= 2 {
   296                         TeamColor(team.name.clone(), color)
   336                                 let mut s = "X".repeat(50);
   297                             .send_all()
   337                                 s.push_str(&values.pop().unwrap());
   298                             .in_room(room_id)
   338                                 values.push(s);
   299                             .but_self(),
   339                             }
   300                     );
   340                             GameCfg::Scheme(name, values)
   301                     server.clients[owner].clan = Some(color);
       
   302                 }
       
   303             } else {
       
   304                 response.add(Warning("No such team.".to_string()).send_self());
       
   305             }
       
   306         }
       
   307         Cfg(cfg) => {
       
   308             if room.is_fixed() {
       
   309                 response.add(Warning("Access denied.".to_string()).send_self());
       
   310             } else if !client.is_master() {
       
   311                 response.add(Error("You're not the room master!".to_string()).send_self());
       
   312             } else {
       
   313                 let cfg = match cfg {
       
   314                     GameCfg::Scheme(name, mut values) => {
       
   315                         if client.protocol_number == 49 && values.len() >= 2 {
       
   316                             let mut s = "X".repeat(50);
       
   317                             s.push_str(&values.pop().unwrap());
       
   318                             values.push(s);
   341                         }
   319                         }
   342                         cfg => cfg,
   320                         GameCfg::Scheme(name, values)
   343                     };
   321                     }
   344 
   322                     cfg => cfg,
   345                     response.add(cfg.to_server_msg().send_all().in_room(room.id).but_self());
   323                 };
   346                     room.set_config(cfg);
   324 
   347                 }
   325                 response.add(cfg.to_server_msg().send_all().in_room(room.id).but_self());
       
   326                 room.set_config(cfg);
   348             }
   327             }
   349         }
   328         }
   350         Save(name, location) => {
   329         Save(name, location) => {
   351             response.add(
   330             response.add(
   352                 server_chat(format!("Room config saved as {}", name))
   331                 server_chat(format!("Room config saved as {}", name))
   353                     .send_all()
   332                     .send_all()
   354                     .in_room(room_id),
   333                     .in_room(room_id),
   355             );
   334             );
   356             server.rooms[room_id].save_config(name, location);
   335             room.save_config(name, location);
   357         }
   336         }
   358         SaveRoom(filename) => {
   337         SaveRoom(filename) => {
   359             if server.clients[client_id].is_admin() {
   338             if client.is_admin() {
   360                 match server.rooms[room_id].get_saves() {
   339                 match room.get_saves() {
   361                     Ok(text) => match server.io.write_file(&filename, &text) {
   340                     Ok(text) => match server.io.write_file(&filename, &text) {
   362                         Ok(_) => response.add(
   341                         Ok(_) => response.add(
   363                             server_chat("Room configs saved successfully.".to_string()).send_self(),
   342                             server_chat("Room configs saved successfully.".to_string()).send_self(),
   364                         ),
   343                         ),
   365                         Err(e) => {
   344                         Err(e) => {
   381                     }
   360                     }
   382                 }
   361                 }
   383             }
   362             }
   384         }
   363         }
   385         LoadRoom(filename) => {
   364         LoadRoom(filename) => {
   386             if server.clients[client_id].is_admin() {
   365             if client.is_admin() {
   387                 match server.io.read_file(&filename) {
   366                 match server.io.read_file(&filename) {
   388                     Ok(text) => match server.rooms[room_id].set_saves(&text) {
   367                     Ok(text) => match room.set_saves(&text) {
   389                         Ok(_) => response.add(
   368                         Ok(_) => response.add(
   390                             server_chat("Room configs loaded successfully.".to_string())
   369                             server_chat("Room configs loaded successfully.".to_string())
   391                                 .send_self(),
   370                                 .send_self(),
   392                         ),
   371                         ),
   393                         Err(e) => {
   372                         Err(e) => {
   409                     }
   388                     }
   410                 }
   389                 }
   411             }
   390             }
   412         }
   391         }
   413         Delete(name) => {
   392         Delete(name) => {
   414             if !server.rooms[room_id].delete_config(&name) {
   393             if !room.delete_config(&name) {
   415                 response.add(Warning(format!("Save doesn't exist: {}", name)).send_self());
   394                 response.add(Warning(format!("Save doesn't exist: {}", name)).send_self());
   416             } else {
   395             } else {
   417                 response.add(
   396                 response.add(
   418                     server_chat(format!("Room config {} has been deleted", name))
   397                     server_chat(format!("Room config {} has been deleted", name))
   419                         .send_all()
   398                         .send_all()
   424         CallVote(None) => {
   403         CallVote(None) => {
   425             response.add(server_chat("Available callvote commands: kick <nickname>, map <name>, pause, newseed, hedgehogs <number>".to_string())
   404             response.add(server_chat("Available callvote commands: kick <nickname>, map <name>, pause, newseed, hedgehogs <number>".to_string())
   426                 .send_self());
   405                 .send_self());
   427         }
   406         }
   428         CallVote(Some(kind)) => {
   407         CallVote(Some(kind)) => {
   429             let is_in_game = server.rooms[room_id].game_info.is_some();
   408             let is_in_game = room.game_info.is_some();
   430             let error = match &kind {
   409             let error = match &kind {
   431                 VoteType::Kick(nick) => {
   410                 VoteType::Kick(nick) => {
   432                     if server
   411                     if server
   433                         .find_client(&nick)
   412                         .find_client(&nick)
   434                         .filter(|c| c.room_id == Some(room_id))
   413                         .filter(|c| c.room_id == Some(room_id))
   446                     } else {
   425                     } else {
   447                         Some(format!("Available maps: {}", names.join(", ")))
   426                         Some(format!("Available maps: {}", names.join(", ")))
   448                     }
   427                     }
   449                 }
   428                 }
   450                 VoteType::Map(Some(name)) => {
   429                 VoteType::Map(Some(name)) => {
   451                     if server.rooms[room_id].saves.get(&name[..]).is_some() {
   430                     if room.saves.get(&name[..]).is_some() {
   452                         None
   431                         None
   453                     } else {
   432                     } else {
   454                         Some("/callvote map: No such map!".to_string())
   433                         Some("/callvote map: No such map!".to_string())
   455                     }
   434                     }
   456                 }
   435                 }
   465                 VoteType::HedgehogsPerTeam(number) => match number {
   444                 VoteType::HedgehogsPerTeam(number) => match number {
   466                     1...MAX_HEDGEHOGS_PER_TEAM => None,
   445                     1...MAX_HEDGEHOGS_PER_TEAM => None,
   467                     _ => Some("/callvote hedgehogs: Specify number from 1 to 8.".to_string()),
   446                     _ => Some("/callvote hedgehogs: Specify number from 1 to 8.".to_string()),
   468                 },
   447                 },
   469             };
   448             };
       
   449 
   470             match error {
   450             match error {
   471                 None => {
   451                 None => {
   472                     let msg = voting_description(&kind);
   452                     let msg = voting_description(&kind);
   473                     let voting = Voting::new(kind, server.room_clients(client_id));
   453                     let voting = Voting::new(kind, server.room_clients(client_id));
   474                     let room = &mut server.rooms[room_id];
   454                     let room = &mut server.rooms[room_id];
   497                 },
   477                 },
   498                 response,
   478                 response,
   499             );
   479             );
   500         }
   480         }
   501         ForceVote(vote) => {
   481         ForceVote(vote) => {
   502             let is_forced = server.clients[client_id].is_admin();
   482             let is_forced = client.is_admin();
   503             super::common::submit_vote(
   483             super::common::submit_vote(
   504                 server,
   484                 server,
   505                 coretypes::Vote {
   485                 coretypes::Vote {
   506                     is_pro: vote,
   486                     is_pro: vote,
   507                     is_forced,
   487                     is_forced,
   508                 },
   488                 },
   509                 response,
   489                 response,
   510             );
   490             );
   511         }
   491         }
   512         ToggleRestrictJoin | ToggleRestrictTeams | ToggleRegisteredOnly => {
   492         ToggleRestrictJoin | ToggleRestrictTeams | ToggleRegisteredOnly => {
   513             let client = &server.clients[client_id];
       
   514             let room = &mut server.rooms[room_id];
       
   515             if client.is_master() {
   493             if client.is_master() {
   516                 room.flags.toggle(room_message_flag(&message));
   494                 room.flags.toggle(room_message_flag(&message));
   517                 super::common::get_room_update(None, room, Some(&client), response);
   495                 super::common::get_room_update(None, room, Some(&client), response);
   518             }
   496             }
   519         }
   497         }
   520         StartGame => {
   498         StartGame => {
   521             super::common::start_game(server, room_id, response);
   499             super::common::start_game(server, room_id, response);
   522         }
   500         }
   523         EngineMessage(em) => {
   501         EngineMessage(em) => {
   524             if let (c, Some(r)) = server.client_and_room(client_id) {
   502             if client.teams_in_game > 0 {
   525                 if c.teams_in_game > 0 {
   503                 let decoding = decode(&em[..]).unwrap();
   526                     let decoding = decode(&em[..]).unwrap();
   504                 let messages = by_msg(&decoding);
   527                     let messages = by_msg(&decoding);
   505                 let valid = messages.filter(|m| is_msg_valid(m, &client.team_indices));
   528                     let valid = messages.filter(|m| is_msg_valid(m, &c.team_indices));
   506                 let non_empty = valid.clone().filter(|m| !is_msg_empty(m));
   529                     let non_empty = valid.clone().filter(|m| !is_msg_empty(m));
   507                 let sync_msg = valid.clone().filter(|m| is_msg_timed(m)).last().map(|m| {
   530                     let sync_msg = valid.clone().filter(|m| is_msg_timed(m)).last().map(|m| {
   508                     if is_msg_empty(m) {
   531                         if is_msg_empty(m) {
   509                         Some(encode(m))
   532                             Some(encode(m))
   510                     } else {
   533                         } else {
   511                         None
   534                             None
   512                     }
   535                         }
   513                 });
   536                     });
   514 
   537 
   515                 let em_response = encode(&valid.flat_map(|msg| msg).cloned().collect::<Vec<_>>());
   538                     let em_response =
   516                 if !em_response.is_empty() {
   539                         encode(&valid.flat_map(|msg| msg).cloned().collect::<Vec<_>>());
   517                     response.add(
   540                     if !em_response.is_empty() {
   518                         ForwardEngineMessage(vec![em_response])
   541                         response.add(
   519                             .send_all()
   542                             ForwardEngineMessage(vec![em_response])
   520                             .in_room(room.id)
   543                                 .send_all()
   521                             .but_self(),
   544                                 .in_room(r.id)
   522                     );
   545                                 .but_self(),
   523                 }
   546                         );
   524                 let em_log = encode(&non_empty.flat_map(|msg| msg).cloned().collect::<Vec<_>>());
   547                     }
   525                 if let Some(ref mut info) = room.game_info {
   548                     let em_log =
   526                     if !em_log.is_empty() {
   549                         encode(&non_empty.flat_map(|msg| msg).cloned().collect::<Vec<_>>());
   527                         info.msg_log.push(em_log);
   550                     if let Some(ref mut info) = r.game_info {
   528                     }
   551                         if !em_log.is_empty() {
   529                     if let Some(msg) = sync_msg {
   552                             info.msg_log.push(em_log);
   530                         info.sync_msg = msg;
   553                         }
       
   554                         if let Some(msg) = sync_msg {
       
   555                             info.sync_msg = msg;
       
   556                         }
       
   557                     }
   531                     }
   558                 }
   532                 }
   559             }
   533             }
   560         }
   534         }
   561         RoundFinished => {
   535         RoundFinished => {
   562             let mut game_ended = false;
   536             let mut game_ended = false;
   563             let client = &mut server.clients[client_id];
       
   564             if client.is_in_game() {
   537             if client.is_in_game() {
   565                 let room = &mut server.rooms[room_id];
       
   566 
       
   567                 client.set_is_in_game(false);
   538                 client.set_is_in_game(false);
   568                 response.add(
   539                 response.add(
   569                     ClientFlags("-g".to_string(), vec![client.nick.clone()])
   540                     ClientFlags("-g".to_string(), vec![client.nick.clone()])
   570                         .send_all()
   541                         .send_all()
   571                         .in_room(room.id),
   542                         .in_room(room.id),