--- 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!"),
}
}