gameServer2/src/protocol/messages.rs
changeset 14420 06672690d71b
parent 14419 6843c4551cde
child 14421 96624a6cdb93
equal deleted inserted replaced
14419:6843c4551cde 14420:06672690d71b
     1 use crate::server::coretypes::{
       
     2     ServerVar, GameCfg, TeamInfo,
       
     3     HedgehogInfo, VoteType
       
     4 };
       
     5 use std::{ops, convert::From, iter::once};
       
     6 
       
     7 #[derive(PartialEq, Eq, Clone, Debug)]
       
     8 pub enum HWProtocolMessage {
       
     9     // core
       
    10     Ping,
       
    11     Pong,
       
    12     Quit(Option<String>),
       
    13     //Cmd(String, Vec<String>),
       
    14     Global(String),
       
    15     Watch(String),
       
    16     ToggleServerRegisteredOnly,
       
    17     SuperPower,
       
    18     Info(String),
       
    19     // not entered state
       
    20     Nick(String),
       
    21     Proto(u16),
       
    22     Password(String, String),
       
    23     Checker(u16, String, String),
       
    24     // lobby
       
    25     List,
       
    26     Chat(String),
       
    27     CreateRoom(String, Option<String>),
       
    28     JoinRoom(String, Option<String>),
       
    29     Follow(String),
       
    30     Rnd(Vec<String>),
       
    31     Kick(String),
       
    32     Ban(String, String, u32),
       
    33     BanIP(String, String, u32),
       
    34     BanNick(String, String, u32),
       
    35     BanList,
       
    36     Unban(String),
       
    37     SetServerVar(ServerVar),
       
    38     GetServerVar,
       
    39     RestartServer,
       
    40     Stats,
       
    41     // in room
       
    42     Part(Option<String>),
       
    43     Cfg(GameCfg),
       
    44     AddTeam(Box<TeamInfo>),
       
    45     RemoveTeam(String),
       
    46     SetHedgehogsNumber(String, u8),
       
    47     SetTeamColor(String, u8),
       
    48     ToggleReady,
       
    49     StartGame,
       
    50     EngineMessage(String),
       
    51     RoundFinished,
       
    52     ToggleRestrictJoin,
       
    53     ToggleRestrictTeams,
       
    54     ToggleRegisteredOnly,
       
    55     RoomName(String),
       
    56     Delegate(String),
       
    57     TeamChat(String),
       
    58     MaxTeams(u8),
       
    59     Fix,
       
    60     Unfix,
       
    61     Greeting(String),
       
    62     CallVote(Option<VoteType>),
       
    63     Vote(bool),
       
    64     ForceVote(bool),
       
    65     Save(String, String),
       
    66     Delete(String),
       
    67     SaveRoom(String),
       
    68     LoadRoom(String),
       
    69     Malformed,
       
    70     Empty,
       
    71 }
       
    72 
       
    73 #[derive(Debug)]
       
    74 pub enum HWServerMessage {
       
    75     Ping,
       
    76     Pong,
       
    77     Bye(String),
       
    78     Nick(String),
       
    79     Proto(u16),
       
    80     ServerAuth(String),
       
    81     LobbyLeft(String, String),
       
    82     LobbyJoined(Vec<String>),
       
    83     ChatMsg {nick: String, msg: String},
       
    84     ClientFlags(String, Vec<String>),
       
    85     Rooms(Vec<String>),
       
    86     RoomAdd(Vec<String>),
       
    87     RoomJoined(Vec<String>),
       
    88     RoomLeft(String, String),
       
    89     RoomRemove(String),
       
    90     RoomUpdated(String, Vec<String>),
       
    91     TeamAdd(Vec<String>),
       
    92     TeamRemove(String),
       
    93     TeamAccepted(String),
       
    94     TeamColor(String, u8),
       
    95     HedgehogsNumber(String, u8),
       
    96     ConfigEntry(String, Vec<String>),
       
    97     Kicked,
       
    98     RunGame,
       
    99     ForwardEngineMessage(Vec<String>),
       
   100     RoundFinished,
       
   101 
       
   102     ServerMessage(String),
       
   103     Notice(String),
       
   104     Warning(String),
       
   105     Error(String),
       
   106     Connected(u32),
       
   107     Unreachable,
       
   108 
       
   109     //Deprecated messages
       
   110     LegacyReady(bool, Vec<String>)
       
   111 }
       
   112 
       
   113 pub fn server_chat(msg: String) -> HWServerMessage  {
       
   114     HWServerMessage::ChatMsg{ nick: "[server]".to_string(), msg }
       
   115 }
       
   116 
       
   117 impl GameCfg {
       
   118     pub fn to_protocol(&self) -> (String, Vec<String>) {
       
   119         use crate::server::coretypes::GameCfg::*;
       
   120         match self {
       
   121             FeatureSize(s) => ("FEATURE_SIZE".to_string(), vec![s.to_string()]),
       
   122             MapType(t) => ("MAP".to_string(), vec![t.to_string()]),
       
   123             MapGenerator(g) => ("MAPGEN".to_string(), vec![g.to_string()]),
       
   124             MazeSize(s) => ("MAZE_SIZE".to_string(), vec![s.to_string()]),
       
   125             Seed(s) => ("SEED".to_string(), vec![s.to_string()]),
       
   126             Template(t) => ("TEMPLATE".to_string(), vec![t.to_string()]),
       
   127 
       
   128             Ammo(n, None) => ("AMMO".to_string(), vec![n.to_string()]),
       
   129             Ammo(n, Some(s)) => ("AMMO".to_string(), vec![n.to_string(), s.to_string()]),
       
   130             Scheme(n, s) if s.is_empty() => ("SCHEME".to_string(), vec![n.to_string()]),
       
   131             Scheme(n, s) => ("SCHEME".to_string(), {
       
   132                 let mut v = vec![n.to_string()];
       
   133                 v.extend(s.clone().into_iter());
       
   134                 v
       
   135             }),
       
   136             Script(s) => ("SCRIPT".to_string(), vec![s.to_string()]),
       
   137             Theme(t) => ("THEME".to_string(), vec![t.to_string()]),
       
   138             DrawnMap(m) => ("DRAWNMAP".to_string(), vec![m.to_string()])
       
   139         }
       
   140     }
       
   141 
       
   142     pub fn to_server_msg(&self) -> HWServerMessage {
       
   143         use self::HWServerMessage::ConfigEntry;
       
   144         let (name, args) = self.to_protocol();
       
   145         HWServerMessage::ConfigEntry(name, args)
       
   146     }
       
   147 }
       
   148 
       
   149 macro_rules! const_braces {
       
   150     ($e: expr) => { "{}\n" }
       
   151 }
       
   152 
       
   153 macro_rules! msg {
       
   154     [$($part: expr),*] => {
       
   155         format!(concat!($(const_braces!($part)),*, "\n"), $($part),*);
       
   156     };
       
   157 }
       
   158 
       
   159 #[cfg(test)]
       
   160 macro_rules! several {
       
   161     [$part: expr] => { once($part) };
       
   162     [$part: expr, $($other: expr),*] => { once($part).chain(several![$($other),*]) };
       
   163 }
       
   164 
       
   165 impl HWProtocolMessage {
       
   166     /** Converts the message to a raw `String`, which can be sent over the network.
       
   167      *
       
   168      * This is the inverse of the `message` parser.
       
   169      */
       
   170     #[cfg(test)]
       
   171     pub(crate) fn to_raw_protocol(&self) -> String {
       
   172         use self::HWProtocolMessage::*;
       
   173         match self {
       
   174             Ping => msg!["PING"],
       
   175             Pong => msg!["PONG"],
       
   176             Quit(None) => msg!["QUIT"],
       
   177             Quit(Some(msg)) => msg!["QUIT", msg],
       
   178             Global(msg) => msg!["CMD", format!("GLOBAL {}", msg)],
       
   179             Watch(name) => msg!["CMD", format!("WATCH {}", name)],
       
   180             ToggleServerRegisteredOnly => msg!["CMD", "REGISTERED_ONLY"],
       
   181             SuperPower =>  msg!["CMD", "SUPER_POWER"],
       
   182             Info(info) => msg!["CMD", format!("INFO {}", info)],
       
   183             Nick(nick) => msg!("NICK", nick),
       
   184             Proto(version) => msg!["PROTO", version],
       
   185             Password(p, s) => msg!["PASSWORD", p, s],
       
   186             Checker(i, n, p) => msg!["CHECKER", i, n, p],
       
   187             List => msg!["LIST"],
       
   188             Chat(msg) => msg!["CHAT", msg],
       
   189             CreateRoom(name, None) => msg!["CREATE_ROOM", name],
       
   190             CreateRoom(name, Some(password)) =>
       
   191                 msg!["CREATE_ROOM", name, password],
       
   192             JoinRoom(name, None) => msg!["JOIN_ROOM", name],
       
   193             JoinRoom(name, Some(password)) =>
       
   194                 msg!["JOIN_ROOM", name, password],
       
   195             Follow(name) => msg!["FOLLOW", name],
       
   196             Rnd(args) => if args.is_empty() {
       
   197                 msg!["CMD", "RND"]
       
   198             } else {
       
   199                 msg!["CMD", format!("RND {}", args.join(" "))]
       
   200             },
       
   201             Kick(name) => msg!["KICK", name],
       
   202             Ban(name, reason, time) => msg!["BAN", name, reason, time],
       
   203             BanIP(ip, reason, time) => msg!["BAN_IP", ip, reason, time],
       
   204             BanNick(nick, reason, time) =>
       
   205                 msg!("BAN_NICK", nick, reason, time),
       
   206             BanList => msg!["BANLIST"],
       
   207             Unban(name) => msg!["UNBAN", name],
       
   208             //SetServerVar(ServerVar), ???
       
   209             GetServerVar => msg!["GET_SERVER_VAR"],
       
   210             RestartServer => msg!["CMD", "RESTART_SERVER YES"],
       
   211             Stats => msg!["CMD", "STATS"],
       
   212             Part(None) => msg!["PART"],
       
   213             Part(Some(msg)) => msg!["PART", msg],
       
   214             Cfg(config) => {
       
   215                 let (name, args) = config.to_protocol();
       
   216                 msg!["CFG", name, args.join("\n")]
       
   217             },
       
   218             AddTeam(info) =>
       
   219                 msg!["ADD_TEAM", info.name, info.color, info.grave, info.fort,
       
   220                      info.voice_pack, info.flag, info.difficulty,
       
   221                      info.hedgehogs.iter()
       
   222                         .flat_map(|h| several![&h.name[..], &h.hat[..]])
       
   223                         .collect::<Vec<_>>().join("\n")],
       
   224             RemoveTeam(name) => msg!["REMOVE_TEAM", name],
       
   225             SetHedgehogsNumber(team, number) => msg!["HH_NUM", team, number],
       
   226             SetTeamColor(team, color) => msg!["TEAM_COLOR", team, color],
       
   227             ToggleReady => msg!["TOGGLE_READY"],
       
   228             StartGame => msg!["START_GAME"],
       
   229             EngineMessage(msg) => msg!["EM", msg],
       
   230             RoundFinished => msg!["ROUNDFINISHED"],
       
   231             ToggleRestrictJoin => msg!["TOGGLE_RESTRICT_JOINS"],
       
   232             ToggleRestrictTeams => msg!["TOGGLE_RESTRICT_TEAMS"],
       
   233             ToggleRegisteredOnly => msg!["TOGGLE_REGISTERED_ONLY"],
       
   234             RoomName(name) => msg!["ROOM_NAME", name],
       
   235             Delegate(name) => msg!["CMD", format!("DELEGATE {}", name)],
       
   236             TeamChat(msg) => msg!["TEAMCHAT", msg],
       
   237             MaxTeams(count) => msg!["CMD", format!("MAXTEAMS {}", count)] ,
       
   238             Fix => msg!["CMD", "FIX"],
       
   239             Unfix => msg!["CMD", "UNFIX"],
       
   240             Greeting(msg) => msg!["CMD", format!("GREETING {}", msg)],
       
   241             //CallVote(Option<(String, Option<String>)>) =>, ??
       
   242             Vote(msg) => msg!["CMD", format!("VOTE {}", if *msg {"YES"} else {"NO"})],
       
   243             ForceVote(msg) => msg!["CMD", format!("FORCE {}", if *msg {"YES"} else {"NO"})],
       
   244             Save(name, location) => msg!["CMD", format!("SAVE {} {}", name, location)],
       
   245             Delete(name) => msg!["CMD", format!("DELETE {}", name)],
       
   246             SaveRoom(name) => msg!["CMD", format!("SAVEROOM {}", name)],
       
   247             LoadRoom(name) => msg!["CMD", format!("LOADROOM {}", name)],
       
   248             Malformed => msg!["A", "QUICK", "BROWN", "HOG", "JUMPS", "OVER", "THE", "LAZY", "DOG"],
       
   249             Empty => msg![""],
       
   250             _ => panic!("Protocol message not yet implemented")
       
   251         }
       
   252     }
       
   253 }
       
   254 
       
   255 fn construct_message(header: &[&str], msg: &[String]) -> String {
       
   256     let mut v: Vec<_> = header.iter().cloned().collect();
       
   257     v.extend(msg.iter().map(|s| &s[..]));
       
   258     v.push("\n");
       
   259     v.join("\n")
       
   260 }
       
   261 
       
   262 impl HWServerMessage {
       
   263     pub fn to_raw_protocol(&self) -> String {
       
   264         use self::HWServerMessage::*;
       
   265         match self {
       
   266             Ping => msg!["PING"],
       
   267             Pong => msg!["PONG"],
       
   268             Connected(protocol_version) => msg![
       
   269                 "CONNECTED",
       
   270                 "Hedgewars server https://www.hedgewars.org/",
       
   271                 protocol_version],
       
   272             Bye(msg) => msg!["BYE", msg],
       
   273             Nick(nick) => msg!["NICK", nick],
       
   274             Proto(proto) => msg!["PROTO", proto],
       
   275             ServerAuth(hash) => msg!["SERVER_AUTH", hash],
       
   276             LobbyLeft(nick, msg) => msg!["LOBBY:LEFT", nick, msg],
       
   277             LobbyJoined(nicks) =>
       
   278                 construct_message(&["LOBBY:JOINED"], &nicks),
       
   279             ClientFlags(flags, nicks) =>
       
   280                 construct_message(&["CLIENT_FLAGS", flags], &nicks),
       
   281             Rooms(info) =>
       
   282                 construct_message(&["ROOMS"], &info),
       
   283             RoomAdd(info) =>
       
   284                 construct_message(&["ROOM", "ADD"], &info),
       
   285             RoomJoined(nicks) =>
       
   286                 construct_message(&["JOINED"], &nicks),
       
   287             RoomLeft(nick, msg) => msg!["LEFT", nick, msg],
       
   288             RoomRemove(name) => msg!["ROOM", "DEL", name],
       
   289             RoomUpdated(name, info) =>
       
   290                 construct_message(&["ROOM", "UPD", name], &info),
       
   291             TeamAdd(info) =>
       
   292                 construct_message(&["ADD_TEAM"], &info),
       
   293             TeamRemove(name) => msg!["REMOVE_TEAM", name],
       
   294             TeamAccepted(name) => msg!["TEAM_ACCEPTED", name],
       
   295             TeamColor(name, color) => msg!["TEAM_COLOR", name, color],
       
   296             HedgehogsNumber(name, number) => msg!["HH_NUM", name, number],
       
   297             ConfigEntry(name, values) =>
       
   298                 construct_message(&["CFG", name], &values),
       
   299             Kicked => msg!["KICKED"],
       
   300             RunGame => msg!["RUN_GAME"],
       
   301             ForwardEngineMessage(em) =>
       
   302                 construct_message(&["EM"], &em),
       
   303             RoundFinished => msg!["ROUND_FINISHED"],
       
   304             ChatMsg {nick, msg} => msg!["CHAT", nick, msg],
       
   305             ServerMessage(msg) => msg!["SERVER_MESSAGE", msg],
       
   306             Notice(msg) => msg!["NOTICE", msg],
       
   307             Warning(msg) => msg!["WARNING", msg],
       
   308             Error(msg) => msg!["ERROR", msg],
       
   309 
       
   310             LegacyReady(is_ready, nicks) =>
       
   311                 construct_message(&[if *is_ready {"READY"} else {"NOT_READY"}], &nicks),
       
   312 
       
   313             _ => msg!["ERROR", "UNIMPLEMENTED"],
       
   314         }
       
   315     }
       
   316 }