rust/hedgewars-server/src/core/server.rs
changeset 15519 b3157d218ae2
parent 15518 e705d30e0f10
child 15520 fd3a20e9d095
equal deleted inserted replaced
15518:e705d30e0f10 15519:b3157d218ae2
     1 use super::{
     1 use super::{
     2     client::HwClient,
     2     client::HwClient,
     3     indexslab::IndexSlab,
     3     indexslab::IndexSlab,
     4     room::HwRoom,
     4     room::HwRoom,
     5     types::{ClientId, RoomId, ServerVar},
     5     types::{ClientId, RoomId, ServerVar, TeamInfo},
     6 };
     6 };
     7 use crate::{protocol::messages::HwProtocolMessage::Greeting, utils};
     7 use crate::{protocol::messages::HwProtocolMessage::Greeting, utils};
     8 
     8 
       
     9 use bitflags::_core::hint::unreachable_unchecked;
     9 use bitflags::*;
    10 use bitflags::*;
    10 use chrono::{offset, DateTime};
    11 use chrono::{offset, DateTime};
    11 use log::*;
    12 use log::*;
    12 use slab::Slab;
    13 use slab::Slab;
    13 use std::{borrow::BorrowMut, collections::HashSet, iter, mem::replace, num::NonZeroU16};
    14 use std::{borrow::BorrowMut, collections::HashSet, iter, mem::replace, num::NonZeroU16};
    53 pub enum ChangeMasterError {
    54 pub enum ChangeMasterError {
    54     NoAccess,
    55     NoAccess,
    55     AlreadyMaster,
    56     AlreadyMaster,
    56     NoClient,
    57     NoClient,
    57     ClientNotInRoom,
    58     ClientNotInRoom,
       
    59 }
       
    60 
       
    61 #[derive(Debug)]
       
    62 pub enum AddTeamError {
       
    63     TooManyTeams,
       
    64     TooManyHedgehogs,
       
    65     TeamAlreadyExists,
       
    66     GameInProgress,
       
    67     Restricted,
       
    68 }
       
    69 
       
    70 #[derive(Debug)]
       
    71 pub enum RemoveTeamError {
       
    72     NoTeam,
       
    73     TeamNotOwned,
    58 }
    74 }
    59 
    75 
    60 #[derive(Debug)]
    76 #[derive(Debug)]
    61 pub enum ModifyTeamError {
    77 pub enum ModifyTeamError {
    62     NoTeam,
    78     NoTeam,
   227     fn client_mut(&mut self, client_id: ClientId) -> &mut HwClient {
   243     fn client_mut(&mut self, client_id: ClientId) -> &mut HwClient {
   228         &mut self.clients[client_id]
   244         &mut self.clients[client_id]
   229     }
   245     }
   230 
   246 
   231     #[inline]
   247     #[inline]
       
   248     pub fn has_client(&self, client_id: ClientId) -> bool {
       
   249         self.clients.contains(client_id)
       
   250     }
       
   251 
       
   252     #[inline]
       
   253     pub fn iter_clients(&self) -> impl Iterator<Item = &HwClient> {
       
   254         self.clients.iter().map(|(_, c)| c)
       
   255     }
       
   256 
       
   257     #[inline]
   232     pub fn room(&self, room_id: RoomId) -> &HwRoom {
   258     pub fn room(&self, room_id: RoomId) -> &HwRoom {
   233         &self.rooms[room_id]
   259         &self.rooms[room_id]
   234     }
   260     }
   235 
   261 
   236     #[inline]
   262     #[inline]
   246     #[inline]
   272     #[inline]
   247     pub fn client_and_room_mut(
   273     pub fn client_and_room_mut(
   248         &mut self,
   274         &mut self,
   249         client_id: ClientId,
   275         client_id: ClientId,
   250         room_id: RoomId,
   276         room_id: RoomId,
   251     ) -> (&mut HwClient, &mut HwRoom) {
   277     ) -> (&HwClient, &mut HwRoom) {
   252         (&mut self.clients[client_id], &mut self.rooms[room_id])
   278         (&self.clients[client_id], &mut self.rooms[room_id])
   253     }
   279     }
   254 
   280 
   255     #[inline]
   281     #[inline]
   256     pub fn is_admin(&self, client_id: ClientId) -> bool {
   282     pub fn is_admin(&self, client_id: ClientId) -> bool {
   257         self.clients
   283         self.clients
   502             }
   528             }
   503             Ok(room_nicks)
   529             Ok(room_nicks)
   504         }
   530         }
   505     }
   531     }
   506 
   532 
       
   533     pub fn leave_game(&mut self, client_id: ClientId) -> Option<Vec<String>> {
       
   534         let client = &mut self.clients[client_id];
       
   535         let client_left = client.is_in_game();
       
   536         if client_left {
       
   537             client.set_is_in_game(false);
       
   538             let room = &mut self.rooms[client.room_id.expect("Client should've been in the game")];
       
   539 
       
   540             let team_names: Vec<_> = room
       
   541                 .client_teams(client_id)
       
   542                 .map(|t| t.name.clone())
       
   543                 .collect();
       
   544 
       
   545             if let Some(ref mut info) = room.game_info {
       
   546                 info.teams_in_game -= team_names.len() as u8;
       
   547 
       
   548                 for team_name in &team_names {
       
   549                     let remove_msg =
       
   550                         utils::to_engine_msg(std::iter::once(b'F').chain(team_name.bytes()));
       
   551                     if let Some(m) = &info.sync_msg {
       
   552                         info.msg_log.push(m.clone());
       
   553                     }
       
   554                     if info.sync_msg.is_some() {
       
   555                         info.sync_msg = None
       
   556                     }
       
   557                     info.msg_log.push(remove_msg);
       
   558                 }
       
   559                 Some(team_names)
       
   560             } else {
       
   561                 unreachable!();
       
   562             }
       
   563         } else {
       
   564             None
       
   565         }
       
   566     }
       
   567 
   507     pub fn end_game(&mut self, room_id: RoomId) -> EndGameResult {
   568     pub fn end_game(&mut self, room_id: RoomId) -> EndGameResult {
   508         let room = &mut self.rooms[room_id];
   569         let room = &mut self.rooms[room_id];
   509         room.ready_players_number = 1;
   570         room.ready_players_number = room.master_id.is_some() as u8;
   510 
   571 
   511         if let Some(info) = replace(&mut room.game_info, None) {
   572         if let Some(info) = replace(&mut room.game_info, None) {
   512             let joined_mid_game_clients = self
   573             let joined_mid_game_clients = self
   513                 .clients
   574                 .clients
   514                 .iter()
   575                 .iter()
   570             std::mem::swap(&mut room.name, &mut name);
   631             std::mem::swap(&mut room.name, &mut name);
   571             Ok(name)
   632             Ok(name)
   572         }
   633         }
   573     }
   634     }
   574 
   635 
   575     pub fn add_team(&mut self, client_id: ClientId) {}
   636     pub fn add_team(
       
   637         &mut self,
       
   638         client_id: ClientId,
       
   639         mut info: Box<TeamInfo>,
       
   640     ) -> Result<&TeamInfo, AddTeamError> {
       
   641         let client = &mut self.clients[client_id];
       
   642         if let Some(room_id) = client.room_id {
       
   643             let room = &mut self.rooms[room_id];
       
   644             if room.teams.len() >= room.max_teams as usize {
       
   645                 Err(AddTeamError::TooManyTeams)
       
   646             } else if room.addable_hedgehogs() == 0 {
       
   647                 Err(AddTeamError::TooManyHedgehogs)
       
   648             } else if room.find_team(|t| t.name == info.name) != None {
       
   649                 Err(AddTeamError::TeamAlreadyExists)
       
   650             } else if room.game_info.is_some() {
       
   651                 Err(AddTeamError::GameInProgress)
       
   652             } else if room.is_team_add_restricted() {
       
   653                 Err(AddTeamError::Restricted)
       
   654             } else {
       
   655                 info.owner = client.nick.clone();
       
   656                 let team = room.add_team(client.id, *info, client.protocol_number < 42);
       
   657                 client.teams_in_game += 1;
       
   658                 client.clan = Some(team.color);
       
   659                 Ok(team)
       
   660             }
       
   661         } else {
       
   662             unreachable!()
       
   663         }
       
   664     }
       
   665 
       
   666     pub fn remove_team(
       
   667         &mut self,
       
   668         client_id: ClientId,
       
   669         team_name: &str,
       
   670     ) -> Result<(), RemoveTeamError> {
       
   671         let client = &mut self.clients[client_id];
       
   672         if let Some(room_id) = client.room_id {
       
   673             let room = &mut self.rooms[room_id];
       
   674             match room.find_team_owner(team_name) {
       
   675                 None => Err(RemoveTeamError::NoTeam),
       
   676                 Some((id, _)) if id != client_id => Err(RemoveTeamError::TeamNotOwned),
       
   677                 Some(_) => {
       
   678                     client.teams_in_game -= 1;
       
   679                     client.clan = room.find_team_color(client.id);
       
   680                     room.remove_team(team_name);
       
   681                     Ok(())
       
   682                 }
       
   683             }
       
   684         } else {
       
   685             unreachable!();
       
   686         }
       
   687     }
   576 
   688 
   577     pub fn set_team_color(
   689     pub fn set_team_color(
   578         &mut self,
   690         &mut self,
   579         client_id: ClientId,
   691         client_id: ClientId,
   580         room_id: RoomId,
   692         room_id: RoomId,