rust/hedgewars-server/src/core/server.rs
changeset 15444 a158ff8f84ef
parent 15181 f6115638aa92
child 15446 61a0bd0bb021
equal deleted inserted replaced
15443:e7c059ac6e54 15444:a158ff8f84ef
     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},
     5     types::{ClientId, RoomId, ServerVar},
     6 };
     6 };
     7 use crate::{protocol::messages::HwProtocolMessage::Greeting, utils};
     7 use crate::{protocol::messages::HwProtocolMessage::Greeting, utils};
     8 
     8 
       
     9 use crate::core::server::JoinRoomError::WrongProtocol;
     9 use bitflags::*;
    10 use bitflags::*;
    10 use log::*;
    11 use log::*;
    11 use slab;
    12 use slab;
    12 use std::{borrow::BorrowMut, iter, num::NonZeroU16};
    13 use std::{borrow::BorrowMut, collections::HashSet, iter, num::NonZeroU16};
    13 
    14 
    14 type Slab<T> = slab::Slab<T>;
    15 type Slab<T> = slab::Slab<T>;
       
    16 
       
    17 pub enum CreateRoomError {
       
    18     InvalidName,
       
    19     AlreadyExists,
       
    20 }
       
    21 
       
    22 pub enum JoinRoomError {
       
    23     DoesntExist,
       
    24     WrongProtocol,
       
    25     Full,
       
    26     Restricted,
       
    27 }
       
    28 
       
    29 pub struct AccessError();
    15 
    30 
    16 pub struct HwAnteClient {
    31 pub struct HwAnteClient {
    17     pub nick: Option<String>,
    32     pub nick: Option<String>,
    18     pub protocol_number: Option<NonZeroU16>,
    33     pub protocol_number: Option<NonZeroU16>,
    19     pub server_salt: String,
    34     pub server_salt: String,
    41         };
    56         };
    42         self.clients.insert(client_id, client);
    57         self.clients.insert(client_id, client);
    43     }
    58     }
    44 
    59 
    45     pub fn remove_client(&mut self, client_id: ClientId) -> Option<HwAnteClient> {
    60     pub fn remove_client(&mut self, client_id: ClientId) -> Option<HwAnteClient> {
    46         let mut client = self.clients.remove(client_id);
    61         let client = self.clients.remove(client_id);
    47         client
    62         client
    48     }
    63     }
    49 }
    64 }
    50 
    65 
    51 pub struct ServerGreetings {
    66 pub struct ServerGreetings {
   113             &self.greetings.for_latest_protocol
   128             &self.greetings.for_latest_protocol
   114         }
   129         }
   115     }
   130     }
   116 
   131 
   117     #[inline]
   132     #[inline]
       
   133     pub fn get_client_nick(&self, client_id: ClientId) -> &str {
       
   134         &self.clients[client_id].nick
       
   135     }
       
   136 
       
   137     #[inline]
   118     pub fn create_room(
   138     pub fn create_room(
   119         &mut self,
   139         &mut self,
   120         creator_id: ClientId,
   140         creator_id: ClientId,
   121         name: String,
   141         name: String,
   122         password: Option<String>,
   142         password: Option<String>,
   123     ) -> RoomId {
   143     ) -> Result<(&HwClient, &HwRoom), CreateRoomError> {
   124         create_room(
   144         use CreateRoomError::*;
   125             &mut self.clients[creator_id],
   145         if utils::is_name_illegal(&name) {
   126             &mut self.rooms,
   146             Err(InvalidName)
   127             name,
   147         } else if self.has_room(&name) {
   128             password,
   148             Err(AlreadyExists)
   129         )
   149         } else {
   130     }
   150             Ok(create_room(
   131 
   151                 &mut self.clients[creator_id],
   132     #[inline]
   152                 &mut self.rooms,
   133     pub fn move_to_room(&mut self, client_id: ClientId, room_id: RoomId) {
   153                 name,
   134         move_to_room(&mut self.clients[client_id], &mut self.rooms[room_id])
   154                 password,
   135     }
   155             ))
   136 
   156         }
       
   157     }
       
   158 
       
   159     pub fn join_room(
       
   160         &mut self,
       
   161         client_id: ClientId,
       
   162         room_id: RoomId,
       
   163     ) -> Result<(&HwClient, &HwRoom, impl Iterator<Item = &HwClient> + Clone), JoinRoomError> {
       
   164         use JoinRoomError::*;
       
   165         let room = &mut self.rooms[room_id];
       
   166         let client = &mut self.clients[client_id];
       
   167 
       
   168         if client.protocol_number != room.protocol_number {
       
   169             Err(WrongProtocol)
       
   170         } else if room.is_join_restricted() {
       
   171             Err(Restricted)
       
   172         } else if room.players_number == u8::max_value() {
       
   173             Err(Full)
       
   174         } else {
       
   175             move_to_room(client, room);
       
   176             let room_id = room.id;
       
   177             Ok((
       
   178                 &self.clients[client_id],
       
   179                 &self.rooms[room_id],
       
   180                 self.clients.iter().map(|(_, c)| c),
       
   181             ))
       
   182         }
       
   183     }
       
   184 
       
   185     #[inline]
       
   186     pub fn join_room_by_name(
       
   187         &mut self,
       
   188         client_id: ClientId,
       
   189         room_name: &str,
       
   190     ) -> Result<(&HwClient, &HwRoom, impl Iterator<Item = &HwClient> + Clone), JoinRoomError> {
       
   191         use JoinRoomError::*;
       
   192         let room = self.rooms.iter().find(|(_, r)| r.name == room_name);
       
   193         if let Some((_, room)) = room {
       
   194             let room_id = room.id;
       
   195             self.join_room(client_id, room_id)
       
   196         } else {
       
   197             Err(DoesntExist)
       
   198         }
       
   199     }
       
   200 
       
   201     #[inline]
       
   202     pub fn set_var(&mut self, client_id: ClientId, var: ServerVar) -> Result<(), AccessError> {
       
   203         if self.clients[client_id].is_admin() {
       
   204             match var {
       
   205                 ServerVar::MOTDNew(msg) => self.greetings.for_latest_protocol = msg,
       
   206                 ServerVar::MOTDOld(msg) => self.greetings.for_old_protocols = msg,
       
   207                 ServerVar::LatestProto(n) => self.latest_protocol = n,
       
   208             }
       
   209             Ok(())
       
   210         } else {
       
   211             Err(AccessError())
       
   212         }
       
   213     }
       
   214 
       
   215     #[inline]
       
   216     pub fn get_vars(&self, client_id: ClientId) -> Result<[ServerVar; 3], AccessError> {
       
   217         if self.clients[client_id].is_admin() {
       
   218             Ok([
       
   219                 ServerVar::MOTDNew(self.greetings.for_latest_protocol.clone()),
       
   220                 ServerVar::MOTDOld(self.greetings.for_old_protocols.clone()),
       
   221                 ServerVar::LatestProto(self.latest_protocol),
       
   222             ])
       
   223         } else {
       
   224             Err(AccessError())
       
   225         }
       
   226     }
       
   227 
       
   228     pub fn get_used_protocols(&self, client_id: ClientId) -> Result<Vec<u16>, AccessError> {
       
   229         if self.clients[client_id].is_admin() {
       
   230             let mut protocols: HashSet<_> = self
       
   231                 .clients
       
   232                 .iter()
       
   233                 .map(|(_, c)| c.protocol_number)
       
   234                 .chain(self.rooms.iter().map(|(_, r)| r.protocol_number))
       
   235                 .collect();
       
   236             let mut protocols: Vec<_> = protocols.drain().collect();
       
   237             protocols.sort();
       
   238             Ok(protocols)
       
   239         } else {
       
   240             Err(AccessError())
       
   241         }
       
   242     }
       
   243 
       
   244     #[inline]
   137     pub fn has_room(&self, name: &str) -> bool {
   245     pub fn has_room(&self, name: &str) -> bool {
   138         self.find_room(name).is_some()
   246         self.find_room(name).is_some()
   139     }
   247     }
   140 
   248 
       
   249     #[inline]
   141     pub fn find_room(&self, name: &str) -> Option<&HwRoom> {
   250     pub fn find_room(&self, name: &str) -> Option<&HwRoom> {
   142         self.rooms
   251         self.rooms
   143             .iter()
   252             .iter()
   144             .find_map(|(_, r)| Some(r).filter(|r| r.name == name))
   253             .find_map(|(_, r)| Some(r).filter(|r| r.name == name))
   145     }
   254     }
   232     let entry = rooms.vacant_entry();
   341     let entry = rooms.vacant_entry();
   233     let room = HwRoom::new(entry.key());
   342     let room = HwRoom::new(entry.key());
   234     entry.insert(room)
   343     entry.insert(room)
   235 }
   344 }
   236 
   345 
   237 fn create_room(
   346 fn create_room<'a, 'b>(
   238     client: &mut HwClient,
   347     client: &'a mut HwClient,
   239     rooms: &mut Slab<HwRoom>,
   348     rooms: &'b mut Slab<HwRoom>,
   240     name: String,
   349     name: String,
   241     password: Option<String>,
   350     password: Option<String>,
   242 ) -> RoomId {
   351 ) -> (&'a HwClient, &'b HwRoom) {
   243     let room = allocate_room(rooms);
   352     let room = allocate_room(rooms);
   244 
   353 
   245     room.master_id = Some(client.id);
   354     room.master_id = Some(client.id);
   246     room.name = name;
   355     room.name = name;
   247     room.password = password;
   356     room.password = password;
   253     client.room_id = Some(room.id);
   362     client.room_id = Some(room.id);
   254     client.set_is_master(true);
   363     client.set_is_master(true);
   255     client.set_is_ready(true);
   364     client.set_is_ready(true);
   256     client.set_is_joined_mid_game(false);
   365     client.set_is_joined_mid_game(false);
   257 
   366 
   258     room.id
   367     (client, room)
   259 }
   368 }
   260 
   369 
   261 fn move_to_room(client: &mut HwClient, room: &mut HwRoom) {
   370 fn move_to_room(client: &mut HwClient, room: &mut HwRoom) {
   262     debug_assert!(client.room_id != Some(room.id));
   371     debug_assert!(client.room_id != Some(room.id));
   263 
   372