# HG changeset patch # User Wuzzy # Date 1532131573 -7200 # Node ID 395a4c92e523f5bea91142f7943b881e14cd7289 # Parent 0c8001e43fd3428d87217fc67d8e1b7a62856664# Parent 282218ab1b28013ba821a56594ca02e87dbfa49d Merge alfadur's server commits with timer cycle key commits diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/Cargo.toml --- a/gameServer2/Cargo.toml Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/Cargo.toml Sat Jul 21 02:06:13 2018 +0200 @@ -13,3 +13,7 @@ log = "0.4" proptest = "0.8" base64 = "0.9" +bitflags = "1.0" +serde = "1.0" +serde_yaml = "0.7" +serde_derive = "1.0" diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/main.rs --- a/gameServer2/src/main.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/main.rs Sat Jul 21 02:06:13 2018 +0200 @@ -12,6 +12,10 @@ extern crate log; 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 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/protocol/messages.rs --- a/gameServer2/src/protocol/messages.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/protocol/messages.rs Sat Jul 21 02:06:13 2018 +0200 @@ -18,7 +18,7 @@ Info(String), // not entered state Nick(String), - Proto(u32), + Proto(u16), Password(String, String), Checker(u32, String, String), // lobby @@ -41,7 +41,7 @@ // in room Part(Option), Cfg(GameCfg), - AddTeam(TeamInfo), + AddTeam(Box), RemoveTeam(String), SetHedgehogsNumber(String, u8), SetTeamColor(String, u8), @@ -76,7 +76,7 @@ Pong, Bye(String), Nick(String), - Proto(u32), + Proto(u16), LobbyLeft(String, String), LobbyJoined(Vec), ChatMsg {nick: String, msg: String}, @@ -105,8 +105,8 @@ Unreachable, } -pub fn server_chat(msg: &str) -> HWServerMessage { - HWServerMessage::ChatMsg{ nick: "[server]".to_string(), msg: msg.to_string() } +pub fn server_chat(msg: String) -> HWServerMessage { + HWServerMessage::ChatMsg{ nick: "[server]".to_string(), msg } } impl GameCfg { @@ -234,10 +234,10 @@ //CallVote(Option<(String, Option)>) =>, ?? Vote(msg) => msg!["CMD", format!("VOTE {}", if *msg {"YES"} else {"NO"})], ForceVote(msg) => msg!["CMD", format!("FORCE {}", if *msg {"YES"} else {"NO"})], - //Save(String, String), ?? - Delete(room) => msg!["CMD", format!("DELETE {}", room)], - SaveRoom(room) => msg!["CMD", format!("SAVEROOM {}", room)], - LoadRoom(room) => msg!["CMD", format!("LOADROOM {}", room)], + Save(name, location) => msg!["CMD", format!("SAVE {} {}", name, location)], + Delete(name) => msg!["CMD", format!("DELETE {}", name)], + SaveRoom(name) => msg!["CMD", format!("SAVEROOM {}", name)], + LoadRoom(name) => msg!["CMD", format!("LOADROOM {}", name)], Malformed => msg!["A", "QUICK", "BROWN", "HOG", "JUMPS", "OVER", "THE", "LAZY", "DOG"], Empty => msg![""], _ => panic!("Protocol message not yet implemented") @@ -245,7 +245,7 @@ } } -fn construct_message(header: &[&str], msg: &Vec) -> String { +fn construct_message(header: &[&str], msg: &[String]) -> String { let mut v: Vec<_> = header.iter().map(|s| *s).collect(); v.extend(msg.iter().map(|s| &s[..])); v.push("\n"); diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/protocol/parser.rs --- a/gameServer2/src/protocol/parser.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/protocol/parser.rs Sat Jul 21 02:06:13 2018 +0200 @@ -24,7 +24,10 @@ named!(end_of_message, tag!("\n\n")); named!(str_line<&[u8], &str>, map_res!(not_line_ending, str::from_utf8)); named!( a_line<&[u8], String>, map!(str_line, String::from)); +named!(cmd_arg<&[u8], String>, + map!(map_res!(take_until_either!(" \n"), str::from_utf8), String::from)); named!( u8_line<&[u8], u8>, map_res!(str_line, FromStr::from_str)); +named!(u16_line<&[u8], u16>, map_res!(str_line, FromStr::from_str)); named!(u32_line<&[u8], u32>, map_res!(str_line, FromStr::from_str)); named!(yes_no_line<&[u8], bool>, alt!( do_parse!(tag_no_case!("YES") >> (true)) @@ -87,7 +90,7 @@ | do_parse!(tag!("ROOM_NAME") >> eol >> n: a_line >> (RoomName(n))) | do_parse!(tag!("REMOVE_TEAM") >> eol >> n: a_line >> (RemoveTeam(n))) - | do_parse!(tag!("PROTO") >> eol >> d: u32_line >> (Proto(d))) + | do_parse!(tag!("PROTO") >> eol >> d: u16_line >> (Proto(d))) | do_parse!(tag!("QUIT") >> msg: opt_param >> (Quit(msg))) )); @@ -103,9 +106,10 @@ | do_parse!(tag_no_case!("PART") >> m: opt_space_param >> (Part(m))) | do_parse!(tag_no_case!("QUIT") >> m: opt_space_param >> (Quit(m))) | do_parse!(tag_no_case!("DELEGATE") >> spaces >> n: a_line >> (Delegate(n))) + | do_parse!(tag_no_case!("SAVE") >> spaces >> n: cmd_arg >> spaces >> l: cmd_arg >> (Save(n, l))) + | do_parse!(tag_no_case!("DELETE") >> spaces >> n: a_line >> (Delete(n))) | do_parse!(tag_no_case!("SAVEROOM") >> spaces >> r: a_line >> (SaveRoom(r))) | do_parse!(tag_no_case!("LOADROOM") >> spaces >> r: a_line >> (LoadRoom(r))) - | do_parse!(tag_no_case!("DELETE") >> spaces >> r: a_line >> (Delete(r))) | do_parse!(tag_no_case!("GLOBAL") >> spaces >> m: a_line >> (Global(m))) | do_parse!(tag_no_case!("WATCH") >> spaces >> i: a_line >> (Watch(i))) | do_parse!(tag_no_case!("GREETING") >> spaces >> m: a_line >> (Greeting(m))) @@ -148,11 +152,11 @@ flag: a_line >> eol >> difficulty: u8_line >> eol >> hedgehogs: _8_hogs >> - (AddTeam(TeamInfo{ + (AddTeam(Box::new(TeamInfo{ name, color, grave, fort, voice_pack, flag, difficulty, hedgehogs, hedgehogs_number: 0 - }))) + })))) | do_parse!(tag!("HH_NUM") >> eol >> n: a_line >> eol >> c: u8_line >> diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/protocol/test.rs --- a/gameServer2/src/protocol/test.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/protocol/test.rs Sat Jul 21 02:06:13 2018 +0200 @@ -118,7 +118,7 @@ 7 => SuperPower(), 8 => Info(Ascii), 9 => Nick(Ascii), - 10 => Proto(u32), + 10 => Proto(u16), 11 => Password(Ascii, Ascii), 12 => Checker(u32, Ascii, Ascii), 13 => List(), @@ -139,7 +139,7 @@ 28 => Stats(), 29 => Part(Option), 30 => Cfg(GameCfg), - 31 => AddTeam(TeamInfo), + 31 => AddTeam(Box), 32 => RemoveTeam(Ascii), 33 => SetHedgehogsNumber(Ascii, u8), 34 => SetTeamColor(Ascii, u8), @@ -160,7 +160,7 @@ //49 => CallVote(Option<(String, Option)>), 50 => Vote(bool), 51 => ForceVote(bool), - //52 => Save(String, String), + 52 => Save(Ascii, Ascii), 53 => Delete(Ascii), 54 => SaveRoom(Ascii), 55 => LoadRoom(Ascii), diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/server/actions.rs --- a/gameServer2/src/server/actions.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/server/actions.rs Sat Jul 21 02:06:13 2018 +0200 @@ -5,7 +5,7 @@ }; use super::{ server::HWServer, - room::{GameInfo}, + room::{GameInfo, RoomFlags}, client::HWClient, coretypes::{ClientId, RoomId, GameCfg, VoteType}, room::HWRoom, @@ -25,7 +25,7 @@ ToSelf, ToAll { room_id: Option, - protocol: Option, + protocol: Option, skip_self: bool } } @@ -60,7 +60,7 @@ self } - pub fn with_protocol(mut self, protocol_number: u32) -> PendingMessage { + pub fn with_protocol(mut self, protocol_number: u16) -> PendingMessage { if let Destination::ToAll {ref mut protocol, ..} = self.destination { *protocol = Some(protocol_number) } @@ -116,7 +116,7 @@ pub fn run_action(server: &mut HWServer, client_id: usize, action: Action) { match action { - Send(msg) => server.send(client_id, msg.destination, msg.message), + Send(msg) => server.send(client_id, &msg.destination, msg.message), ByeClient(msg) => { let room_id; let nick; @@ -126,12 +126,12 @@ nick = c.nick.clone(); } - room_id.map (|id| { + if let Some(id) = room_id{ if id != server.lobby_id { server.react(client_id, vec![ MoveToLobby(format!("quit: {}", msg.clone()))]); } - }); + } server.react(client_id, vec![ LobbyLeft(nick, msg.clone()).send_all().action(), @@ -218,14 +218,14 @@ let c = &mut server.clients[client_id]; r.players_number += 1; c.room_id = Some(room_id); - c.is_joined_mid_game = false; - if r.master_id == Some(c.id) { + + let is_master = r.master_id == Some(c.id); + c.set_is_master(is_master); + c.set_is_ready(is_master); + c.set_is_joined_mid_game(false); + + if is_master { r.ready_players_number += 1; - c.is_master = true; - c.is_ready = true; - } else { - c.is_ready = false; - c.is_master = false; } let mut v = vec![ @@ -236,11 +236,11 @@ v.push(ChatMsg {nick: "[greeting]".to_string(), msg: r.greeting.clone()} .send_self().action()); } - if !c.is_master { + if !c.is_master() { let team_names: Vec<_>; if let Some(ref mut info) = r.game_info { - c.is_in_game = true; - c.is_joined_mid_game = true; + c.set_is_in_game(true); + c.set_is_joined_mid_game(true); { let teams = info.client_teams(c.id); @@ -273,7 +273,7 @@ v.push(ForwardEngineMessage(info.msg_log.clone()) .send_self().action()); - for name in team_names.iter() { + for name in &team_names { v.push(ForwardEngineMessage( vec![to_engine_msg(once(b'G').chain(name.bytes()))]) .send_all().in_room(r.id).action()); @@ -295,7 +295,7 @@ if config { actions.push(ConfigEntry("FULLMAPCONFIG".to_string(), r.map_config()) .send(to).action()); - for cfg in r.game_config().into_iter() { + for cfg in r.game_config() { actions.push(cfg.to_server_msg().send(to).action()); } } @@ -319,7 +319,7 @@ .send(to).action()); } let nicks: Vec<_> = server.clients.iter() - .filter(|(_, c)| c.room_id == Some(r.id) && c.is_ready) + .filter(|(_, c)| c.room_id == Some(r.id) && c.is_ready()) .map(|(_, c)| c.nick.clone()).collect(); if !nicks.is_empty() { actions.push(ClientFlags("+r".to_string(), nicks) @@ -331,11 +331,12 @@ } AddVote{vote, is_forced} => { let mut actions = Vec::new(); - if let (c, Some(r)) = server.client_and_room(client_id) { + if let Some(r) = server.room(client_id) { let mut result = None; if let Some(ref mut voting) = r.voting { if is_forced || voting.votes.iter().find(|(id, _)| client_id == *id).is_none() { - actions.push(server_chat("Your vote has been counted.").send_self().action()); + actions.push(server_chat("Your vote has been counted.".to_string()) + .send_self().action()); voting.votes.push((client_id, vote)); let i = voting.votes.iter(); let pro = i.clone().filter(|(_, v)| *v).count(); @@ -347,14 +348,16 @@ result = Some(false); } } else { - actions.push(server_chat("You already have voted.").send_self().action()); + actions.push(server_chat("You already have voted.".to_string()) + .send_self().action()); } } else { - actions.push(server_chat("There's no voting going on.").send_self().action()); + actions.push(server_chat("There's no voting going on.".to_string()) + .send_self().action()); } if let Some(res) = result { - actions.push(server_chat("Voting closed.") + actions.push(server_chat("Voting closed.".to_string()) .send_all().in_room(r.id).action()); let voting = replace(&mut r.voting, None).unwrap(); if res { @@ -378,13 +381,25 @@ } } }, - VoteType::Map(_) => { - unimplemented!(); + VoteType::Map(None) => (), + VoteType::Map(Some(name)) => { + if let Some(location) = server.rooms[room_id].load_config(&name) { + actions.push(server_chat(location.to_string()) + .send_all().in_room(room_id).action()); + actions.push(SendRoomUpdate(None)); + for (_, c) in server.clients.iter() { + if c.room_id == Some(room_id) { + actions.push(SendRoomData{ + to: c.id, teams: false, + config: true, flags: false}) + } + } + } }, VoteType::Pause => { if let Some(ref mut info) = server.rooms[room_id].game_info { info.is_paused = !info.is_paused; - actions.push(server_chat("Pause toggled.") + actions.push(server_chat("Pause toggled.".to_string()) .send_all().in_room(room_id).action()); actions.push(ForwardEngineMessage(vec![to_engine_msg(once(b'I'))]) .send_all().in_room(room_id).action()); @@ -411,10 +426,10 @@ let lobby_id = server.lobby_id; if let (c, Some(r)) = server.client_and_room(client_id) { r.players_number -= 1; - if c.is_ready && r.ready_players_number > 0 { + if c.is_ready() && r.ready_players_number > 0 { r.ready_players_number -= 1; } - if c.is_master && (r.players_number > 0 || r.is_fixed) { + if c.is_master() && (r.players_number > 0 || r.is_fixed()) { actions.push(ChangeMaster(r.id, None)); } actions.push(ClientFlags("-i".to_string(), vec![c.nick.clone()]) @@ -425,7 +440,7 @@ if let (c, Some(r)) = server.client_and_room(client_id) { c.room_id = Some(lobby_id); - if r.players_number == 0 && !r.is_fixed { + if r.players_number == 0 && !r.is_fixed() { actions.push(RemoveRoom(r.id)); } else { actions.push(RemoveClientTeams); @@ -439,18 +454,18 @@ ChangeMaster(room_id, new_id) => { let mut actions = Vec::new(); let room_client_ids = server.room_clients(room_id); - let new_id = if server.room(client_id).map(|r| r.is_fixed).unwrap_or(false) { + let new_id = if server.room(client_id).map(|r| r.is_fixed()).unwrap_or(false) { new_id } else { new_id.or_else(|| - room_client_ids.iter().find(|id| **id != client_id).map(|id| *id)) + room_client_ids.iter().find(|id| **id != client_id).cloned()) }; let new_nick = new_id.map(|id| server.clients[id].nick.clone()); if let (c, Some(r)) = server.client_and_room(client_id) { match r.master_id { Some(id) if id == c.id => { - c.is_master = false; + c.set_is_master(false); r.master_id = None; actions.push(ClientFlags("-h".to_string(), vec![c.nick.clone()]) .send_all().in_room(r.id).action()); @@ -459,12 +474,16 @@ None => {} } r.master_id = new_id; + r.set_join_restriction(false); + r.set_team_add_restriction(false); + let is_fixed = r.is_fixed(); + r.set_unregistered_players_restriction(is_fixed); if let Some(nick) = new_nick { actions.push(ClientFlags("+h".to_string(), vec![nick]) .send_all().in_room(r.id).action()); } } - new_id.map(|id| server.clients[id].is_master = true); + if let Some(id) = new_id { server.clients[id].set_is_master(true) } server.react(client_id, actions); } RemoveTeam(name) => { @@ -476,7 +495,7 @@ } actions.push(TeamRemove(name.clone()).send_all().in_room(r.id).action()); actions.push(SendRoomUpdate(None)); - if r.game_info.is_some() && c.is_in_game { + if r.game_info.is_some() && c.is_in_game() { actions.push(SendTeamRemovalMessage(name)); } } @@ -514,7 +533,7 @@ room.start_round(); for id in room_clients { let c = &mut server.clients[id]; - c.is_in_game = true; + c.set_is_in_game(false); c.team_indices = room.client_team_indices(c.id); } vec![RunGame.send_all().in_room(room.id).action(), @@ -527,7 +546,7 @@ } SendTeamRemovalMessage(team_name) => { let mut actions = Vec::new(); - if let (c, Some(r)) = server.client_and_room(client_id) { + if let Some(r) = server.room(client_id) { if let Some(ref mut info) = r.game_info { let msg = once(b'F').chain(team_name.bytes()); actions.push(ForwardEngineMessage(vec![to_engine_msg(msg)]). @@ -564,11 +583,11 @@ if let Some(info) = old_info { for (_, c) in server.clients.iter() { - if c.room_id == Some(room_id) && c.is_joined_mid_game { + if c.room_id == Some(room_id) && c.is_joined_mid_game() { actions.push(SendRoomData{ to: c.id, teams: false, config: true, flags: false}); - for name in info.left_teams.iter() { + for name in &info.left_teams { actions.push(TeamRemove(name.clone()) .send(c.id).action()); } @@ -579,10 +598,11 @@ let nicks: Vec<_> = server.clients.iter_mut() .filter(|(_, c)| c.room_id == Some(room_id)) .map(|(_, c)| { - c.is_ready = c.is_master; - c.is_joined_mid_game = false; + let is_master = c.is_master(); + c.set_is_ready(is_master); + c.set_is_joined_mid_game(false); c - }).filter_map(|c| if !c.is_master { + }).filter_map(|c| if !c.is_master() { Some(c.nick.clone()) } else { None diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/server/client.rs --- a/gameServer2/src/server/client.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/server/client.rs Sat Jul 21 02:06:13 2018 +0200 @@ -1,18 +1,27 @@ use super::coretypes::ClientId; +bitflags!{ + pub struct ClientFlags: u8 { + const IS_ADMIN = 0b0000_0001; + const IS_MASTER = 0b0000_0010; + 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; + } +} + pub struct HWClient { pub id: ClientId, pub room_id: Option, pub nick: String, - pub protocol_number: u32, - pub is_admin: bool, - pub is_master: bool, - pub is_ready: bool, - pub is_in_game: bool, + pub protocol_number: u16, + pub flags: ClientFlags, pub teams_in_game: u8, pub team_indices: Vec, - pub clan: Option, - pub is_joined_mid_game: bool, + pub clan: Option } impl HWClient { @@ -22,14 +31,30 @@ room_id: None, nick: String::new(), protocol_number: 0, - is_admin: false, - is_master: false, - is_ready: false, - is_in_game: false, + flags: ClientFlags::DEFAULT, teams_in_game: 0, team_indices: Vec::new(), clan: None, - is_joined_mid_game: false, } } + + fn contains(& self, mask: ClientFlags) -> bool { + self.flags.contains(mask) + } + + fn set(&mut self, mask: ClientFlags, value: bool) { + self.flags.set(mask, value); + } + + pub fn is_admin(&self)-> bool { self.contains(ClientFlags::IS_ADMIN) } + pub fn is_master(&self)-> bool { self.contains(ClientFlags::IS_MASTER) } + pub fn is_ready(&self)-> bool { self.contains(ClientFlags::IS_READY) } + pub fn is_in_game(&self)-> bool { self.contains(ClientFlags::IS_IN_GAME) } + pub fn is_joined_mid_game(&self)-> bool { self.contains(ClientFlags::IS_JOINED_MID_GAME) } + + pub fn set_is_admin(&mut self, value: bool) { self.set(ClientFlags::IS_ADMIN, value) } + pub fn set_is_master(&mut self, value: bool) { self.set(ClientFlags::IS_MASTER, value) } + pub fn set_is_ready(&mut self, value: bool) { self.set(ClientFlags::IS_READY, value) } + pub fn set_is_in_game(&mut self, value: bool) { self.set(ClientFlags::IS_IN_GAME, value) } + pub fn set_is_joined_mid_game(&mut self, value: bool) { self.set(ClientFlags::IS_JOINED_MID_GAME, value) } } \ No newline at end of file diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/server/handlers/common.rs --- a/gameServer2/src/server/handlers/common.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/server/handlers/common.rs Sat Jul 21 02:06:13 2018 +0200 @@ -1,30 +1,21 @@ use protocol::messages::{ HWProtocolMessage::{self, Rnd}, HWServerMessage::{self, ChatMsg}, }; -use rand::{self, Rng}; -use server::{actions::Action, room::HWRoom, server::HWServer}; +use rand::{self, Rng, thread_rng}; +use server::{actions::Action, server::HWServer}; -pub fn rnd_action(options: Vec, room: Option<&mut HWRoom>) -> Vec { - if let Some(room) = room { - let msg = rnd_reply(options); - vec![msg.send_all().in_room(room.id).action()] +pub fn rnd_reply(options: &[String]) -> HWServerMessage { + let mut rng = thread_rng(); + let reply = if options.is_empty() { + (*rng.choose(&["heads", "tails"]).unwrap()).to_owned() } else { - Vec::new() - } -} + rng.choose(&options).unwrap().clone() + }; -fn rnd_reply(options: Vec) -> HWServerMessage { - let options = if options.is_empty() { - vec!["heads".to_owned(), "tails".to_owned()] - } else { - options - }; - let reply = rand::thread_rng().choose(&options).unwrap(); - let msg = ChatMsg { + ChatMsg { nick: "[random]".to_owned(), msg: reply.clone(), - }; - msg + } } #[cfg(test)] @@ -45,7 +36,7 @@ fn run_handle_test(opts: Vec) { let opts2 = opts.clone(); for opt in opts { - while reply2string(rnd_reply(opts2.clone())) != opt {} + while reply2string(rnd_reply(&opts2)) != opt {} } } @@ -72,7 +63,7 @@ while tries < 1000 || ((ones as f64 / tries as f64) - lim).abs() >= eps { tries += 1; - if reply2string(rnd_reply(opts.clone())) == 1.to_string() { + if reply2string(rnd_reply(&opts)) == 1.to_string() { ones += 1; } } diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/server/handlers/inroom.rs --- a/gameServer2/src/server/handlers/inroom.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/server/handlers/inroom.rs Sat Jul 21 02:06:13 2018 +0200 @@ -6,15 +6,18 @@ server_chat }; use server::{ - coretypes::{ClientId, Voting, VoteType}, + coretypes::{ClientId, RoomId, Voting, VoteType}, server::HWServer, - room::HWRoom, + room::{HWRoom, RoomFlags}, 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_action; +use super::common::rnd_reply; #[derive(Clone)] struct ByMsg<'a> { @@ -35,8 +38,8 @@ } } -fn by_msg(source: &Vec) -> ByMsg { - ByMsg {messages: &source[..]} +fn by_msg(source: &[u8]) -> ByMsg { + ByMsg {messages: source} } const VALID_MESSAGES: &[u8] = @@ -81,7 +84,29 @@ }) } -pub fn handle(server: &mut HWServer, client_id: ClientId, message: HWProtocolMessage) { +fn room_message_flag(msg: &HWProtocolMessage) -> RoomFlags { + use protocol::messages::HWProtocolMessage::*; + match msg { + ToggleRestrictJoin => RoomFlags::RESTRICTED_JOIN, + ToggleRestrictTeams => RoomFlags::RESTRICTED_TEAM_ADD, + ToggleRegisteredOnly => RoomFlags::RESTRICTED_UNREGISTERED_PLAYERS, + _ => RoomFlags::empty() + } +} + +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 { Part(None) => server.react(client_id, vec![ @@ -91,28 +116,24 @@ Chat(msg) => { let actions = { let c = &mut server.clients[client_id]; - let chat_msg = ChatMsg {nick: c.nick.clone(), msg: msg}; - if let Some(room_id) = c.room_id { - vec![chat_msg.send_all().in_room(room_id).but_self().action()] - } else { - Vec::new() - } + let chat_msg = ChatMsg {nick: c.nick.clone(), msg}; + vec![chat_msg.send_all().in_room(room_id).but_self().action()] }; server.react(client_id, actions); }, Fix => { if let (c, Some(r)) = server.client_and_room(client_id) { - if c.is_admin { r.is_fixed = true } + if c.is_admin() { r.set_is_fixed(true) } } } Unfix => { if let (c, Some(r)) = server.client_and_room(client_id) { - if c.is_admin { r.is_fixed = false } + if c.is_admin() { r.set_is_fixed(false) } } } Greeting(text) => { if let (c, Some(r)) = server.client_and_room(client_id) { - if c.is_admin || c.is_master && !r.is_fixed { + if c.is_admin() || c.is_master() && !r.is_fixed() { r.greeting = text } } @@ -121,35 +142,32 @@ let actions = if is_name_illegal(&new_name) { vec![Warn("Illegal room name! A room name must be between 1-40 characters long, must not have a trailing or leading space and must not have any of these characters: $()*+?[]^{|}".to_string())] - } else if server.room(client_id).map(|r| r.is_fixed).unwrap_or(false) { + } else if server.rooms[room_id].is_fixed() { vec![Warn("Access denied.".to_string())] } else if server.has_room(&new_name) { vec![Warn("A room with the same name already exists.".to_string())] } else { let mut old_name = new_name.clone(); - if let (_, Some(r)) = server.client_and_room(client_id) { - swap(&mut r.name, &mut old_name); - vec![SendRoomUpdate(Some(old_name))] - } else { - Vec::new() - } + swap(&mut server.rooms[room_id].name, &mut old_name); + vec![SendRoomUpdate(Some(old_name))] }; server.react(client_id, actions); }, ToggleReady => { let actions = if let (c, Some(r)) = server.client_and_room(client_id) { - let flags = if c.is_ready { + let flags = if c.is_ready() { r.ready_players_number -= 1; "-r" } else { r.ready_players_number += 1; "+r" }; - c.is_ready = !c.is_ready; + let is_ready = !c.is_ready(); + c.set_is_ready(is_ready); let mut v = vec![ClientFlags(flags.to_string(), vec![c.nick.clone()]) .send_all().in_room(r.id).action()]; - if r.is_fixed && r.ready_players_number as u32 == r.players_number { + if r.is_fixed() && r.ready_players_number == r.players_number { v.push(StartRoomGame(r.id)) } v @@ -161,7 +179,6 @@ AddTeam(info) => { let mut actions = Vec::new(); if let (c, Some(r)) = server.client_and_room(client_id) { - let room_id = r.id; if r.teams.len() >= r.team_limit as usize { actions.push(Warn("Too many teams!".to_string())) } else if r.addable_hedgehogs() == 0 { @@ -170,8 +187,10 @@ actions.push(Warn("There's already a team with same name in the list.".to_string())) } else if r.game_info.is_some() { actions.push(Warn("Joining not possible: Round is in progress.".to_string())) + } else if r.is_team_add_restricted() { + actions.push(Warn("This room currently does not allow adding new teams.".to_string())); } else { - let team = r.add_team(c.id, info); + let team = r.add_team(c.id, *info); c.teams_in_game += 1; c.clan = Some(team.color); actions.push(TeamAccepted(team.name.clone()) @@ -206,10 +225,9 @@ }, SetHedgehogsNumber(team_name, number) => { let actions = if let (c, Some(r)) = server.client_and_room(client_id) { - let room_id = r.id; let addable_hedgehogs = r.addable_hedgehogs(); if let Some((_, mut team)) = r.find_team_and_owner_mut(|t| t.name == team_name) { - if !c.is_master { + if !c.is_master() { vec![ProtocolError("You're not the room master!".to_string())] } else if number < 1 || number > 8 || number > addable_hedgehogs + team.hedgehogs_number { @@ -231,9 +249,8 @@ SetTeamColor(team_name, color) => { let mut owner_id = None; let actions = if let (c, Some(r)) = server.client_and_room(client_id) { - let room_id = r.id; if let Some((owner, mut team)) = r.find_team_and_owner_mut(|t| t.name == team_name) { - if !c.is_master { + if !c.is_master() { vec![ProtocolError("You're not the room master!".to_string())] } else if false { Vec::new() @@ -258,9 +275,9 @@ }, Cfg(cfg) => { let actions = if let (c, Some(r)) = server.client_and_room(client_id) { - if r.is_fixed { + if r.is_fixed() { vec![Warn("Access denied.".to_string())] - } else if !c.is_master { + } else if !c.is_master() { vec![ProtocolError("You're not the room master!".to_string())] } else { let v = vec![cfg.to_server_msg() @@ -273,33 +290,98 @@ }; server.react(client_id, actions); } + Save(name, location) => { + let actions = vec![server_chat(format!("Room config saved as {}", name)) + .send_all().in_room(room_id).action()]; + 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))] + } else { + vec![server_chat(format!("Room config {} has been deleted", name)) + .send_all().in_room(room_id).action()] + }; + server.react(client_id, actions); + } CallVote(None) => { server.react(client_id, vec![ - server_chat("Available callvote commands: kick , map , pause, newseed, hedgehogs ") + server_chat("Available callvote commands: kick , map , pause, newseed, hedgehogs ".to_string()) .send_self().action()]) } CallVote(Some(kind)) => { - let (room_id, is_in_game) = server.room(client_id) - .map(|r| (r.id, r.game_info.is_some())).unwrap(); + let is_in_game = server.rooms[room_id].game_info.is_some(); let error = match &kind { VoteType::Kick(nick) => { if server.find_client(&nick).filter(|c| c.room_id == Some(room_id)).is_some() { None } else { - Some("/callvote kick: No such user!") + Some("/callvote kick: No such user!".to_string()) } }, VoteType::Map(None) => { - Some("/callvote map: Not implemented") + let names: Vec<_> = server.rooms[room_id].saves.keys().cloned().collect(); + if names.is_empty() { + Some("/callvote map: No maps saved in this room!".to_string()) + } else { + Some(format!("Available maps: {}", names.join(", "))) + } }, VoteType::Map(Some(name)) => { - Some("/callvote map: Not implemented") + if server.rooms[room_id].saves.get(&name[..]).is_some() { + None + } else { + Some("/callvote map: No such map!".to_string()) + } }, VoteType::Pause => { if is_in_game { None } else { - Some("/callvote pause: No game in progress!") + Some("/callvote pause: No game in progress!".to_string()) } }, VoteType::NewSeed => { @@ -308,7 +390,7 @@ VoteType::HedgehogsPerTeam(number) => { match number { 1...8 => None, - _ => Some("/callvote hedgehogs: Specify number from 1 to 8.") + _ => Some("/callvote hedgehogs: Specify number from 1 to 8.".to_string()) } }, }; @@ -316,9 +398,9 @@ None => { let msg = voting_description(&kind); let voting = Voting::new(kind, server.room_clients(client_id)); - server.room(client_id).unwrap().voting = Some(voting); + server.rooms[room_id].voting = Some(voting); server.react(client_id, vec![ - server_chat(&msg).send_all().in_room(room_id).action(), + server_chat(msg).send_all().in_room(room_id).action(), AddVote{ vote: true, is_forced: false}]); } Some(msg) => { @@ -328,28 +410,20 @@ } } Vote(vote) => { - let actions = if let (c, Some(r)) = server.client_and_room(client_id) { - vec![AddVote{ vote, is_forced: false }] - } else { - Vec::new() - }; - server.react(client_id, actions); + server.react(client_id, vec![AddVote{ vote, is_forced: false }]); } ForceVote(vote) => { - let actions = if let (c, Some(r)) = server.client_and_room(client_id) { - vec![AddVote{ vote, is_forced: c.is_admin} ] - } else { - Vec::new() - }; - server.react(client_id, actions); + let is_forced = server.clients[client_id].is_admin(); + server.react(client_id, vec![AddVote{ vote, is_forced }]); + } + ToggleRestrictJoin | ToggleRestrictTeams | ToggleRegisteredOnly => { + if server.clients[client_id].is_master() { + server.rooms[room_id].flags.toggle(room_message_flag(&message)); + } + server.react(client_id, vec![SendRoomUpdate(None)]); } StartGame => { - let actions = if let (_, Some(r)) = server.client_and_room(client_id) { - vec![StartRoomGame(r.id)] - } else { - Vec::new() - }; - server.react(client_id, actions); + server.react(client_id, vec![StartRoomGame(room_id)]); } EngineMessage(em) => { let mut actions = Vec::new(); @@ -383,8 +457,8 @@ RoundFinished => { let mut actions = Vec::new(); if let (c, Some(r)) = server.client_and_room(client_id) { - if c.is_in_game { - c.is_in_game = false; + if c.is_in_game() { + c.set_is_in_game(false); actions.push(ClientFlags("-g".to_string(), vec![c.nick.clone()]). send_all().in_room(r.id).action()); if r.game_info.is_some() { @@ -397,8 +471,16 @@ server.react(client_id, actions) }, Rnd(v) => { - let actions = rnd_action(v, server.room(client_id)); - server.react(client_id, actions) + let result = rnd_reply(&v); + let mut echo = vec!["/rnd".to_string()]; + echo.extend(v.into_iter()); + let chat_msg = ChatMsg { + nick: server.clients[client_id].nick.clone(), + msg: echo.join(" ") + }; + server.react(client_id, vec![ + chat_msg.send_all().in_room(room_id).action(), + result.send_all().in_room(room_id).action()]) }, _ => warn!("Unimplemented!") } diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/server/handlers/lobby.rs --- a/gameServer2/src/server/handlers/lobby.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/server/handlers/lobby.rs Sat Jul 21 02:06:13 2018 +0200 @@ -10,7 +10,7 @@ HWServerMessage::* }; use utils::is_name_illegal; -use super::common::rnd_action; +use super::common::rnd_reply; pub fn handle(server: &mut HWServer, client_id: ClientId, message: HWProtocolMessage) { use protocol::messages::HWProtocolMessage::*; @@ -31,8 +31,9 @@ server.react(client_id, actions); }, Chat(msg) => { - let chat_msg = ChatMsg {nick: server.clients[client_id].nick.clone(), msg: msg}; - server.react(client_id, vec![chat_msg.send_all().but_self().action()]); + let actions = vec![ChatMsg {nick: server.clients[client_id].nick.clone(), msg} + .send_all().in_room(server.lobby_id).but_self().action()]; + server.react(client_id, actions); }, JoinRoom(name, password) => { let actions; @@ -48,6 +49,10 @@ actions = if let Some((_, r)) = room { if c.protocol_number != r.protocol_number { vec![Warn("Room version incompatible to your Hedgewars version!".to_string())] + } else if r.is_join_restricted() { + vec![Warn("Access denied. This room currently doesn't allow joining.".to_string())] + } else if r.players_number == u8::max_value() { + vec![Warn("This room is already full".to_string())] } else { vec![MoveToRoom(r.id), RoomJoined(nicks).send_self().action()] @@ -59,8 +64,7 @@ server.react(client_id, actions); }, Rnd(v) => { - let actions = rnd_action(v, server.room(client_id)); - server.react(client_id, actions) + server.react(client_id, vec![rnd_reply(&v).send_self().action()]); }, List => warn!("Deprecated LIST message received"), _ => warn!("Incorrect command in lobby state"), diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/server/handlers/mod.rs --- a/gameServer2/src/server/handlers/mod.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/server/handlers/mod.rs Sat Jul 21 02:06:13 2018 +0200 @@ -1,36 +1,38 @@ use mio; -use std::io::Write; -use std::io; +use std::{io, io::Write}; -use super::server::HWServer; -use super::actions::Action; -use super::actions::Action::*; -use protocol::messages::HWProtocolMessage; -use protocol::messages::HWServerMessage::*; - +use super::{ + server::HWServer, + actions::{Action, Action::*}, + coretypes::ClientId +}; +use protocol::messages::{ + HWProtocolMessage, + HWServerMessage::* +}; mod common; mod loggingin; mod lobby; mod inroom; -pub fn handle(server: &mut HWServer, token: usize, message: HWProtocolMessage) { +pub fn handle(server: &mut HWServer, client_id: ClientId, message: HWProtocolMessage) { match message { HWProtocolMessage::Ping => - server.react(token, vec![Pong.send_self().action()]), + server.react(client_id, vec![Pong.send_self().action()]), HWProtocolMessage::Quit(Some(msg)) => - server.react(token, vec![ByeClient("User quit: ".to_string() + &msg)]), + server.react(client_id, vec![ByeClient("User quit: ".to_string() + &msg)]), HWProtocolMessage::Quit(None) => - server.react(token, vec![ByeClient("User quit".to_string())]), + server.react(client_id, vec![ByeClient("User quit".to_string())]), HWProtocolMessage::Malformed => warn!("Malformed/unknown message"), HWProtocolMessage::Empty => warn!("Empty message"), _ => { - match server.clients[token].room_id { + match server.clients[client_id].room_id { None => - loggingin::handle(server, token, message), + loggingin::handle(server, client_id, message), Some(id) if id == server.lobby_id => - lobby::handle(server, token, message), - _ => - inroom::handle(server, token, message) + lobby::handle(server, client_id, message), + Some(id) => + inroom::handle(server, client_id, id, message) } }, } diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/server/network.rs --- a/gameServer2/src/server/network.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/server/network.rs Sat Jul 21 02:06:13 2018 +0200 @@ -105,14 +105,14 @@ } pub fn send_raw_msg(&mut self, msg: &[u8]) { - self.buf_out.write(msg).unwrap(); + self.buf_out.write_all(msg).unwrap(); } - pub fn send_string(&mut self, msg: &String) { + pub fn send_string(&mut self, msg: &str) { self.send_raw_msg(&msg.as_bytes()); } - pub fn send_msg(&mut self, msg: HWServerMessage) { + pub fn send_msg(&mut self, msg: &HWServerMessage) { self.send_string(&msg.to_raw_protocol()); } } @@ -143,7 +143,7 @@ let mut client_exists = false; if let Some(ref client) = self.clients.get(id) { poll.deregister(&client.socket) - .ok().expect("could not deregister socket"); + .expect("could not deregister socket"); info!("client {} ({}) removed", client.id, client.peer_addr); client_exists = true; } @@ -156,7 +156,7 @@ poll.register(&client_socket, Token(id), Ready::readable() | Ready::writable(), PollOpt::edge()) - .ok().expect("could not register socket with event loop"); + .expect("could not register socket with event loop"); let entry = self.clients.vacant_entry(); let client = NetworkClient::new(id, client_socket, addr); @@ -189,7 +189,7 @@ Ok(()) } - fn operation_failed(&mut self, poll: &Poll, client_id: ClientId, error: Error, msg: &str) -> io::Result<()> { + fn operation_failed(&mut self, poll: &Poll, client_id: ClientId, error: &Error, msg: &str) -> io::Result<()> { let addr = if let Some(ref mut client) = self.clients.get_mut(client_id) { client.peer_addr } else { @@ -224,7 +224,7 @@ }; } Err(e) => self.operation_failed( - poll, client_id, e, + poll, client_id, &e, "Error while reading from client socket")? } @@ -256,7 +256,7 @@ }, Ok(_) => {} Err(e) => self.operation_failed( - poll, client_id, e, + poll, client_id, &e, "Error while writing to client socket")? } diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/server/room.rs --- a/gameServer2/src/server/room.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/server/room.rs Sat Jul 21 02:06:13 2018 +0200 @@ -1,24 +1,29 @@ -use std::{iter}; +use std::{ + iter, collections::HashMap +}; use server::{ coretypes::{ClientId, RoomId, TeamInfo, GameCfg, GameCfg::*, Voting}, client::{HWClient} }; +use serde::{Serialize, Deserialize}; +use serde_yaml; -const MAX_HEDGEHOGS_IN_ROOM: u8 = 48; +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, @@ -53,7 +58,7 @@ } } -fn client_teams_impl(teams: &Vec<(ClientId, TeamInfo)>, client_id: ClientId) +fn client_teams_impl(teams: &[(ClientId, TeamInfo)], client_id: ClientId) -> impl Iterator + Clone { teams.iter().filter(move |(id, _)| *id == client_id).map(|(_, t)| t) @@ -106,22 +111,38 @@ } } +#[derive(Serialize, Deserialize)] +pub struct RoomSave { + pub location: String, + config: RoomConfig +} + +bitflags!{ + pub struct RoomFlags: u8 { + const FIXED = 0b0000_0001; + const RESTRICTED_JOIN = 0b0000_0010; + const RESTRICTED_TEAM_ADD = 0b0000_0100; + const RESTRICTED_UNREGISTERED_PLAYERS = 0b0000_1000; + } +} + pub struct HWRoom { pub id: RoomId, pub master_id: Option, pub name: String, pub password: Option, - pub protocol_number: u32, pub greeting: String, - pub is_fixed: bool, + pub protocol_number: u16, + pub flags: RoomFlags, - pub players_number: u32, + pub players_number: u8, pub default_hedgehog_number: u8, pub team_limit: u8, pub ready_players_number: u8, pub teams: Vec<(ClientId, TeamInfo)>, config: RoomConfig, pub voting: Option, + pub saves: HashMap, pub game_info: Option } @@ -133,15 +154,16 @@ name: String::new(), password: None, greeting: "".to_string(), - is_fixed: false, + flags: RoomFlags::empty(), protocol_number: 0, players_number: 0, default_hedgehog_number: 4, - team_limit: 8, + team_limit: MAX_TEAMS_IN_ROOM, ready_players_number: 0, teams: Vec::new(), config: RoomConfig::new(), voting: None, + saves: HashMap::new(), game_info: None } } @@ -250,11 +272,47 @@ } } + pub fn is_fixed(&self) -> bool { + self.flags.contains(RoomFlags::FIXED) + } + pub fn is_join_restricted(&self) -> bool { + self.flags.contains(RoomFlags::RESTRICTED_JOIN) + } + pub fn is_team_add_restricted(&self) -> bool { + self.flags.contains(RoomFlags::RESTRICTED_TEAM_ADD) + } + pub fn are_unregistered_players_restricted(&self) -> bool { + self.flags.contains(RoomFlags::RESTRICTED_UNREGISTERED_PLAYERS) + } + + pub fn set_is_fixed(&mut self, value: bool) { + self.flags.set(RoomFlags::FIXED, value) + } + pub fn set_join_restriction(&mut self, value: bool) { + self.flags.set(RoomFlags::RESTRICTED_JOIN, value) + } + pub fn set_team_add_restriction(&mut self, value: bool) { + self.flags.set(RoomFlags::RESTRICTED_TEAM_ADD, value) + } + pub fn set_unregistered_players_restriction(&mut self, value: bool) { + self.flags.set(RoomFlags::RESTRICTED_UNREGISTERED_PLAYERS, value) + } + + fn flags_string(&self) -> String { + let mut result = "-".to_string(); + if self.game_info.is_some() { result += "g" } + if self.password.is_some() { result += "p" } + if self.is_join_restricted() { result += "j" } + if self.are_unregistered_players_restricted() { + result += "r" + } + result + } + pub fn info(&self, master: Option<&HWClient>) -> Vec { - let flags = "-".to_string(); let c = &self.config; vec![ - flags, + self.flags_string(), self.name.clone(), self.players_number.to_string(), self.teams.len().to_string(), @@ -280,6 +338,34 @@ } } + pub fn save_config(&mut self, name: String, location: String) { + self.saves.insert(name, RoomSave { location, config: self.config.clone() }); + } + + pub fn load_config(&mut self, name: &str) -> Option<&str> { + if let Some(save) = self.saves.get(name) { + self.config = save.config.clone(); + Some(&save.location[..]) + } else { + None + } + } + + pub fn delete_config(&mut self, name: &str) -> bool { + 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(), diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/server/server.rs --- a/gameServer2/src/server/server.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/server/server.rs Sat Jul 21 02:06:13 2018 +0200 @@ -40,7 +40,7 @@ let client = HWClient::new(entry.key()); entry.insert(client); } - self.send(key, Destination::ToSelf, HWServerMessage::Connected(utils::PROTOCOL_VERSION)); + self.send(key, &Destination::ToSelf, HWServerMessage::Connected(utils::PROTOCOL_VERSION)); key } @@ -64,8 +64,8 @@ } } - fn get_recipients(&self, client_id: ClientId, destination: Destination) -> Vec { - let mut ids = match destination { + fn get_recipients(&self, client_id: ClientId, destination: &Destination) -> Vec { + let mut ids = match *destination { Destination::ToSelf => vec![client_id], Destination::ToId(id) => vec![id], Destination::ToAll {room_id: Some(id), ..} => @@ -83,8 +83,8 @@ ids } - pub fn send(&mut self, client_id: ClientId, destination: Destination, message: HWServerMessage) { - let ids = self.get_recipients(client_id, destination); + pub fn send(&mut self, client_id: ClientId, destination: &Destination, message: HWServerMessage) { + let ids = self.get_recipients(client_id, &destination); self.output.push((ids, message)); } @@ -94,6 +94,8 @@ } } + pub fn lobby(&self) -> &HWRoom { &self.rooms[self.lobby_id] } + pub fn has_room(&self, name: &str) -> bool { self.rooms.iter().any(|(_, r)| r.name == name) } @@ -124,7 +126,7 @@ self.select_clients(|(_, c)| c.room_id == Some(room_id)) } - pub fn protocol_clients(&self, protocol: u32) -> Vec { + pub fn protocol_clients(&self, protocol: u16) -> Vec { self.select_clients(|(_, c)| c.protocol_number == protocol) } diff -r 0c8001e43fd3 -r 395a4c92e523 gameServer2/src/utils.rs --- a/gameServer2/src/utils.rs Sat Jul 21 00:34:32 2018 +0200 +++ b/gameServer2/src/utils.rs Sat Jul 21 02:06:13 2018 +0200 @@ -3,7 +3,7 @@ use base64::{encode}; pub const PROTOCOL_VERSION : u32 = 3; -pub const SERVER: mio::Token = mio::Token(1000000000 + 0); +pub const SERVER: mio::Token = mio::Token(1_000_000_000); pub fn is_name_illegal(name: &str ) -> bool{ name.len() > 40 ||