rust/hedgewars-server/src/core/server.rs
changeset 15487 91f0c5ec37b5
parent 15482 4cc9ec732392
child 15492 395be40faa51
--- a/rust/hedgewars-server/src/core/server.rs	Sat Oct 26 23:48:57 2019 +0200
+++ b/rust/hedgewars-server/src/core/server.rs	Mon Oct 28 00:31:41 2019 +0300
@@ -45,6 +45,20 @@
 }
 
 #[derive(Debug)]
+pub struct ChangeMasterResult {
+    pub old_master_id: Option<ClientId>,
+    pub new_master_id: ClientId,
+}
+
+#[derive(Debug)]
+pub enum ChangeMasterError {
+    NoAccess,
+    AlreadyMaster,
+    NoClient,
+    ClientNotInRoom,
+}
+
+#[derive(Debug)]
 pub struct UninitializedError();
 #[derive(Debug)]
 pub struct AccessError();
@@ -349,6 +363,50 @@
         }
     }
 
+    pub fn change_master(
+        &mut self,
+        client_id: ClientId,
+        room_id: RoomId,
+        new_master_nick: String,
+    ) -> Result<ChangeMasterResult, ChangeMasterError> {
+        let client = &mut self.clients[client_id];
+        let room = &mut self.rooms[room_id];
+
+        if client.is_admin() || room.master_id == Some(client_id) {
+            let new_master_id = self
+                .clients
+                .iter()
+                .find(|(_, c)| c.nick == new_master_nick)
+                .map(|(id, _)| id);
+
+            match new_master_id {
+                Some(new_master_id) if new_master_id == client_id => {
+                    Err(ChangeMasterError::AlreadyMaster)
+                }
+                Some(new_master_id) => {
+                    let new_master = &mut self.clients[new_master_id];
+                    if new_master.room_id == Some(room_id) {
+                        self.clients[new_master_id].set_is_master(true);
+                        let old_master_id = room.master_id;
+                        if let Some(master_id) = old_master_id {
+                            self.clients[master_id].set_is_master(false);
+                        }
+                        room.master_id = Some(new_master_id);
+                        Ok(ChangeMasterResult {
+                            old_master_id,
+                            new_master_id,
+                        })
+                    } else {
+                        Err(ChangeMasterError::ClientNotInRoom)
+                    }
+                }
+                None => Err(ChangeMasterError::NoClient),
+            }
+        } else {
+            Err(ChangeMasterError::NoAccess)
+        }
+    }
+
     #[inline]
     pub fn set_var(&mut self, client_id: ClientId, var: ServerVar) -> Result<(), AccessError> {
         if self.clients[client_id].is_admin() {