Implement room config export
authoralfadur
Sat, 21 Jul 2018 02:13:55 +0300
changeset 13529 662f7df89d06
parent 13528 c8b626b0a3ad
child 13530 80db7232b4b5
Implement room config export
gameServer2/Cargo.toml
gameServer2/src/main.rs
gameServer2/src/server/client.rs
gameServer2/src/server/handlers/inroom.rs
gameServer2/src/server/room.rs
--- a/gameServer2/Cargo.toml	Fri Jul 20 22:14:20 2018 +0300
+++ b/gameServer2/Cargo.toml	Sat Jul 21 02:13:55 2018 +0300
@@ -14,3 +14,6 @@
 proptest = "0.8"
 base64 = "0.9"
 bitflags = "1.0"
+serde = "1.0"
+serde_yaml = "0.7"
+serde_derive = "1.0"
--- a/gameServer2/src/main.rs	Fri Jul 20 22:14:20 2018 +0300
+++ b/gameServer2/src/main.rs	Sat Jul 21 02:13:55 2018 +0300
@@ -13,6 +13,9 @@
 extern crate env_logger;
 #[macro_use] extern crate proptest;
 #[macro_use] extern crate bitflags;
+extern crate serde;
+extern crate serde_yaml;
+#[macro_use] extern crate serde_derive;
 
 //use std::io::*;
 //use rand::Rng;
--- a/gameServer2/src/server/client.rs	Fri Jul 20 22:14:20 2018 +0300
+++ b/gameServer2/src/server/client.rs	Sat Jul 21 02:13:55 2018 +0300
@@ -7,6 +7,9 @@
         const IS_READY = 0b0000_0100;
         const IS_IN_GAME = 0b0000_1000;
         const IS_JOINED_MID_GAME = 0b0001_0000;
+
+        const NONE = 0b0000_0000;
+        const DEFAULT = Self::NONE.bits;
     }
 }
 
@@ -28,7 +31,7 @@
             room_id: None,
             nick: String::new(),
             protocol_number: 0,
-            flags: ClientFlags::empty(),
+            flags: ClientFlags::DEFAULT,
             teams_in_game: 0,
             team_indices: Vec::new(),
             clan: None,
--- a/gameServer2/src/server/handlers/inroom.rs	Fri Jul 20 22:14:20 2018 +0300
+++ b/gameServer2/src/server/handlers/inroom.rs	Sat Jul 21 02:13:55 2018 +0300
@@ -12,7 +12,10 @@
     actions::{Action, Action::*}
 };
 use utils::is_name_illegal;
-use std::mem::swap;
+use std::{
+    mem::swap, fs::{File, OpenOptions},
+    io::{Read, Write, Result, Error, ErrorKind}
+};
 use base64::{encode, decode};
 use super::common::rnd_reply;
 
@@ -91,6 +94,18 @@
     }
 }
 
+fn read_file(filename: &str) -> Result<String> {
+    let mut reader = File::open(filename)?;
+    let mut result = String::new();
+    reader.read_to_string(&mut result)?;
+    Ok(result)
+}
+
+fn write_file(filename: &str, content: &str) -> Result<()> {
+    let mut writer = OpenOptions::new().create(true).write(true).open(filename)?;
+    writer.write_all(content.as_bytes())
+}
+
 pub fn handle(server: &mut HWServer, client_id: ClientId, room_id: RoomId, message: HWProtocolMessage) {
     use protocol::messages::HWProtocolMessage::*;
     match message {
@@ -281,6 +296,48 @@
             server.rooms[room_id].save_config(name, location);
             server.react(client_id, actions);
         }
+        SaveRoom(filename) => {
+            let actions = if server.clients[client_id].is_admin() {
+                match server.rooms[room_id].get_saves() {
+                    Ok(text) => match write_file(&filename, &text) {
+                        Ok(_) => vec![server_chat("Room configs saved successfully.".to_string())
+                            .send_self().action()],
+                        Err(e) => {
+                            warn!("Error while writing the config file \"{}\": {}", filename, e);
+                            vec![Warn("Unable to save the room configs.".to_string())]
+                        }
+                    }
+                    Err(e) => {
+                        warn!("Error while serializing the room configs: {}", e);
+                        vec![Warn("Unable to serialize the room configs.".to_string())]
+                    }
+                }
+            } else {
+                Vec::new()
+            };
+            server.react(client_id, actions);
+        }
+        LoadRoom(filename) => {
+            let actions = if server.clients[client_id].is_admin() {
+                match read_file(&filename) {
+                    Ok(text) => match server.rooms[room_id].set_saves(&text) {
+                        Ok(_) => vec![server_chat("Room configs loaded successfully.".to_string())
+                            .send_self().action()],
+                        Err(e) => {
+                            warn!("Error while deserializing the room configs: {}", e);
+                            vec![Warn("Unable to deserialize the room configs.".to_string())]
+                        }
+                    }
+                    Err(e) => {
+                        warn!("Error while reading the config file \"{}\": {}", filename, e);
+                        vec![Warn("Unable to load the room configs.".to_string())]
+                    }
+                }
+            } else {
+                Vec::new()
+            };
+            server.react(client_id, actions);
+        }
         Delete(name) => {
             let actions = if !server.rooms[room_id].delete_config(&name) {
                 vec![Warn(format!("Save doesn't exist: {}", name))]
--- a/gameServer2/src/server/room.rs	Fri Jul 20 22:14:20 2018 +0300
+++ b/gameServer2/src/server/room.rs	Sat Jul 21 02:13:55 2018 +0300
@@ -5,23 +5,25 @@
     coretypes::{ClientId, RoomId, TeamInfo, GameCfg, GameCfg::*, Voting},
     client::{HWClient}
 };
+use serde::{Serialize, Deserialize};
+use serde_yaml;
 
 const MAX_HEDGEHOGS_IN_ROOM: u8 = 64;
 const MAX_TEAMS_IN_ROOM: u8 = 8;
 
-#[derive(Clone)]
+#[derive(Clone, Serialize, Deserialize)]
 struct Ammo {
     name: String,
     settings: Option<String>
 }
 
-#[derive(Clone)]
+#[derive(Clone, Serialize, Deserialize)]
 struct Scheme {
     name: String,
     settings: Option<Vec<String>>
 }
 
-#[derive(Clone)]
+#[derive(Clone, Serialize, Deserialize)]
 struct RoomConfig {
     feature_size: u32,
     map_type: String,
@@ -109,6 +111,7 @@
     }
 }
 
+#[derive(Serialize, Deserialize)]
 pub struct RoomSave {
     pub location: String,
     config: RoomConfig
@@ -352,6 +355,17 @@
         self.saves.remove(name).is_some()
     }
 
+    pub fn get_saves(&self) -> Result<String, serde_yaml::Error> {
+        serde_yaml::to_string(&(&self.greeting, &self.saves))
+    }
+
+    pub fn set_saves(&mut self, text: &str) -> Result<(), serde_yaml::Error> {
+        serde_yaml::from_str::<(String, HashMap<String, RoomSave>)>(text).map(|(greeting, saves)| {
+            self.greeting = greeting;
+            self.saves = saves;
+        })
+    }
+
     pub fn team_info(owner: &HWClient, team: &TeamInfo) -> Vec<String> {
         let mut info = vec![
             team.name.clone(),