# HG changeset patch # User alfadur # Date 1532128435 -10800 # Node ID 662f7df89d06952d10b92455319128dea53615e8 # Parent c8b626b0a3adafdf971176527245f79bfa65577a Implement room config export diff -r c8b626b0a3ad -r 662f7df89d06 gameServer2/Cargo.toml --- 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" diff -r c8b626b0a3ad -r 662f7df89d06 gameServer2/src/main.rs --- 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; diff -r c8b626b0a3ad -r 662f7df89d06 gameServer2/src/server/client.rs --- 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, diff -r c8b626b0a3ad -r 662f7df89d06 gameServer2/src/server/handlers/inroom.rs --- 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 { + 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))] diff -r c8b626b0a3ad -r 662f7df89d06 gameServer2/src/server/room.rs --- 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 } -#[derive(Clone)] +#[derive(Clone, Serialize, Deserialize)] struct Scheme { name: String, settings: Option> } -#[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 { + 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)>(text).map(|(greeting, saves)| { + self.greeting = greeting; + self.saves = saves; + }) + } + pub fn team_info(owner: &HWClient, team: &TeamInfo) -> Vec { let mut info = vec![ team.name.clone(),