implement info, registered only & super power messages
authoralfadur
Thu, 11 Apr 2019 01:13:29 +0300
changeset 14786 8ecdb5c6bb2a
parent 14785 a1077e8d26f4
child 14787 0e64acbc3f8b
implement info, registered only & super power messages
rust/hedgewars-server/src/protocol/messages.rs
rust/hedgewars-server/src/server/client.rs
rust/hedgewars-server/src/server/core.rs
rust/hedgewars-server/src/server/handlers.rs
--- a/rust/hedgewars-server/src/protocol/messages.rs	Wed Apr 10 23:56:53 2019 +0300
+++ b/rust/hedgewars-server/src/protocol/messages.rs	Thu Apr 11 01:13:29 2019 +0300
@@ -141,6 +141,7 @@
     ForwardEngineMessage(Vec<String>),
     RoundFinished,
 
+    Info(Vec<String>),
     ServerMessage(String),
     ServerVars(Vec<String>),
     Notice(String),
@@ -389,6 +390,7 @@
             ForwardEngineMessage(em) => construct_message(&["EM"], &em),
             RoundFinished => msg!["ROUND_FINISHED"],
             ChatMsg { nick, msg } => msg!["CHAT", nick, msg],
+            Info(info) => construct_message(&["INFO"], &info),
             ServerMessage(msg) => msg!["SERVER_MESSAGE", msg],
             ServerVars(vars) => construct_message(&["SERVER_VARS"], &vars),
             Notice(msg) => msg!["NOTICE", msg],
--- a/rust/hedgewars-server/src/server/client.rs	Wed Apr 10 23:56:53 2019 +0300
+++ b/rust/hedgewars-server/src/server/client.rs	Thu Apr 11 01:13:29 2019 +0300
@@ -10,6 +10,7 @@
         const IS_JOINED_MID_GAME = 0b0001_0000;
         const IS_CHECKER = 0b0010_0000;
         const IS_CONTRIBUTOR = 0b0100_0000;
+        const HAS_SUPER_POWER = 0b1000_0000;
 
         const NONE = 0b0000_0000;
         const DEFAULT = Self::NONE.bits;
@@ -70,6 +71,9 @@
     pub fn is_contributor(&self) -> bool {
         self.contains(ClientFlags::IS_CONTRIBUTOR)
     }
+    pub fn has_super_power(&self) -> bool {
+        self.contains(ClientFlags::HAS_SUPER_POWER)
+    }
 
     pub fn set_is_admin(&mut self, value: bool) {
         self.set(ClientFlags::IS_ADMIN, value)
@@ -92,4 +96,7 @@
     pub fn set_is_contributor(&mut self, value: bool) {
         self.set(ClientFlags::IS_CONTRIBUTOR, value)
     }
+    pub fn set_has_super_power(&mut self, value: bool) {
+        self.set(ClientFlags::HAS_SUPER_POWER, value)
+    }
 }
--- a/rust/hedgewars-server/src/server/core.rs	Wed Apr 10 23:56:53 2019 +0300
+++ b/rust/hedgewars-server/src/server/core.rs	Thu Apr 11 01:13:29 2019 +0300
@@ -7,6 +7,7 @@
 use crate::utils;
 
 use crate::protocol::messages::HWProtocolMessage::Greeting;
+use bitflags::*;
 use log::*;
 use slab;
 use std::{borrow::BorrowMut, iter, num::NonZeroU16};
@@ -60,11 +61,18 @@
     }
 }
 
+bitflags! {
+    pub struct ServerFlags: u8 {
+        const REGISTERED_ONLY = 0b0000_1000;
+    }
+}
+
 pub struct HWServer {
     pub clients: IndexSlab<HWClient>,
     pub rooms: Slab<HWRoom>,
     pub anteroom: HWAnteroom,
     pub latest_protocol: u16,
+    pub flags: ServerFlags,
     pub greetings: ServerGreetings,
 }
 
@@ -78,6 +86,7 @@
             anteroom: HWAnteroom::new(clients_limit),
             greetings: ServerGreetings::new(),
             latest_protocol: 58,
+            flags: ServerFlags::empty(),
         }
     }
 
@@ -183,6 +192,14 @@
         let room_id = self.clients[self_id].room_id;
         self.collect_clients(|(id, c)| *id != self_id && c.room_id == room_id)
     }
+
+    pub fn is_registered_only(&self) -> bool {
+        self.flags.contains(ServerFlags::REGISTERED_ONLY)
+    }
+
+    pub fn set_is_registered_only(&mut self, value: bool) {
+        self.flags.set(ServerFlags::REGISTERED_ONLY, value)
+    }
 }
 
 fn allocate_room(rooms: &mut Slab<HWRoom>) -> &mut HWRoom {
--- a/rust/hedgewars-server/src/server/handlers.rs	Wed Apr 10 23:56:53 2019 +0300
+++ b/rust/hedgewars-server/src/server/handlers.rs	Thu Apr 11 01:13:29 2019 +0300
@@ -222,6 +222,50 @@
                     HWProtocolMessage::Quit(None) => {
                         common::remove_client(server, response, "User quit".to_string());
                     }
+                    HWProtocolMessage::Info(nick) => {
+                        if let Some(client) = server.find_client(&nick) {
+                            let admin_sign = if client.is_admin() { "@" } else { "" };
+                            let master_sign = if client.is_master() { "+" } else { "" };
+                            let room_info = match client.room_id {
+                                Some(room_id) => {
+                                    let room = &server.rooms[room_id];
+                                    let status = match room.game_info {
+                                        Some(_) if client.teams_in_game == 0 => "(spectating)",
+                                        Some(_) => "(playing)",
+                                        None => "",
+                                    };
+                                    format!(
+                                        "[{}{}room {}]{}",
+                                        admin_sign, master_sign, room.name, status
+                                    )
+                                }
+                                None => format!("[{}lobby]", admin_sign),
+                            };
+
+                            let info = vec![
+                                client.nick.clone(),
+                                utils::protocol_version_string(client.protocol_number).to_string(),
+                                room_info,
+                            ];
+                            Info(info);
+                        } else {
+                            response
+                                .add(server_chat("Player is not online.".to_string()).send_self())
+                        }
+                    }
+                    HWProtocolMessage::ToggleServerRegisteredOnly => {
+                        if !server.clients[client_id].is_admin() {
+                            response.add(Warning("Access denied.".to_string()).send_self());
+                        } else {
+                            server.set_is_registered_only(server.is_registered_only());
+                            let msg = if server.is_registered_only() {
+                                "This server no longer allows unregistered players to join."
+                            } else {
+                                "This server now allows unregistered players to join."
+                            };
+                            response.add(server_chat(msg.to_string()).send_all());
+                        }
+                    }
                     HWProtocolMessage::Global(msg) => {
                         if !server.clients[client_id].is_admin() {
                             response.add(Warning("Access denied.".to_string()).send_self());
@@ -229,6 +273,15 @@
                             response.add(global_chat(msg).send_all())
                         }
                     }
+                    HWProtocolMessage::SuperPower => {
+                        if !server.clients[client_id].is_admin() {
+                            response.add(Warning("Access denied.".to_string()).send_self());
+                        } else {
+                            server.clients[client_id].set_has_super_power(true);
+                            response
+                                .add(server_chat("Super power activated.".to_string()).send_self())
+                        }
+                    }
                     HWProtocolMessage::Watch(id) => {
                         #[cfg(feature = "official-server")]
                         {
@@ -278,12 +331,20 @@
 ) {
     match io_result {
         IoResult::Account(Some(info)) => {
-            response.add(ServerAuth(format!("{:x}", info.server_hash)).send_self());
-            if let Some(client) = server.anteroom.remove_client(client_id) {
-                server.add_client(client_id, client);
-                let client = &mut server.clients[client_id];
-                client.set_is_admin(info.is_admin);
-                client.set_is_contributor(info.is_admin)
+            if !info.is_registered && server.is_registered_only() {
+                response.add(
+                    Bye("This server only allows registered users to join.".to_string())
+                        .send_self(),
+                );
+                response.remove_client(client_id);
+            } else {
+                response.add(ServerAuth(format!("{:x}", info.server_hash)).send_self());
+                if let Some(client) = server.anteroom.remove_client(client_id) {
+                    server.add_client(client_id, client);
+                    let client = &mut server.clients[client_id];
+                    client.set_is_admin(info.is_admin);
+                    client.set_is_contributor(info.is_admin)
+                }
             }
         }
         IoResult::Account(None) => {