move change_master into the server
authoralfadur
Mon, 28 Oct 2019 00:31:41 +0300
changeset 15492 91f0c5ec37b5
parent 15491 d668fcb9307e
child 15493 04b63bcdb2ab
move change_master into the server
rust/hedgewars-server/src/core/server.rs
rust/hedgewars-server/src/handlers/common.rs
rust/hedgewars-server/src/handlers/inroom.rs
--- 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() {
--- a/rust/hedgewars-server/src/handlers/common.rs	Sat Oct 26 23:48:57 2019 +0200
+++ b/rust/hedgewars-server/src/handlers/common.rs	Mon Oct 28 00:31:41 2019 +0300
@@ -98,38 +98,6 @@
     response.add(rooms_msg.send_self());
 }
 
-pub fn change_master(
-    server: &mut HwServer,
-    room_id: RoomId,
-    new_master_id: ClientId,
-    response: &mut Response,
-) {
-    let room = &mut server.rooms[room_id];
-    if let Some(master_id) = room.master_id {
-        server.clients[master_id].set_is_master(false);
-        response.add(
-            ClientFlags(
-                remove_flags(&[Flags::RoomMaster]),
-                vec![server.clients[master_id].nick.clone()],
-            )
-            .send_all()
-            .in_room(room_id),
-        )
-    }
-
-    room.master_id = Some(new_master_id);
-    server.clients[new_master_id].set_is_master(true);
-
-    response.add(
-        ClientFlags(
-            add_flags(&[Flags::RoomMaster]),
-            vec![server.clients[new_master_id].nick.clone()],
-        )
-        .send_all()
-        .in_room(room_id),
-    );
-}
-
 pub fn get_room_join_data<'a, I: Iterator<Item = &'a HwClient> + Clone>(
     client: &HwClient,
     room: &HwRoom,
--- a/rust/hedgewars-server/src/handlers/inroom.rs	Sat Oct 26 23:48:57 2019 +0200
+++ b/rust/hedgewars-server/src/handlers/inroom.rs	Mon Oct 28 00:31:41 2019 +0300
@@ -2,7 +2,7 @@
 use crate::{
     core::{
         room::{HwRoom, RoomFlags, MAX_TEAMS_IN_ROOM},
-        server::{HwServer, LeaveRoomResult},
+        server::{ChangeMasterError, ChangeMasterResult, HwServer, LeaveRoomResult},
         types,
         types::{ClientId, GameCfg, RoomId, VoteType, Voting, MAX_HEDGEHOGS_PER_TEAM},
     },
@@ -315,7 +315,7 @@
                             .in_room(room_id)
                             .but_self(),
                     );
-                    server.clients[owner].clan = Some(color);
+                    server.client_mut(owner).clan = Some(color);
                 }
             } else {
                 response.warn(NO_TEAM);
@@ -571,32 +571,47 @@
             let mut echo = vec!["/rnd".to_string()];
             echo.extend(v.into_iter());
             let chat_msg = ChatMsg {
-                nick: server.clients[client_id].nick.clone(),
+                nick: server.client(client_id).nick.clone(),
                 msg: echo.join(" "),
             };
             response.add(chat_msg.send_all().in_room(room_id));
             response.add(result.send_all().in_room(room_id));
         }
-        Delegate(nick) => {
-            let delegate_id = server.find_client(&nick).map(|c| (c.id, c.room_id));
-            let client = &server.clients[client_id];
-            if !(client.is_admin() || client.is_master()) {
+        Delegate(nick) => match server.change_master(client_id, room_id, nick) {
+            Ok(ChangeMasterResult {
+                old_master_id,
+                new_master_id,
+            }) => {
+                if let Some(master_id) = old_master_id {
+                    response.add(
+                        ClientFlags(
+                            remove_flags(&[Flags::RoomMaster]),
+                            vec![server.client(master_id).nick.clone()],
+                        )
+                        .send_all()
+                        .in_room(room_id),
+                    );
+                }
+                response.add(
+                    ClientFlags(
+                        add_flags(&[Flags::RoomMaster]),
+                        vec![server.client(new_master_id).nick.clone()],
+                    )
+                    .send_all()
+                    .in_room(room_id),
+                );
+            }
+            Err(ChangeMasterError::NoAccess) => {
                 response.warn("You're not the room master or a server admin!")
-            } else {
-                match delegate_id {
-                    None => response.warn("Player is not online."),
-                    Some((id, _)) if id == client_id => {
-                        response.warn("You're already the room master.")
-                    }
-                    Some((_, id)) if id != Some(room_id) => {
-                        response.warn("The player is not in your room.")
-                    }
-                    Some((id, _)) => {
-                        super::common::change_master(server, room_id, id, response);
-                    }
-                }
+            }
+            Err(ChangeMasterError::AlreadyMaster) => {
+                response.warn("You're already the room master.")
             }
-        }
+            Err(ChangeMasterError::NoClient) => response.warn("Player is not online."),
+            Err(ChangeMasterError::ClientNotInRoom) => {
+                response.warn("The player is not in your room.")
+            }
+        },
         _ => warn!("Unimplemented!"),
     }
 }