# HG changeset patch # User alfadur # Date 1530044558 -10800 # Node ID 5fb27f94fc3b8085f125dc04ba0a735d794fb321 # Parent d1368c776a4f6a47d1c190a3c2f533a38a72fcb4 Implement game config messages diff -r d1368c776a4f -r 5fb27f94fc3b gameServer2/src/protocol/messages.rs --- a/gameServer2/src/protocol/messages.rs Sun Jun 24 12:09:31 2018 -0400 +++ b/gameServer2/src/protocol/messages.rs Tue Jun 26 23:22:38 2018 +0300 @@ -91,6 +91,7 @@ TeamAccepted(String), TeamColor(String, u8), HedgehogsNumber(String, u8), + ConfigEntry(String, Vec), ServerMessage(String), Warning(String), @@ -99,6 +100,33 @@ Unreachable, } +impl GameCfg { + pub fn into_server_msg(self) -> HWServerMessage { + use self::HWServerMessage::ConfigEntry; + use server::coretypes::GameCfg::*; + match self { + FeatureSize(s) => ConfigEntry("FEATURE_SIZE".to_string(), vec![s.to_string()]), + MapType(t) => ConfigEntry("MAP".to_string(), vec![t.to_string()]), + MapGenerator(g) => ConfigEntry("MAPGEN".to_string(), vec![g.to_string()]), + MazeSize(s) => ConfigEntry("MAZE_SIZE".to_string(), vec![s.to_string()]), + Seed(s) => ConfigEntry("SEED".to_string(), vec![s.to_string()]), + Template(t) => ConfigEntry("TEMPLATE".to_string(), vec![t.to_string()]), + + Ammo(n, None) => ConfigEntry("AMMO".to_string(), vec![n.to_string()]), + Ammo(n, Some(s)) => ConfigEntry("AMMO".to_string(), vec![n.to_string(), s.to_string()]), + Scheme(n, None) => ConfigEntry("SCHEME".to_string(), vec![n.to_string()]), + Scheme(n, Some(s)) => ConfigEntry("SCHEME".to_string(), { + let mut v = vec![n.to_string()]; + v.extend(s.into_iter()); + v + }), + Script(s) => ConfigEntry("SCRIPT".to_string(), vec![s.to_string()]), + Theme(t) => ConfigEntry("THEME".to_string(), vec![t.to_string()]), + DrawnMap(m) => ConfigEntry("DRAWNMAP".to_string(), vec![m.to_string()]) + } + } +} + impl<'a> HWProtocolMessage { pub fn to_raw_protocol(&self) -> String { use self::HWProtocolMessage::*; @@ -229,6 +257,8 @@ TeamAccepted(name) => msg!["TEAM_ACCEPTED", name], TeamColor(name, color) => msg!["TEAM_COLOR", name, color], HedgehogsNumber(name, number) => msg!["HH_NUM", name, number], + ConfigEntry(name, values) => + construct_message(&["CFG", name], &values), ChatMsg(nick, msg) => msg!["CHAT", nick, msg], ServerMessage(msg) => msg!["SERVER_MESSAGE", msg], Warning(msg) => msg!["WARNING", msg], diff -r d1368c776a4f -r 5fb27f94fc3b gameServer2/src/protocol/parser.rs --- a/gameServer2/src/protocol/parser.rs Sun Jun 24 12:09:31 2018 -0400 +++ b/gameServer2/src/protocol/parser.rs Tue Jun 26 23:22:38 2018 +0300 @@ -9,7 +9,7 @@ test::gen_proto_msg }; use server::coretypes::{ - HedgehogInfo, TeamInfo + HedgehogInfo, TeamInfo, GameCfg }; named!(end_of_message, tag!("\n\n")); @@ -139,6 +139,45 @@ (BanNick(n, r, t))) )); +named!(cfg_message<&[u8], HWProtocolMessage>, preceded!(tag!("CFG\n"), map!(alt!( + do_parse!(tag!("THEME") >> eol >> + name: a_line >> + (GameCfg::Theme(name))) + | do_parse!(tag!("SCRIPT") >> eol >> + name: a_line >> + (GameCfg::Script(name))) + | do_parse!(tag!("AMMO") >> eol >> + name: a_line >> + value: opt_param >> + (GameCfg::Ammo(name, value))) + | do_parse!(tag!("SCHEME") >> eol >> + name: a_line >> eol >> + values: separated_list!(eol, a_line) >> + (GameCfg::Scheme(name, + if values.is_empty() {None} else {Some(values)}))) + | do_parse!(tag!("FEATURE_SIZE") >> eol >> + value: u32_line >> + (GameCfg::FeatureSize(value))) + | do_parse!(tag!("MAP") >> eol >> + value: a_line >> + (GameCfg::MapType(value))) + | do_parse!(tag!("MAPGEN") >> eol >> + value: u32_line >> + (GameCfg::MapGenerator(value))) + | do_parse!(tag!("MAZE_SIZE") >> eol >> + value: u32_line >> + (GameCfg::MazeSize(value))) + | do_parse!(tag!("SEED") >> eol >> + value: a_line >> + (GameCfg::Seed(value))) + | do_parse!(tag!("TEMPLATE") >> eol >> + value: u32_line >> + (GameCfg::Template(value))) + | do_parse!(tag!("DRAWNMAP") >> eol >> + value: a_line >> + (GameCfg::DrawnMap(value))) +), Cfg))); + named!(malformed_message<&[u8], HWProtocolMessage>, do_parse!(separated_list!(eol, a_line) >> (Malformed))); @@ -151,6 +190,7 @@ | one_param_message | cmd_message | complex_message + | cfg_message ), end_of_message ) | terminated!(malformed_message, end_of_message) diff -r d1368c776a4f -r 5fb27f94fc3b gameServer2/src/server/actions.rs --- a/gameServer2/src/server/actions.rs Sun Jun 24 12:09:31 2018 -0400 +++ b/gameServer2/src/server/actions.rs Tue Jun 26 23:22:38 2018 +0300 @@ -211,9 +211,18 @@ } let flags_msg = ClientFlags("+i".to_string(), vec![c.nick.clone()]); - vec![RoomJoined(vec![c.nick.clone()]).send_all().in_room(room_id).action(), - flags_msg.send_all().action(), - SendRoomUpdate(None)] + let mut v = vec![ + RoomJoined(vec![c.nick.clone()]).send_all().in_room(room_id).action(), + flags_msg.send_all().action(), + SendRoomUpdate(None)]; + if !c.is_master { + v.push(ConfigEntry("FULLMAPCONFIG".to_string(), r.map_config()) + .send_self().action()); + for cfg in r.game_config().into_iter() { + v.push(cfg.into_server_msg().send_self().action()); + } + } + v }; server.react(client_id, actions); }, @@ -274,7 +283,7 @@ server.react(client_id, actions); } RemoveTeam(name) => { - let actions = if let (c, Some(r)) = server.client_and_room(client_id) { + let actions = if let (_, Some(r)) = server.client_and_room(client_id) { r.remove_team(&name); vec![TeamRemove(name).send_all().in_room(r.id).action(), SendRoomUpdate(None)] diff -r d1368c776a4f -r 5fb27f94fc3b gameServer2/src/server/coretypes.rs --- a/gameServer2/src/server/coretypes.rs Sun Jun 24 12:09:31 2018 -0400 +++ b/gameServer2/src/server/coretypes.rs Tue Jun 26 23:22:38 2018 +0300 @@ -7,7 +7,18 @@ #[derive(PartialEq, Eq, Clone, Debug)] pub enum GameCfg { + FeatureSize(u32), + MapType(String), + MapGenerator(u32), + MazeSize(u32), + Seed(String), + Template(u32), + Ammo(String, Option), + Scheme(String, Option>), + Script(String), + Theme(String), + DrawnMap(String) } #[derive(PartialEq, Eq, Clone, Debug)] diff -r d1368c776a4f -r 5fb27f94fc3b gameServer2/src/server/handlers/inroom.rs --- a/gameServer2/src/server/handlers/inroom.rs Sun Jun 24 12:09:31 2018 -0400 +++ b/gameServer2/src/server/handlers/inroom.rs Tue Jun 26 23:22:38 2018 +0300 @@ -40,7 +40,7 @@ vec![Warn("A room with the same name already exists.".to_string())] } else { let mut old_name = new_name.clone(); - if let (c, Some(r)) = server.client_and_room(client_id) { + if let (_, Some(r)) = server.client_and_room(client_id) { swap(&mut r.name, &mut old_name); vec![SendRoomUpdate(Some(old_name))] } else { @@ -66,7 +66,7 @@ }; server.react(client_id, actions); } - AddTeam(mut info) => { + AddTeam(info) => { let mut actions = Vec::new(); if let (c, Some(r)) = server.client_and_room(client_id) { let room_id = r.id; @@ -163,6 +163,20 @@ } server.react(client_id, actions); + }, + Cfg(cfg) => { + let actions = if let (c, Some(r)) = server.client_and_room(client_id) { + if !c.is_master { + vec![ProtocolError("You're not the room master!".to_string())] + } else { + r.set_config(cfg.clone()); + vec![cfg.into_server_msg() + .send_all().in_room(r.id).but_self().action()] + } + } else { + Vec::new() + }; + server.react(client_id, actions); } _ => warn!("Unimplemented!") } diff -r d1368c776a4f -r 5fb27f94fc3b gameServer2/src/server/room.rs --- a/gameServer2/src/server/room.rs Sun Jun 24 12:09:31 2018 -0400 +++ b/gameServer2/src/server/room.rs Tue Jun 26 23:22:38 2018 +0300 @@ -1,12 +1,56 @@ -use std::iter; +use std::{iter}; use server::{ - coretypes::{TeamInfo, GameCfg}, + coretypes::{TeamInfo, GameCfg, GameCfg::*}, client::{ClientId, HWClient} }; const MAX_HEDGEHOGS_IN_ROOM: u8 = 48; pub type RoomId = usize; +struct Ammo { + name: String, + settings: Option +} + +struct Scheme { + name: String, + settings: Option> +} + +struct RoomConfig { + feature_size: u32, + map_type: String, + map_generator: u32, + maze_size: u32, + seed: String, + template: u32, + + ammo: Ammo, + scheme: Scheme, + script: String, + theme: String, + drawn_map: Option +} + +impl RoomConfig { + fn new() -> RoomConfig { + RoomConfig { + feature_size: 12, + map_type: "+rnd+".to_string(), + map_generator: 0, + maze_size: 0, + seed: "seed".to_string(), + template: 0, + + ammo: Ammo {name: "Default".to_string(), settings: None }, + scheme: Scheme {name: "Default".to_string(), settings: None }, + script: "Normal".to_string(), + theme: "\u{1f994}".to_string(), + drawn_map: None + } + } +} + pub struct HWRoom { pub id: RoomId, pub master_id: Option, @@ -19,6 +63,7 @@ pub team_limit: u8, pub ready_players_number: u8, pub teams: Vec<(ClientId, TeamInfo)>, + config: RoomConfig, pub game_info: Option<()> } @@ -35,6 +80,7 @@ team_limit: 8, ready_players_number: 0, teams: Vec::new(), + config: RoomConfig::new(), game_info: None } } @@ -90,21 +136,61 @@ self.client_teams(owner_id).nth(0).map(|t| t.color) } + pub fn set_config(&mut self, cfg: GameCfg) { + let c = &mut self.config; + match cfg { + FeatureSize(s) => c.feature_size = s, + MapType(t) => c.map_type = t, + MapGenerator(g) => c.map_generator = g, + MazeSize(s) => c.maze_size = s, + Seed(s) => c.seed = s, + Template(t) => c.template = t, + + Ammo(n, s) => c.ammo = Ammo {name: n, settings: s}, + Scheme(n, s) => c.scheme = Scheme {name: n, settings: s}, + Script(s) => c.script = s, + Theme(t) => c.theme = t, + DrawnMap(m) => c.drawn_map = Some(m) + }; + } + pub fn info(&self, master: Option<&HWClient>) -> Vec { let flags = "-".to_string(); + let c = &self.config; vec![ flags, self.name.clone(), self.players_number.to_string(), self.teams.len().to_string(), - master.map_or("?", |c| &c.nick).to_string(), - "Normal".to_string(), - "Default".to_string(), - "Default".to_string(), - "Default".to_string(), + master.map_or("[]", |c| &c.nick).to_string(), + c.map_type.to_string(), + c.script.to_string(), + c.scheme.name.to_string(), + c.ammo.name.to_string() ] } + pub fn map_config(&self) -> Vec { + let c = &self.config; + vec![c.feature_size.to_string(), c.map_type.to_string(), + c.map_generator.to_string(), c.maze_size.to_string(), + c.seed.to_string(), c.template.to_string()] + } + + pub fn game_config(&self) -> Vec { + use server::coretypes::GameCfg::*; + let c = &self.config; + let mut v = vec![ + Ammo(c.ammo.name.to_string(), c.ammo.settings.clone()), + Scheme(c.scheme.name.to_string(), c.scheme.settings.clone()), + Script(c.script.to_string()), + Theme(c.theme.to_string())]; + if let Some(ref m) = c.drawn_map { + v.push(DrawnMap(m.to_string())) + } + v + } + pub fn team_info(owner: &HWClient, team: &TeamInfo) -> Vec { let mut info = vec![ team.name.clone(), diff -r d1368c776a4f -r 5fb27f94fc3b gameServer2/src/server/server.rs --- a/gameServer2/src/server/server.rs Sun Jun 24 12:09:31 2018 -0400 +++ b/gameServer2/src/server/server.rs Tue Jun 26 23:22:38 2018 +0300 @@ -69,8 +69,7 @@ Destination::ToAll {protocol: Some(proto), ..} => self.protocol_clients(proto), Destination::ToAll {..} => - self.clients.iter().map(|(id, _)| id).collect::>(), - _ => Vec::new() + self.clients.iter().map(|(id, _)| id).collect::>() }; if let Destination::ToAll {skip_self: true, ..} = destination { if let Some(index) = ids.iter().position(|id| *id == client_id) {