rust/hedgewars-server/src/core/server.rs
changeset 15523 f4f6060b536c
parent 15522 4a0b06b03199
child 15525 16d3c9acd715
equal deleted inserted replaced
15522:4a0b06b03199 15523:f4f6060b536c
     1 use super::{
     1 use super::{
     2     anteroom::HwAnteroomClient,
     2     anteroom::HwAnteroomClient,
     3     client::HwClient,
     3     client::HwClient,
     4     indexslab::IndexSlab,
     4     indexslab::IndexSlab,
     5     room::HwRoom,
     5     room::HwRoom,
     6     types::{ClientId, RoomId, ServerVar, TeamInfo},
     6     types::{ClientId, GameCfg, RoomId, ServerVar, TeamInfo},
     7 };
     7 };
     8 use crate::{protocol::messages::HwProtocolMessage::Greeting, utils};
     8 use crate::{protocol::messages::HwProtocolMessage::Greeting, utils};
     9 
     9 
    10 use bitflags::_core::hint::unreachable_unchecked;
    10 use bitflags::_core::hint::unreachable_unchecked;
    11 use bitflags::*;
    11 use bitflags::*;
    12 use log::*;
    12 use log::*;
    13 use slab::Slab;
    13 use slab::Slab;
    14 use std::{borrow::BorrowMut, collections::HashSet, iter, mem::replace};
    14 use std::{borrow::BorrowMut, cmp::min, collections::HashSet, iter, mem::replace};
    15 
    15 
    16 #[derive(Debug)]
    16 #[derive(Debug)]
    17 pub enum CreateRoomError {
    17 pub enum CreateRoomError {
    18     InvalidName,
    18     InvalidName,
    19     AlreadyExists,
    19     AlreadyExists,
    38         removed_teams: Vec<String>,
    38         removed_teams: Vec<String>,
    39     },
    39     },
    40 }
    40 }
    41 
    41 
    42 #[derive(Debug)]
    42 #[derive(Debug)]
    43 pub enum LeaveRoomError {
       
    44     NoRoom,
       
    45 }
       
    46 
       
    47 #[derive(Debug)]
       
    48 pub struct ChangeMasterResult {
    43 pub struct ChangeMasterResult {
    49     pub old_master_id: Option<ClientId>,
    44     pub old_master_id: Option<ClientId>,
    50     pub new_master_id: ClientId,
    45     pub new_master_id: ClientId,
    51 }
    46 }
    52 
    47 
    75 
    70 
    76 #[derive(Debug)]
    71 #[derive(Debug)]
    77 pub enum ModifyTeamError {
    72 pub enum ModifyTeamError {
    78     NoTeam,
    73     NoTeam,
    79     NotMaster,
    74     NotMaster,
       
    75 }
       
    76 
       
    77 #[derive(Debug)]
       
    78 pub enum SetTeamCountError {
       
    79     InvalidNumber,
       
    80     NotMaster,
       
    81 }
       
    82 
       
    83 #[derive(Debug)]
       
    84 pub enum SetHedgehogsError {
       
    85     NoTeam,
       
    86     InvalidNumber(u8),
       
    87     NotMaster,
       
    88 }
       
    89 
       
    90 #[derive(Debug)]
       
    91 pub enum SetConfigError {
       
    92     NotMaster,
       
    93     RoomFixed,
    80 }
    94 }
    81 
    95 
    82 #[derive(Debug)]
    96 #[derive(Debug)]
    83 pub enum ModifyRoomNameError {
    97 pub enum ModifyRoomNameError {
    84     AccessDenied,
    98     AccessDenied,
   196     pub fn client_and_room(&self, client_id: ClientId, room_id: RoomId) -> (&HwClient, &HwRoom) {
   210     pub fn client_and_room(&self, client_id: ClientId, room_id: RoomId) -> (&HwClient, &HwRoom) {
   197         (&self.clients[client_id], &self.rooms[room_id])
   211         (&self.clients[client_id], &self.rooms[room_id])
   198     }
   212     }
   199 
   213 
   200     #[inline]
   214     #[inline]
   201     pub fn client_and_room_mut(
   215     fn client_and_room_mut(&mut self, client_id: ClientId) -> Option<(&mut HwClient, &mut HwRoom)> {
   202         &mut self,
   216         let client = &mut self.clients[client_id];
   203         client_id: ClientId,
   217         if let Some(room_id) = client.room_id {
   204         room_id: RoomId,
   218             Some((client, &mut self.rooms[room_id]))
   205     ) -> (&HwClient, &HwRoom) {
   219         } else {
   206         (&self.clients[client_id], &mut self.rooms[room_id])
   220             None
       
   221         }
       
   222     }
       
   223 
       
   224     #[inline]
       
   225     pub fn get_room_control(&mut self, client_id: ClientId) -> Option<HwRoomControl> {
       
   226         HwRoomControl::new(self, client_id)
   207     }
   227     }
   208 
   228 
   209     #[inline]
   229     #[inline]
   210     pub fn is_admin(&self, client_id: ClientId) -> bool {
   230     pub fn is_admin(&self, client_id: ClientId) -> bool {
   211         self.clients
   231         self.clients
   311         } else {
   331         } else {
   312             Err(DoesntExist)
   332             Err(DoesntExist)
   313         }
   333         }
   314     }
   334     }
   315 
   335 
   316     pub fn leave_room(&mut self, client_id: ClientId) -> Result<LeaveRoomResult, LeaveRoomError> {
   336     pub fn enable_super_power(&mut self, client_id: ClientId) -> bool {
   317         let client = &mut self.clients[client_id];
   337         let client = &mut self.clients[client_id];
   318         if let Some(room_id) = client.room_id {
   338         if client.is_admin() {
   319             let room = &mut self.rooms[room_id];
   339             client.set_has_super_power(true);
   320 
   340         }
   321             room.players_number -= 1;
   341         client.is_admin()
   322             client.room_id = None;
   342     }
   323 
   343 
   324             let is_empty = room.players_number == 0;
   344     #[inline]
   325             let is_fixed = room.is_fixed();
   345     pub fn set_var(&mut self, client_id: ClientId, var: ServerVar) -> Result<(), AccessError> {
   326             let was_master = room.master_id == Some(client_id);
   346         if self.clients[client_id].is_admin() {
   327             let was_in_game = client.is_in_game();
   347             match var {
   328             let mut removed_teams = vec![];
   348                 ServerVar::MOTDNew(msg) => self.greetings.for_latest_protocol = msg,
   329 
   349                 ServerVar::MOTDOld(msg) => self.greetings.for_old_protocols = msg,
   330             if is_empty && !is_fixed {
   350                 ServerVar::LatestProto(n) => self.latest_protocol = n,
   331                 if client.is_ready() && room.ready_players_number > 0 {
   351             }
   332                     room.ready_players_number -= 1;
   352             Ok(())
       
   353         } else {
       
   354             Err(AccessError())
       
   355         }
       
   356     }
       
   357 
       
   358     #[inline]
       
   359     pub fn get_vars(&self, client_id: ClientId) -> Result<[ServerVar; 3], AccessError> {
       
   360         if self.clients[client_id].is_admin() {
       
   361             Ok([
       
   362                 ServerVar::MOTDNew(self.greetings.for_latest_protocol.clone()),
       
   363                 ServerVar::MOTDOld(self.greetings.for_old_protocols.clone()),
       
   364                 ServerVar::LatestProto(self.latest_protocol),
       
   365             ])
       
   366         } else {
       
   367             Err(AccessError())
       
   368         }
       
   369     }
       
   370 
       
   371     pub fn get_used_protocols(&self, client_id: ClientId) -> Result<Vec<u16>, AccessError> {
       
   372         if self.clients[client_id].is_admin() {
       
   373             let mut protocols: HashSet<_> = self
       
   374                 .clients
       
   375                 .iter()
       
   376                 .map(|(_, c)| c.protocol_number)
       
   377                 .chain(self.rooms.iter().map(|(_, r)| r.protocol_number))
       
   378                 .collect();
       
   379             let mut protocols: Vec<_> = protocols.drain().collect();
       
   380             protocols.sort();
       
   381             Ok(protocols)
       
   382         } else {
       
   383             Err(AccessError())
       
   384         }
       
   385     }
       
   386 
       
   387     #[inline]
       
   388     pub fn has_room(&self, name: &str) -> bool {
       
   389         self.find_room(name).is_some()
       
   390     }
       
   391 
       
   392     #[inline]
       
   393     pub fn find_room(&self, name: &str) -> Option<&HwRoom> {
       
   394         self.rooms
       
   395             .iter()
       
   396             .find_map(|(_, r)| Some(r).filter(|r| r.name == name))
       
   397     }
       
   398 
       
   399     pub fn find_room_mut(&mut self, name: &str) -> Option<&mut HwRoom> {
       
   400         self.rooms
       
   401             .iter_mut()
       
   402             .find_map(|(_, r)| Some(r).filter(|r| r.name == name))
       
   403     }
       
   404 
       
   405     pub fn find_client(&self, nick: &str) -> Option<&HwClient> {
       
   406         self.clients
       
   407             .iter()
       
   408             .find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
       
   409     }
       
   410 
       
   411     pub fn find_client_mut(&mut self, nick: &str) -> Option<&mut HwClient> {
       
   412         self.clients
       
   413             .iter_mut()
       
   414             .find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
       
   415     }
       
   416 
       
   417     pub fn all_clients(&self) -> impl Iterator<Item = ClientId> + '_ {
       
   418         self.clients.iter().map(|(id, _)| id)
       
   419     }
       
   420 
       
   421     pub fn filter_clients<'a, F>(&'a self, f: F) -> impl Iterator<Item = ClientId> + 'a
       
   422     where
       
   423         F: Fn(&(usize, &HwClient)) -> bool + 'a,
       
   424     {
       
   425         self.clients.iter().filter(f).map(|(_, c)| c.id)
       
   426     }
       
   427 
       
   428     pub fn filter_rooms<'a, F>(&'a self, f: F) -> impl Iterator<Item = RoomId> + 'a
       
   429     where
       
   430         F: Fn(&(usize, &HwRoom)) -> bool + 'a,
       
   431     {
       
   432         self.rooms.iter().filter(f).map(|(_, c)| c.id)
       
   433     }
       
   434 
       
   435     pub fn collect_clients<F>(&self, f: F) -> Vec<ClientId>
       
   436     where
       
   437         F: Fn(&(usize, &HwClient)) -> bool,
       
   438     {
       
   439         self.filter_clients(f).collect()
       
   440     }
       
   441 
       
   442     pub fn collect_nicks<F>(&self, f: F) -> Vec<String>
       
   443     where
       
   444         F: Fn(&(usize, &HwClient)) -> bool,
       
   445     {
       
   446         self.clients
       
   447             .iter()
       
   448             .filter(f)
       
   449             .map(|(_, c)| c.nick.clone())
       
   450             .collect()
       
   451     }
       
   452 
       
   453     pub fn lobby_clients(&self) -> impl Iterator<Item = ClientId> + '_ {
       
   454         self.filter_clients(|(_, c)| c.room_id == None)
       
   455     }
       
   456 
       
   457     pub fn room_clients(&self, room_id: RoomId) -> impl Iterator<Item = ClientId> + '_ {
       
   458         self.filter_clients(move |(_, c)| c.room_id == Some(room_id))
       
   459     }
       
   460 
       
   461     pub fn protocol_clients(&self, protocol: u16) -> impl Iterator<Item = ClientId> + '_ {
       
   462         self.filter_clients(move |(_, c)| c.protocol_number == protocol)
       
   463     }
       
   464 
       
   465     pub fn protocol_rooms(&self, protocol: u16) -> impl Iterator<Item = RoomId> + '_ {
       
   466         self.filter_rooms(move |(_, r)| r.protocol_number == protocol)
       
   467     }
       
   468 
       
   469     pub fn other_clients_in_room(&self, self_id: ClientId) -> Vec<ClientId> {
       
   470         let room_id = self.clients[self_id].room_id;
       
   471         self.collect_clients(|(id, c)| *id != self_id && c.room_id == room_id)
       
   472     }
       
   473 
       
   474     pub fn is_registered_only(&self) -> bool {
       
   475         self.flags.contains(ServerFlags::REGISTERED_ONLY)
       
   476     }
       
   477 
       
   478     pub fn set_is_registered_only(&mut self, value: bool) {
       
   479         self.flags.set(ServerFlags::REGISTERED_ONLY, value)
       
   480     }
       
   481 }
       
   482 
       
   483 pub struct HwRoomControl<'a> {
       
   484     server: &'a mut HwServer,
       
   485     client_id: ClientId,
       
   486     room_id: RoomId,
       
   487 }
       
   488 
       
   489 impl<'a> HwRoomControl<'a> {
       
   490     #[inline]
       
   491     pub fn new(server: &'a mut HwServer, client_id: ClientId) -> Option<Self> {
       
   492         if let Some(room_id) = server.clients[client_id].room_id {
       
   493             Some(Self {
       
   494                 server,
       
   495                 client_id,
       
   496                 room_id,
       
   497             })
       
   498         } else {
       
   499             None
       
   500         }
       
   501     }
       
   502 
       
   503     #[inline]
       
   504     pub fn server(&self) -> &HwServer {
       
   505         self.server
       
   506     }
       
   507 
       
   508     #[inline]
       
   509     pub fn client(&self) -> &HwClient {
       
   510         &self.server.clients[self.client_id]
       
   511     }
       
   512 
       
   513     #[inline]
       
   514     fn client_mut(&mut self) -> &mut HwClient {
       
   515         &mut self.server.clients[self.client_id]
       
   516     }
       
   517 
       
   518     #[inline]
       
   519     pub fn room(&self) -> &HwRoom {
       
   520         &self.server.rooms[self.room_id]
       
   521     }
       
   522 
       
   523     #[inline]
       
   524     fn room_mut(&mut self) -> &mut HwRoom {
       
   525         &mut self.server.rooms[self.room_id]
       
   526     }
       
   527 
       
   528     #[inline]
       
   529     pub fn get(&self) -> (&HwClient, &HwRoom) {
       
   530         (self.client(), self.room())
       
   531     }
       
   532 
       
   533     #[inline]
       
   534     fn get_mut(&mut self) -> (&mut HwClient, &mut HwRoom) {
       
   535         (
       
   536             &mut self.server.clients[self.client_id],
       
   537             &mut self.server.rooms[self.room_id],
       
   538         )
       
   539     }
       
   540 
       
   541     pub fn leave_room(&mut self) -> LeaveRoomResult {
       
   542         let (client, room) = self.get_mut();
       
   543         room.players_number -= 1;
       
   544         client.room_id = None;
       
   545 
       
   546         let is_empty = room.players_number == 0;
       
   547         let is_fixed = room.is_fixed();
       
   548         let was_master = room.master_id == Some(client.id);
       
   549         let was_in_game = client.is_in_game();
       
   550         let mut removed_teams = vec![];
       
   551 
       
   552         if is_empty && !is_fixed {
       
   553             if client.is_ready() && room.ready_players_number > 0 {
       
   554                 room.ready_players_number -= 1;
       
   555             }
       
   556 
       
   557             removed_teams = room
       
   558                 .client_teams(client.id)
       
   559                 .map(|t| t.name.clone())
       
   560                 .collect();
       
   561 
       
   562             for team_name in &removed_teams {
       
   563                 room.remove_team(team_name);
       
   564             }
       
   565 
       
   566             if client.is_master() && !is_fixed {
       
   567                 client.set_is_master(false);
       
   568                 room.master_id = None;
       
   569             }
       
   570         }
       
   571 
       
   572         client.set_is_ready(false);
       
   573         client.set_is_in_game(false);
       
   574 
       
   575         if !is_fixed {
       
   576             if room.players_number == 0 {
       
   577                 self.server.rooms.remove(self.room_id);
       
   578             } else if room.master_id == None {
       
   579                 let protocol_number = room.protocol_number;
       
   580                 let new_master_id = self.server.room_clients(self.room_id).next();
       
   581 
       
   582                 if let Some(new_master_id) = new_master_id {
       
   583                     let room = self.room_mut();
       
   584                     room.master_id = Some(new_master_id);
       
   585                     let new_master = &mut self.server.clients[new_master_id];
       
   586                     new_master.set_is_master(true);
       
   587 
       
   588                     if protocol_number < 42 {
       
   589                         todo!();
       
   590                         let nick = new_master.nick.clone();
       
   591                         self.room_mut().name = nick;
       
   592                     }
       
   593 
       
   594                     let room = self.room_mut();
       
   595                     room.set_join_restriction(false);
       
   596                     room.set_team_add_restriction(false);
       
   597                     room.set_unregistered_players_restriction(true);
   333                 }
   598                 }
   334 
   599             }
   335                 removed_teams = room
   600         }
   336                     .client_teams(client.id)
   601 
   337                     .map(|t| t.name.clone())
   602         if is_empty && !is_fixed {
   338                     .collect();
   603             LeaveRoomResult::RoomRemoved
   339 
   604         } else {
   340                 for team_name in &removed_teams {
   605             LeaveRoomResult::RoomRemains {
   341                     room.remove_team(team_name);
   606                 is_empty,
   342                 }
   607                 was_master,
   343 
   608                 was_in_game,
   344                 if client.is_master() && !is_fixed {
   609                 new_master: self.room().master_id,
   345                     client.set_is_master(false);
   610                 removed_teams,
   346                     room.master_id = None;
   611             }
   347                 }
       
   348             }
       
   349 
       
   350             client.set_is_ready(false);
       
   351             client.set_is_in_game(false);
       
   352 
       
   353             if !is_fixed {
       
   354                 if room.players_number == 0 {
       
   355                     self.rooms.remove(room_id);
       
   356                 } else if room.master_id == None {
       
   357                     let new_master_id = self.room_clients(room_id).next();
       
   358                     if let Some(new_master_id) = new_master_id {
       
   359                         let room = &mut self.rooms[room_id];
       
   360                         room.master_id = Some(new_master_id);
       
   361                         let new_master = &mut self.clients[new_master_id];
       
   362                         new_master.set_is_master(true);
       
   363 
       
   364                         if room.protocol_number < 42 {
       
   365                             room.name = new_master.nick.clone();
       
   366                         }
       
   367 
       
   368                         room.set_join_restriction(false);
       
   369                         room.set_team_add_restriction(false);
       
   370                         room.set_unregistered_players_restriction(true);
       
   371                     }
       
   372                 }
       
   373             }
       
   374 
       
   375             if is_empty && !is_fixed {
       
   376                 Ok(LeaveRoomResult::RoomRemoved)
       
   377             } else {
       
   378                 Ok(LeaveRoomResult::RoomRemains {
       
   379                     is_empty,
       
   380                     was_master,
       
   381                     was_in_game,
       
   382                     new_master: self.rooms[room_id].master_id,
       
   383                     removed_teams,
       
   384                 })
       
   385             }
       
   386         } else {
       
   387             Err(LeaveRoomError::NoRoom)
       
   388         }
   612         }
   389     }
   613     }
   390 
   614 
   391     pub fn change_master(
   615     pub fn change_master(
   392         &mut self,
   616         &mut self,
   393         client_id: ClientId,
       
   394         room_id: RoomId,
       
   395         new_master_nick: String,
   617         new_master_nick: String,
   396     ) -> Result<ChangeMasterResult, ChangeMasterError> {
   618     ) -> Result<ChangeMasterResult, ChangeMasterError> {
   397         let client = &mut self.clients[client_id];
   619         use ChangeMasterError::*;
   398         let room = &mut self.rooms[room_id];
   620         let (client, room) = self.get_mut();
   399 
   621 
   400         if client.is_admin() || room.master_id == Some(client_id) {
   622         if client.is_admin() || room.master_id == Some(client.id) {
   401             let new_master_id = self
   623             let new_master_id = self
       
   624                 .server
   402                 .clients
   625                 .clients
   403                 .iter()
   626                 .iter()
   404                 .find(|(_, c)| c.nick == new_master_nick)
   627                 .find(|(_, c)| c.nick == new_master_nick)
   405                 .map(|(id, _)| id);
   628                 .map(|(id, _)| id);
   406 
   629 
   407             match new_master_id {
   630             match new_master_id {
   408                 Some(new_master_id) if new_master_id == client_id => {
   631                 Some(new_master_id) if new_master_id == self.client_id => Err(AlreadyMaster),
   409                     Err(ChangeMasterError::AlreadyMaster)
       
   410                 }
       
   411                 Some(new_master_id) => {
   632                 Some(new_master_id) => {
   412                     let new_master = &mut self.clients[new_master_id];
   633                     let new_master = &mut self.server.clients[new_master_id];
   413                     if new_master.room_id == Some(room_id) {
   634                     if new_master.room_id == Some(self.room_id) {
   414                         self.clients[new_master_id].set_is_master(true);
   635                         self.server.clients[new_master_id].set_is_master(true);
   415                         let old_master_id = room.master_id;
   636                         let room = self.room_mut();
       
   637                         let old_master_id = self.room().master_id;
       
   638 
   416                         if let Some(master_id) = old_master_id {
   639                         if let Some(master_id) = old_master_id {
   417                             self.clients[master_id].set_is_master(false);
   640                             self.server.clients[master_id].set_is_master(false);
   418                         }
   641                         }
   419                         room.master_id = Some(new_master_id);
   642                         self.room_mut().master_id = Some(new_master_id);
   420                         Ok(ChangeMasterResult {
   643                         Ok(ChangeMasterResult {
   421                             old_master_id,
   644                             old_master_id,
   422                             new_master_id,
   645                             new_master_id,
   423                         })
   646                         })
   424                     } else {
   647                     } else {
   425                         Err(ChangeMasterError::ClientNotInRoom)
   648                         Err(ClientNotInRoom)
   426                     }
   649                     }
   427                 }
   650                 }
   428                 None => Err(ChangeMasterError::NoClient),
   651                 None => Err(NoClient),
   429             }
   652             }
   430         } else {
   653         } else {
   431             Err(ChangeMasterError::NoAccess)
   654             Err(NoAccess)
   432         }
   655         }
   433     }
   656     }
   434 
   657 
   435     pub fn start_game(&mut self, room_id: RoomId) -> Result<Vec<String>, StartGameError> {
   658     pub fn vote(&mut self) {
       
   659         todo!("port from the room handler")
       
   660     }
       
   661 
       
   662     pub fn add_engine_message(&mut self) {
       
   663         todo!("port from the room handler")
       
   664     }
       
   665 
       
   666     pub fn toggle_flag(&mut self, flags: super::room::RoomFlags) -> bool {
       
   667         let (client, room) = self.get_mut();
       
   668         if client.is_master() {
       
   669             room.flags.toggle(flags);
       
   670         }
       
   671         client.is_master()
       
   672     }
       
   673 
       
   674     pub fn fix_room(&mut self) -> Result<(), AccessError> {
       
   675         let (client, room) = self.get_mut();
       
   676         if client.is_admin() {
       
   677             room.set_is_fixed(true);
       
   678             room.set_join_restriction(false);
       
   679             room.set_team_add_restriction(false);
       
   680             room.set_unregistered_players_restriction(true);
       
   681             Ok(())
       
   682         } else {
       
   683             Err(AccessError())
       
   684         }
       
   685     }
       
   686 
       
   687     pub fn unfix_room(&mut self) -> Result<(), AccessError> {
       
   688         let (client, room) = self.get_mut();
       
   689         if client.is_admin() {
       
   690             room.set_is_fixed(false);
       
   691             Ok(())
       
   692         } else {
       
   693             Err(AccessError())
       
   694         }
       
   695     }
       
   696 
       
   697     pub fn set_room_name(&mut self, mut name: String) -> Result<String, ModifyRoomNameError> {
       
   698         use ModifyRoomNameError::*;
       
   699         let room_exists = self.server.has_room(&name);
       
   700         let (client, room) = self.get_mut();
       
   701         if room.is_fixed() || room.master_id != Some(client.id) {
       
   702             Err(AccessDenied)
       
   703         } else if utils::is_name_illegal(&name) {
       
   704             Err(InvalidName)
       
   705         } else if room_exists {
       
   706             Err(DuplicateName)
       
   707         } else {
       
   708             std::mem::swap(&mut room.name, &mut name);
       
   709             Ok(name)
       
   710         }
       
   711     }
       
   712 
       
   713     pub fn set_room_greeting(&mut self, greeting: Option<String>) -> Result<(), AccessError> {
       
   714         let (client, room) = self.get_mut();
       
   715         if client.is_admin() {
       
   716             room.greeting = greeting.unwrap_or(String::new());
       
   717             Ok(())
       
   718         } else {
       
   719             Err(AccessError())
       
   720         }
       
   721     }
       
   722 
       
   723     pub fn set_room_max_teams(&mut self, count: u8) -> Result<(), SetTeamCountError> {
       
   724         use SetTeamCountError::*;
       
   725         let (client, room) = self.get_mut();
       
   726         if !client.is_master() {
       
   727             Err(NotMaster)
       
   728         } else if !(2..=super::room::MAX_TEAMS_IN_ROOM).contains(&count) {
       
   729             Err(InvalidNumber)
       
   730         } else {
       
   731             room.max_teams = count;
       
   732             Ok(())
       
   733         }
       
   734     }
       
   735 
       
   736     pub fn set_team_hedgehogs_number(
       
   737         &mut self,
       
   738         team_name: &str,
       
   739         number: u8,
       
   740     ) -> Result<(), SetHedgehogsError> {
       
   741         use SetHedgehogsError::*;
       
   742         let (client, room) = self.get_mut();
       
   743         let addable_hedgehogs = room.addable_hedgehogs();
       
   744         if let Some((_, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) {
       
   745             let max_hedgehogs = min(
       
   746                 super::room::MAX_HEDGEHOGS_IN_ROOM,
       
   747                 addable_hedgehogs + team.hedgehogs_number,
       
   748             );
       
   749             if !client.is_master() {
       
   750                 Err(NotMaster)
       
   751             } else if !(1..=max_hedgehogs).contains(&number) {
       
   752                 Err(InvalidNumber(team.hedgehogs_number))
       
   753             } else {
       
   754                 team.hedgehogs_number = number;
       
   755                 Ok(())
       
   756             }
       
   757         } else {
       
   758             Err(NoTeam)
       
   759         }
       
   760     }
       
   761 
       
   762     pub fn add_team(&mut self, mut info: Box<TeamInfo>) -> Result<&TeamInfo, AddTeamError> {
       
   763         use AddTeamError::*;
       
   764         let (client, room) = self.get_mut();
       
   765         if room.teams.len() >= room.max_teams as usize {
       
   766             Err(TooManyTeams)
       
   767         } else if room.addable_hedgehogs() == 0 {
       
   768             Err(TooManyHedgehogs)
       
   769         } else if room.find_team(|t| t.name == info.name) != None {
       
   770             Err(TeamAlreadyExists)
       
   771         } else if room.game_info.is_some() {
       
   772             Err(GameInProgress)
       
   773         } else if room.is_team_add_restricted() {
       
   774             Err(Restricted)
       
   775         } else {
       
   776             info.owner = client.nick.clone();
       
   777             let team = room.add_team(client.id, *info, client.protocol_number < 42);
       
   778             client.teams_in_game += 1;
       
   779             client.clan = Some(team.color);
       
   780             Ok(team)
       
   781         }
       
   782     }
       
   783 
       
   784     pub fn remove_team(&mut self, team_name: &str) -> Result<(), RemoveTeamError> {
       
   785         use RemoveTeamError::*;
       
   786         let (client, room) = self.get_mut();
       
   787         match room.find_team_owner(team_name) {
       
   788             None => Err(NoTeam),
       
   789             Some((id, _)) if id != client.id => Err(RemoveTeamError::TeamNotOwned),
       
   790             Some(_) => {
       
   791                 client.teams_in_game -= 1;
       
   792                 client.clan = room.find_team_color(client.id);
       
   793                 room.remove_team(team_name);
       
   794                 Ok(())
       
   795             }
       
   796         }
       
   797     }
       
   798 
       
   799     pub fn set_team_color(&mut self, team_name: &str, color: u8) -> Result<(), ModifyTeamError> {
       
   800         use ModifyTeamError::*;
       
   801         let (client, room) = self.get_mut();
       
   802         if let Some((owner, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) {
       
   803             if !client.is_master() {
       
   804                 Err(NotMaster)
       
   805             } else {
       
   806                 team.color = color;
       
   807                 self.server.clients[owner].clan = Some(color);
       
   808                 Ok(())
       
   809             }
       
   810         } else {
       
   811             Err(NoTeam)
       
   812         }
       
   813     }
       
   814 
       
   815     pub fn set_config(&mut self, cfg: GameCfg) -> Result<(), SetConfigError> {
       
   816         use SetConfigError::*;
       
   817         let (client, room) = self.get_mut();
       
   818         if room.is_fixed() {
       
   819             Err(RoomFixed)
       
   820         } else if !client.is_master() {
       
   821             Err(NotMaster)
       
   822         } else {
       
   823             let cfg = match cfg {
       
   824                 GameCfg::Scheme(name, mut values) => {
       
   825                     if client.protocol_number == 49 && values.len() >= 2 {
       
   826                         let mut s = "X".repeat(50);
       
   827                         s.push_str(&values.pop().unwrap());
       
   828                         values.push(s);
       
   829                     }
       
   830                     GameCfg::Scheme(name, values)
       
   831                 }
       
   832                 cfg => cfg,
       
   833             };
       
   834 
       
   835             room.set_config(cfg);
       
   836             Ok(())
       
   837         }
       
   838     }
       
   839 
       
   840     pub fn save_config(&mut self, name: String, location: String) {
       
   841         self.room_mut().save_config(name, location);
       
   842     }
       
   843 
       
   844     pub fn delete_config(&mut self, name: &str) -> bool {
       
   845         self.room_mut().delete_config(name)
       
   846     }
       
   847 
       
   848     pub fn toggle_ready(&mut self) -> bool {
       
   849         let (client, room) = self.get_mut();
       
   850         client.set_is_ready(!client.is_ready());
       
   851         if client.is_ready() {
       
   852             room.ready_players_number += 1;
       
   853         } else {
       
   854             room.ready_players_number -= 1;
       
   855         }
       
   856         client.is_ready()
       
   857     }
       
   858 
       
   859     pub fn start_game(&mut self) -> Result<Vec<String>, StartGameError> {
       
   860         use StartGameError::*;
   436         let (room_clients, room_nicks): (Vec<_>, Vec<_>) = self
   861         let (room_clients, room_nicks): (Vec<_>, Vec<_>) = self
       
   862             .server
   437             .clients
   863             .clients
   438             .iter()
   864             .iter()
   439             .map(|(id, c)| (id, c.nick.clone()))
   865             .map(|(id, c)| (id, c.nick.clone()))
   440             .unzip();
   866             .unzip();
   441 
   867 
   442         let room = &mut self.rooms[room_id];
   868         let room = self.room_mut();
   443 
   869 
   444         if !room.has_multiple_clans() {
   870         if !room.has_multiple_clans() {
   445             Err(StartGameError::NotEnoughClans)
   871             Err(NotEnoughClans)
   446         } else if room.protocol_number <= 43 && room.players_number != room.ready_players_number {
   872         } else if room.protocol_number <= 43 && room.players_number != room.ready_players_number {
   447             Err(StartGameError::NotReady)
   873             Err(NotReady)
   448         } else if room.game_info.is_some() {
   874         } else if room.game_info.is_some() {
   449             Err(StartGameError::AlreadyInGame)
   875             Err(AlreadyInGame)
   450         } else {
   876         } else {
   451             room.start_round();
   877             room.start_round();
   452             for id in room_clients {
   878             for id in room_clients {
   453                 let c = &mut self.clients[id];
   879                 let team_indices = self.room().client_team_indices(id);
       
   880                 let c = &mut self.server.clients[id];
   454                 c.set_is_in_game(true);
   881                 c.set_is_in_game(true);
   455                 c.team_indices = room.client_team_indices(c.id);
   882                 c.team_indices = team_indices;
   456             }
   883             }
   457             Ok(room_nicks)
   884             Ok(room_nicks)
   458         }
   885         }
   459     }
   886     }
   460 
   887 
   461     pub fn leave_game(&mut self, client_id: ClientId) -> Option<Vec<String>> {
   888     pub fn leave_game(&mut self) -> Option<Vec<String>> {
   462         let client = &mut self.clients[client_id];
   889         let (client, room) = self.get_mut();
   463         let client_left = client.is_in_game();
   890         let client_left = client.is_in_game();
   464         if client_left {
   891         if client_left {
   465             client.set_is_in_game(false);
   892             client.set_is_in_game(false);
   466             let room = &mut self.rooms[client.room_id.expect("Client should've been in the game")];
       
   467 
   893 
   468             let team_names: Vec<_> = room
   894             let team_names: Vec<_> = room
   469                 .client_teams(client_id)
   895                 .client_teams(client.id)
   470                 .map(|t| t.name.clone())
   896                 .map(|t| t.name.clone())
   471                 .collect();
   897                 .collect();
   472 
   898 
   473             if let Some(ref mut info) = room.game_info {
   899             if let Some(ref mut info) = room.game_info {
   474                 info.teams_in_game -= team_names.len() as u8;
   900                 info.teams_in_game -= team_names.len() as u8;
   491         } else {
   917         } else {
   492             None
   918             None
   493         }
   919         }
   494     }
   920     }
   495 
   921 
   496     pub fn end_game(&mut self, room_id: RoomId) -> EndGameResult {
   922     pub fn end_game(&mut self) -> Option<EndGameResult> {
   497         let room = &mut self.rooms[room_id];
   923         let room = self.room_mut();
   498         room.ready_players_number = room.master_id.is_some() as u8;
   924         room.ready_players_number = room.master_id.is_some() as u8;
   499 
   925 
   500         if let Some(info) = replace(&mut room.game_info, None) {
   926         if let Some(info) = replace(&mut room.game_info, None) {
       
   927             let room_id = room.id;
   501             let joined_mid_game_clients = self
   928             let joined_mid_game_clients = self
       
   929                 .server
   502                 .clients
   930                 .clients
   503                 .iter()
   931                 .iter()
   504                 .filter(|(_, c)| c.room_id == Some(room_id) && c.is_joined_mid_game())
   932                 .filter(|(_, c)| c.room_id == Some(self.room_id) && c.is_joined_mid_game())
   505                 .map(|(_, c)| c.id)
   933                 .map(|(_, c)| c.id)
   506                 .collect();
   934                 .collect();
   507 
   935 
   508             let unreadied_nicks: Vec<_> = self
   936             let unreadied_nicks: Vec<_> = self
       
   937                 .server
   509                 .clients
   938                 .clients
   510                 .iter_mut()
   939                 .iter_mut()
   511                 .filter(|(_, c)| c.room_id == Some(room_id))
   940                 .filter(|(_, c)| c.room_id == Some(room_id))
   512                 .map(|(_, c)| {
   941                 .map(|(_, c)| {
   513                     c.set_is_ready(c.is_master());
   942                     c.set_is_ready(c.is_master());
   521                         None
   950                         None
   522                     }
   951                     }
   523                 })
   952                 })
   524                 .collect();
   953                 .collect();
   525 
   954 
   526             EndGameResult {
   955             Some(EndGameResult {
   527                 joined_mid_game_clients,
   956                 joined_mid_game_clients,
   528                 left_teams: info.left_teams.clone(),
   957                 left_teams: info.left_teams.clone(),
   529                 unreadied_nicks,
   958                 unreadied_nicks,
   530             }
   959             })
   531         } else {
   960         } else {
   532             unreachable!()
   961             None
   533         }
   962         }
   534     }
       
   535 
       
   536     pub fn enable_super_power(&mut self, client_id: ClientId) -> bool {
       
   537         let client = &mut self.clients[client_id];
       
   538         if client.is_admin() {
       
   539             client.set_has_super_power(true);
       
   540         }
       
   541         client.is_admin()
       
   542     }
       
   543 
       
   544     pub fn set_room_name(
       
   545         &mut self,
       
   546         client_id: ClientId,
       
   547         room_id: RoomId,
       
   548         mut name: String,
       
   549     ) -> Result<String, ModifyRoomNameError> {
       
   550         let room_exists = self.has_room(&name);
       
   551         let room = &mut self.rooms[room_id];
       
   552         if room.is_fixed() || room.master_id != Some(client_id) {
       
   553             Err(ModifyRoomNameError::AccessDenied)
       
   554         } else if utils::is_name_illegal(&name) {
       
   555             Err(ModifyRoomNameError::InvalidName)
       
   556         } else if room_exists {
       
   557             Err(ModifyRoomNameError::DuplicateName)
       
   558         } else {
       
   559             std::mem::swap(&mut room.name, &mut name);
       
   560             Ok(name)
       
   561         }
       
   562     }
       
   563 
       
   564     pub fn add_team(
       
   565         &mut self,
       
   566         client_id: ClientId,
       
   567         mut info: Box<TeamInfo>,
       
   568     ) -> Result<&TeamInfo, AddTeamError> {
       
   569         let client = &mut self.clients[client_id];
       
   570         if let Some(room_id) = client.room_id {
       
   571             let room = &mut self.rooms[room_id];
       
   572             if room.teams.len() >= room.max_teams as usize {
       
   573                 Err(AddTeamError::TooManyTeams)
       
   574             } else if room.addable_hedgehogs() == 0 {
       
   575                 Err(AddTeamError::TooManyHedgehogs)
       
   576             } else if room.find_team(|t| t.name == info.name) != None {
       
   577                 Err(AddTeamError::TeamAlreadyExists)
       
   578             } else if room.game_info.is_some() {
       
   579                 Err(AddTeamError::GameInProgress)
       
   580             } else if room.is_team_add_restricted() {
       
   581                 Err(AddTeamError::Restricted)
       
   582             } else {
       
   583                 info.owner = client.nick.clone();
       
   584                 let team = room.add_team(client.id, *info, client.protocol_number < 42);
       
   585                 client.teams_in_game += 1;
       
   586                 client.clan = Some(team.color);
       
   587                 Ok(team)
       
   588             }
       
   589         } else {
       
   590             unreachable!()
       
   591         }
       
   592     }
       
   593 
       
   594     pub fn remove_team(
       
   595         &mut self,
       
   596         client_id: ClientId,
       
   597         team_name: &str,
       
   598     ) -> Result<(), RemoveTeamError> {
       
   599         let client = &mut self.clients[client_id];
       
   600         if let Some(room_id) = client.room_id {
       
   601             let room = &mut self.rooms[room_id];
       
   602             match room.find_team_owner(team_name) {
       
   603                 None => Err(RemoveTeamError::NoTeam),
       
   604                 Some((id, _)) if id != client_id => Err(RemoveTeamError::TeamNotOwned),
       
   605                 Some(_) => {
       
   606                     client.teams_in_game -= 1;
       
   607                     client.clan = room.find_team_color(client.id);
       
   608                     room.remove_team(team_name);
       
   609                     Ok(())
       
   610                 }
       
   611             }
       
   612         } else {
       
   613             unreachable!();
       
   614         }
       
   615     }
       
   616 
       
   617     pub fn set_team_color(
       
   618         &mut self,
       
   619         client_id: ClientId,
       
   620         room_id: RoomId,
       
   621         team_name: &str,
       
   622         color: u8,
       
   623     ) -> Result<(), ModifyTeamError> {
       
   624         let client = &self.clients[client_id];
       
   625         let room = &mut self.rooms[room_id];
       
   626         if let Some((owner, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) {
       
   627             if !client.is_master() {
       
   628                 Err(ModifyTeamError::NotMaster)
       
   629             } else {
       
   630                 team.color = color;
       
   631                 self.clients[owner].clan = Some(color);
       
   632                 Ok(())
       
   633             }
       
   634         } else {
       
   635             Err(ModifyTeamError::NoTeam)
       
   636         }
       
   637     }
       
   638 
       
   639     pub fn toggle_ready(&mut self, client_id: ClientId) -> bool {
       
   640         let client = &mut self.clients[client_id];
       
   641         if let Some(room_id) = client.room_id {
       
   642             let room = &mut self.rooms[room_id];
       
   643 
       
   644             client.set_is_ready(!client.is_ready());
       
   645             if client.is_ready() {
       
   646                 room.ready_players_number += 1;
       
   647             } else {
       
   648                 room.ready_players_number -= 1;
       
   649             }
       
   650         }
       
   651         client.is_ready()
       
   652     }
       
   653 
       
   654     #[inline]
       
   655     pub fn set_var(&mut self, client_id: ClientId, var: ServerVar) -> Result<(), AccessError> {
       
   656         if self.clients[client_id].is_admin() {
       
   657             match var {
       
   658                 ServerVar::MOTDNew(msg) => self.greetings.for_latest_protocol = msg,
       
   659                 ServerVar::MOTDOld(msg) => self.greetings.for_old_protocols = msg,
       
   660                 ServerVar::LatestProto(n) => self.latest_protocol = n,
       
   661             }
       
   662             Ok(())
       
   663         } else {
       
   664             Err(AccessError())
       
   665         }
       
   666     }
       
   667 
       
   668     #[inline]
       
   669     pub fn get_vars(&self, client_id: ClientId) -> Result<[ServerVar; 3], AccessError> {
       
   670         if self.clients[client_id].is_admin() {
       
   671             Ok([
       
   672                 ServerVar::MOTDNew(self.greetings.for_latest_protocol.clone()),
       
   673                 ServerVar::MOTDOld(self.greetings.for_old_protocols.clone()),
       
   674                 ServerVar::LatestProto(self.latest_protocol),
       
   675             ])
       
   676         } else {
       
   677             Err(AccessError())
       
   678         }
       
   679     }
       
   680 
       
   681     pub fn get_used_protocols(&self, client_id: ClientId) -> Result<Vec<u16>, AccessError> {
       
   682         if self.clients[client_id].is_admin() {
       
   683             let mut protocols: HashSet<_> = self
       
   684                 .clients
       
   685                 .iter()
       
   686                 .map(|(_, c)| c.protocol_number)
       
   687                 .chain(self.rooms.iter().map(|(_, r)| r.protocol_number))
       
   688                 .collect();
       
   689             let mut protocols: Vec<_> = protocols.drain().collect();
       
   690             protocols.sort();
       
   691             Ok(protocols)
       
   692         } else {
       
   693             Err(AccessError())
       
   694         }
       
   695     }
       
   696 
       
   697     #[inline]
       
   698     pub fn has_room(&self, name: &str) -> bool {
       
   699         self.find_room(name).is_some()
       
   700     }
       
   701 
       
   702     #[inline]
       
   703     pub fn find_room(&self, name: &str) -> Option<&HwRoom> {
       
   704         self.rooms
       
   705             .iter()
       
   706             .find_map(|(_, r)| Some(r).filter(|r| r.name == name))
       
   707     }
       
   708 
       
   709     pub fn find_room_mut(&mut self, name: &str) -> Option<&mut HwRoom> {
       
   710         self.rooms
       
   711             .iter_mut()
       
   712             .find_map(|(_, r)| Some(r).filter(|r| r.name == name))
       
   713     }
       
   714 
       
   715     pub fn find_client(&self, nick: &str) -> Option<&HwClient> {
       
   716         self.clients
       
   717             .iter()
       
   718             .find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
       
   719     }
       
   720 
       
   721     pub fn find_client_mut(&mut self, nick: &str) -> Option<&mut HwClient> {
       
   722         self.clients
       
   723             .iter_mut()
       
   724             .find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
       
   725     }
       
   726 
       
   727     pub fn all_clients(&self) -> impl Iterator<Item = ClientId> + '_ {
       
   728         self.clients.iter().map(|(id, _)| id)
       
   729     }
       
   730 
       
   731     pub fn filter_clients<'a, F>(&'a self, f: F) -> impl Iterator<Item = ClientId> + 'a
       
   732     where
       
   733         F: Fn(&(usize, &HwClient)) -> bool + 'a,
       
   734     {
       
   735         self.clients.iter().filter(f).map(|(_, c)| c.id)
       
   736     }
       
   737 
       
   738     pub fn filter_rooms<'a, F>(&'a self, f: F) -> impl Iterator<Item = RoomId> + 'a
       
   739     where
       
   740         F: Fn(&(usize, &HwRoom)) -> bool + 'a,
       
   741     {
       
   742         self.rooms.iter().filter(f).map(|(_, c)| c.id)
       
   743     }
       
   744 
       
   745     pub fn collect_clients<F>(&self, f: F) -> Vec<ClientId>
       
   746     where
       
   747         F: Fn(&(usize, &HwClient)) -> bool,
       
   748     {
       
   749         self.filter_clients(f).collect()
       
   750     }
       
   751 
       
   752     pub fn collect_nicks<F>(&self, f: F) -> Vec<String>
       
   753     where
       
   754         F: Fn(&(usize, &HwClient)) -> bool,
       
   755     {
       
   756         self.clients
       
   757             .iter()
       
   758             .filter(f)
       
   759             .map(|(_, c)| c.nick.clone())
       
   760             .collect()
       
   761     }
       
   762 
       
   763     pub fn lobby_clients(&self) -> impl Iterator<Item = ClientId> + '_ {
       
   764         self.filter_clients(|(_, c)| c.room_id == None)
       
   765     }
       
   766 
       
   767     pub fn room_clients(&self, room_id: RoomId) -> impl Iterator<Item = ClientId> + '_ {
       
   768         self.filter_clients(move |(_, c)| c.room_id == Some(room_id))
       
   769     }
       
   770 
       
   771     pub fn protocol_clients(&self, protocol: u16) -> impl Iterator<Item = ClientId> + '_ {
       
   772         self.filter_clients(move |(_, c)| c.protocol_number == protocol)
       
   773     }
       
   774 
       
   775     pub fn protocol_rooms(&self, protocol: u16) -> impl Iterator<Item = RoomId> + '_ {
       
   776         self.filter_rooms(move |(_, r)| r.protocol_number == protocol)
       
   777     }
       
   778 
       
   779     pub fn other_clients_in_room(&self, self_id: ClientId) -> Vec<ClientId> {
       
   780         let room_id = self.clients[self_id].room_id;
       
   781         self.collect_clients(|(id, c)| *id != self_id && c.room_id == room_id)
       
   782     }
       
   783 
       
   784     pub fn is_registered_only(&self) -> bool {
       
   785         self.flags.contains(ServerFlags::REGISTERED_ONLY)
       
   786     }
       
   787 
       
   788     pub fn set_is_registered_only(&mut self, value: bool) {
       
   789         self.flags.set(ServerFlags::REGISTERED_ONLY, value)
       
   790     }
   963     }
   791 }
   964 }
   792 
   965 
   793 fn allocate_room(rooms: &mut Slab<HwRoom>) -> &mut HwRoom {
   966 fn allocate_room(rooms: &mut Slab<HwRoom>) -> &mut HwRoom {
   794     let entry = rooms.vacant_entry();
   967     let entry = rooms.vacant_entry();