--- 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<String>),
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],
--- 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)
--- 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)]
--- 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<String>),
+ Scheme(String, Option<Vec<String>>),
+ Script(String),
+ Theme(String),
+ DrawnMap(String)
}
#[derive(PartialEq, Eq, Clone, Debug)]
--- 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!")
}
--- 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<String>
+}
+
+struct Scheme {
+ name: String,
+ settings: Option<Vec<String>>
+}
+
+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<String>
+}
+
+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<ClientId>,
@@ -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<String> {
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<String> {
+ 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<GameCfg> {
+ 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<String> {
let mut info = vec![
team.name.clone(),
--- 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<_>>(),
- _ => Vec::new()
+ self.clients.iter().map(|(id, _)| id).collect::<Vec<_>>()
};
if let Destination::ToAll {skip_self: true, ..} = destination {
if let Some(index) = ids.iter().position(|id| *id == client_id) {