rust/hedgewars-server/src/core/server.rs
changeset 15525 16d3c9acd715
parent 15523 f4f6060b536c
child 15526 24f692e791d3
--- a/rust/hedgewars-server/src/core/server.rs	Tue Dec 24 12:46:23 2019 -0500
+++ b/rust/hedgewars-server/src/core/server.rs	Tue Dec 24 20:57:58 2019 +0300
@@ -3,7 +3,7 @@
     client::HwClient,
     indexslab::IndexSlab,
     room::HwRoom,
-    types::{ClientId, GameCfg, RoomId, ServerVar, TeamInfo},
+    types::{ClientId, GameCfg, RoomId, ServerVar, TeamInfo, Vote, VoteType, Voting},
 };
 use crate::{protocol::messages::HwProtocolMessage::Greeting, utils};
 
@@ -101,6 +101,24 @@
 }
 
 #[derive(Debug)]
+pub enum StartVoteError {
+    VotingInProgress,
+}
+
+#[derive(Debug)]
+pub enum VoteResult {
+    Submitted,
+    Succeeded(VoteType),
+    Failed,
+}
+
+#[derive(Debug)]
+pub enum VoteError {
+    NoVoting,
+    AlreadyVoted,
+}
+
+#[derive(Debug)]
 pub enum StartGameError {
     NotEnoughClans,
     NotEnoughTeams,
@@ -167,11 +185,6 @@
     }
 
     #[inline]
-    fn client_mut(&mut self, client_id: ClientId) -> &mut HwClient {
-        &mut self.clients[client_id]
-    }
-
-    #[inline]
     pub fn has_client(&self, client_id: ClientId) -> bool {
         self.clients.contains(client_id)
     }
@@ -187,11 +200,6 @@
     }
 
     #[inline]
-    pub fn room_mut(&mut self, room_id: RoomId) -> &mut HwRoom {
-        &mut self.rooms[room_id]
-    }
-
-    #[inline]
     pub fn get_room(&self, room_id: RoomId) -> Option<&HwRoom> {
         self.rooms.get(room_id)
     }
@@ -538,6 +546,11 @@
         )
     }
 
+    pub fn change_client<'b: 'a>(self, client_id: ClientId) -> Option<HwRoomControl<'a>> {
+        let room_id = self.room_id;
+        HwRoomControl::new(self.server, client_id).filter(|c| c.room_id == room_id)
+    }
+
     pub fn leave_room(&mut self) -> LeaveRoomResult {
         let (client, room) = self.get_mut();
         room.players_number -= 1;
@@ -586,7 +599,6 @@
                     new_master.set_is_master(true);
 
                     if protocol_number < 42 {
-                        todo!();
                         let nick = new_master.nick.clone();
                         self.room_mut().name = nick;
                     }
@@ -655,8 +667,44 @@
         }
     }
 
-    pub fn vote(&mut self) {
-        todo!("port from the room handler")
+    pub fn start_vote(&mut self, kind: VoteType) -> Result<(), StartVoteError> {
+        use StartVoteError::*;
+        match self.room().voting {
+            Some(_) => Err(VotingInProgress),
+            None => {
+                let voting = Voting::new(kind, self.server.room_clients(self.room_id).collect());
+                self.room_mut().voting = Some(voting);
+                Ok(())
+            }
+        }
+    }
+
+    pub fn vote(&mut self, vote: Vote) -> Result<VoteResult, VoteError> {
+        use self::{VoteError::*, VoteResult::*};
+        let client_id = self.client_id;
+        if let Some(ref mut voting) = self.room_mut().voting {
+            if vote.is_forced || voting.votes.iter().all(|(id, _)| client_id != *id) {
+                voting.votes.push((client_id, vote.is_pro));
+                let i = voting.votes.iter();
+                let pro = i.clone().filter(|(_, v)| *v).count();
+                let contra = i.filter(|(_, v)| !*v).count();
+                let success_quota = voting.voters.len() / 2 + 1;
+                if vote.is_forced && vote.is_pro || pro >= success_quota {
+                    let voting = self.room_mut().voting.take().unwrap();
+                    Ok(Succeeded(voting.kind))
+                } else if vote.is_forced && !vote.is_pro
+                    || contra > voting.voters.len() - success_quota
+                {
+                    Ok(Failed)
+                } else {
+                    Ok(Submitted)
+                }
+            } else {
+                Err(AlreadyVoted)
+            }
+        } else {
+            Err(NoVoting)
+        }
     }
 
     pub fn add_engine_message(&mut self) {
@@ -759,6 +807,10 @@
         }
     }
 
+    pub fn set_hedgehogs_number(&mut self, number: u8) -> Vec<String> {
+        self.room_mut().set_hedgehogs_number(number)
+    }
+
     pub fn add_team(&mut self, mut info: Box<TeamInfo>) -> Result<&TeamInfo, AddTeamError> {
         use AddTeamError::*;
         let (client, room) = self.get_mut();
@@ -841,6 +893,10 @@
         self.room_mut().save_config(name, location);
     }
 
+    pub fn load_config(&mut self, name: &str) -> Option<&str> {
+        self.room_mut().load_config(name)
+    }
+
     pub fn delete_config(&mut self, name: &str) -> bool {
         self.room_mut().delete_config(name)
     }
@@ -885,6 +941,13 @@
         }
     }
 
+    pub fn toggle_pause(&mut self) -> bool {
+        if let Some(ref mut info) = self.room_mut().game_info {
+            info.is_paused = !info.is_paused;
+        }
+        self.room_mut().game_info.is_some()
+    }
+
     pub fn leave_game(&mut self) -> Option<Vec<String>> {
         let (client, room) = self.get_mut();
         let client_left = client.is_in_game();