Server action refactoring part 8 of N
authoralfadur <mail@none>
Tue, 05 Feb 2019 17:46:43 +0300
changeset 14683 932ff7683653
parent 14682 204fb862d0e4
child 14684 bc267f6b29d7
Server action refactoring part 8 of N
rust/hedgewars-server/src/server/actions.rs
rust/hedgewars-server/src/server/handlers/common.rs
rust/hedgewars-server/src/server/handlers/inroom.rs
rust/hedgewars-server/src/server/handlers/loggingin.rs
--- a/rust/hedgewars-server/src/server/actions.rs	Tue Feb 05 04:55:40 2019 +0100
+++ b/rust/hedgewars-server/src/server/actions.rs	Tue Feb 05 17:46:43 2019 +0300
@@ -87,16 +87,6 @@
         }
         self
     }
-
-    pub fn action(self) -> Action {
-        Send(self)
-    }
-}
-
-impl Into<Action> for PendingMessage {
-    fn into(self) -> Action {
-        self.action()
-    }
 }
 
 impl HWServerMessage {
@@ -112,11 +102,6 @@
 }
 
 pub enum Action {
-    Send(PendingMessage),
-    CheckRegistered,
-    JoinLobby,
-    RemoveRoom(RoomId),
-    MoveToRoom(RoomId),
     ChangeMaster(RoomId, Option<ClientId>),
     SendRoomUpdate(Option<String>),
     StartRoomGame(RoomId),
@@ -133,199 +118,12 @@
         is_forced: bool,
     },
     ApplyVoting(VoteType, RoomId),
-    Warn(String),
-    ProtocolError(String),
 }
 
 use self::Action::*;
 
 pub fn run_action(server: &mut HWServer, client_id: usize, action: Action) {
     match action {
-        Send(msg) => server.send(client_id, &msg.destination, msg.message),
-        CheckRegistered => {
-            let client = &server.clients[client_id];
-            if client.protocol_number > 0 && client.nick != "" {
-                let has_nick_clash = server
-                    .clients
-                    .iter()
-                    .any(|(id, c)| id != client_id && c.nick == client.nick);
-
-                let actions = if !client.is_checker() && has_nick_clash {
-                    if client.protocol_number < 38 {
-                        //ByeClient("Nickname is already in use".to_string())
-                        vec![]
-                    } else {
-                        server.clients[client_id].nick.clear();
-                        vec![Notice("NickAlreadyInUse".to_string()).send_self().action()]
-                    }
-                } else {
-                    vec![JoinLobby]
-                };
-                server.react(client_id, actions);
-            }
-        }
-        JoinLobby => {
-            server.clients[client_id].room_id = Some(server.lobby_id);
-
-            let mut lobby_nicks = Vec::new();
-            for (_, c) in server.clients.iter() {
-                if c.room_id.is_some() {
-                    lobby_nicks.push(c.nick.clone());
-                }
-            }
-            let joined_msg = LobbyJoined(lobby_nicks);
-
-            let everyone_msg = LobbyJoined(vec![server.clients[client_id].nick.clone()]);
-            let flags_msg = ClientFlags(
-                "+i".to_string(),
-                server
-                    .clients
-                    .iter()
-                    .filter(|(_, c)| c.room_id.is_some())
-                    .map(|(_, c)| c.nick.clone())
-                    .collect(),
-            );
-            let server_msg = ServerMessage("\u{1f994} is watching".to_string());
-            let rooms_msg = Rooms(
-                server
-                    .rooms
-                    .iter()
-                    .filter(|(id, _)| *id != server.lobby_id)
-                    .flat_map(|(_, r)| r.info(r.master_id.map(|id| &server.clients[id])))
-                    .collect(),
-            );
-            server.react(
-                client_id,
-                vec![
-                    everyone_msg.send_all().but_self().action(),
-                    joined_msg.send_self().action(),
-                    flags_msg.send_self().action(),
-                    server_msg.send_self().action(),
-                    rooms_msg.send_self().action(),
-                ],
-            );
-        }
-        RemoveRoom(room_id) => {
-            let r = &mut server.rooms[room_id];
-            let actions = vec![RoomRemove(r.name.clone())
-                .send_all()
-                .with_protocol(r.protocol_number)
-                .action()];
-            server.rooms.remove(room_id);
-            server.react(client_id, actions);
-        }
-        MoveToRoom(room_id) => {
-            let r = &mut server.rooms[room_id];
-            let c = &mut server.clients[client_id];
-            r.players_number += 1;
-            c.room_id = Some(room_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;
-            }
-
-            let mut v = vec![
-                RoomJoined(vec![c.nick.clone()])
-                    .send_all()
-                    .in_room(room_id)
-                    .action(),
-                ClientFlags("+i".to_string(), vec![c.nick.clone()])
-                    .send_all()
-                    .action(),
-                SendRoomUpdate(None),
-            ];
-
-            if !r.greeting.is_empty() {
-                v.push(
-                    ChatMsg {
-                        nick: "[greeting]".to_string(),
-                        msg: r.greeting.clone(),
-                    }
-                    .send_self()
-                    .action(),
-                );
-            }
-
-            if !c.is_master() {
-                let team_names: Vec<_>;
-                if let Some(ref mut info) = r.game_info {
-                    c.set_is_in_game(true);
-                    c.set_is_joined_mid_game(true);
-
-                    {
-                        let teams = info.client_teams(c.id);
-                        c.teams_in_game = teams.clone().count() as u8;
-                        c.clan = teams.clone().next().map(|t| t.color);
-                        team_names = teams.map(|t| t.name.clone()).collect();
-                    }
-
-                    if !team_names.is_empty() {
-                        info.left_teams.retain(|name| !team_names.contains(&name));
-                        info.teams_in_game += team_names.len() as u8;
-                        r.teams = info
-                            .teams_at_start
-                            .iter()
-                            .filter(|(_, t)| !team_names.contains(&t.name))
-                            .cloned()
-                            .collect();
-                    }
-                } else {
-                    team_names = Vec::new();
-                }
-
-                v.push(SendRoomData {
-                    to: client_id,
-                    teams: true,
-                    config: true,
-                    flags: true,
-                });
-
-                if let Some(ref info) = r.game_info {
-                    v.push(RunGame.send_self().action());
-                    v.push(
-                        ClientFlags("+g".to_string(), vec![c.nick.clone()])
-                            .send_all()
-                            .in_room(r.id)
-                            .action(),
-                    );
-                    v.push(
-                        ForwardEngineMessage(vec![to_engine_msg("e$spectate 1".bytes())])
-                            .send_self()
-                            .action(),
-                    );
-                    v.push(
-                        ForwardEngineMessage(info.msg_log.clone())
-                            .send_self()
-                            .action(),
-                    );
-
-                    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(),
-                        );
-                    }
-                    if info.is_paused {
-                        v.push(
-                            ForwardEngineMessage(vec![to_engine_msg(once(b'I'))])
-                                .send_all()
-                                .in_room(r.id)
-                                .action(),
-                        )
-                    }
-                }
-            }
-            server.react(client_id, v);
-        }
         SendRoomData {
             to,
             teams,
@@ -336,13 +134,14 @@
             let room_id = server.clients[client_id].room_id;
             if let Some(r) = room_id.and_then(|id| server.rooms.get(id)) {
                 if config {
-                    actions.push(
+                    /*                    actions.push(
                         ConfigEntry("FULLMAPCONFIG".to_string(), r.map_config())
                             .send(to)
                             .action(),
-                    );
+                    )*/
+;
                     for cfg in r.game_config() {
-                        actions.push(cfg.to_server_msg().send(to).action());
+                        //actions.push(cfg.to_server_msg().send(to).action());
                     }
                 }
                 if teams {
@@ -351,7 +150,7 @@
                         None => &r.teams,
                     };
                     for (owner_id, team) in current_teams.iter() {
-                        actions.push(
+                        /*actions.push(
                             TeamAdd(HWRoom::team_info(&server.clients[*owner_id], &team))
                                 .send(to)
                                 .action(),
@@ -361,16 +160,18 @@
                             HedgehogsNumber(team.name.clone(), team.hedgehogs_number)
                                 .send(to)
                                 .action(),
-                        );
+                        );*/
                     }
                 }
                 if flags {
                     if let Some(id) = r.master_id {
-                        actions.push(
-                            ClientFlags("+h".to_string(), vec![server.clients[id].nick.clone()])
-                                .send(to)
-                                .action(),
-                        );
+                        /*
+                                                actions.push(
+                                                    ClientFlags("+h".to_string(), vec![server.clients[id].nick.clone()])
+                                                        .send(to)
+                                                        .action(),
+                                                );
+                        */
                     }
                     let nicks: Vec<_> = server
                         .clients
@@ -379,7 +180,8 @@
                         .map(|(_, c)| c.nick.clone())
                         .collect();
                     if !nicks.is_empty() {
-                        actions.push(ClientFlags("+r".to_string(), nicks).send(to).action());
+                        /*actions.push(ClientFlags("+r".to_string(), nicks).send(to).action())*/
+;
                     }
                 }
             }
@@ -391,11 +193,12 @@
                 let mut result = None;
                 if let Some(ref mut voting) = r.voting {
                     if is_forced || voting.votes.iter().all(|(id, _)| client_id != *id) {
-                        actions.push(
+                        /*                        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();
@@ -408,27 +211,29 @@
                             result = Some(false);
                         }
                     } else {
-                        actions.push(
+                        /*                        actions.push(
                             server_chat("You already have voted.".to_string())
                                 .send_self()
                                 .action(),
-                        );
+                        )*/
+;
                     }
                 } else {
-                    actions.push(
+                    /*                    actions.push(
                         server_chat("There's no voting going on.".to_string())
                             .send_self()
                             .action(),
-                    );
+                    )*/
+;
                 }
 
                 if let Some(res) = result {
-                    actions.push(
+                    /*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 {
                         actions.push(ApplyVoting(voting.kind, r.id));
@@ -446,7 +251,7 @@
                     if let Some(c) = server.find_client(&nick) {
                         if c.room_id == Some(room_id) {
                             id = c.id;
-                            actions.push(Kicked.send_self().action());
+                            //actions.push(Kicked.send_self().action());
                             //actions.push(MoveToLobby("kicked".to_string()));
                         }
                     }
@@ -454,12 +259,12 @@
                 VoteType::Map(None) => (),
                 VoteType::Map(Some(name)) => {
                     if let Some(location) = server.rooms[room_id].load_config(&name) {
-                        actions.push(
+                        /*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) {
@@ -476,35 +281,35 @@
                 VoteType::Pause => {
                     if let Some(ref mut info) = server.rooms[room_id].game_info {
                         info.is_paused = !info.is_paused;
-                        actions.push(
+                        /*actions.push(
                             server_chat("Pause toggled.".to_string())
                                 .send_all()
                                 .in_room(room_id)
                                 .action(),
-                        );
-                        actions.push(
+                        );*/
+                        /*actions.push(
                             ForwardEngineMessage(vec![to_engine_msg(once(b'I'))])
                                 .send_all()
                                 .in_room(room_id)
                                 .action(),
-                        );
+                        );*/
                     }
                 }
                 VoteType::NewSeed => {
                     let seed = thread_rng().gen_range(0, 1_000_000_000).to_string();
                     let cfg = GameCfg::Seed(seed);
-                    actions.push(cfg.to_server_msg().send_all().in_room(room_id).action());
+                    /*actions.push(cfg.to_server_msg().send_all().in_room(room_id).action());*/
                     server.rooms[room_id].set_config(cfg);
                 }
                 VoteType::HedgehogsPerTeam(number) => {
                     let r = &mut server.rooms[room_id];
                     let nicks = r.set_hedgehogs_number(number);
-                    actions.extend(nicks.into_iter().map(|n| {
+                    /*actions.extend(nicks.into_iter().map(|n| {
                         HedgehogsNumber(n, number)
                             .send_all()
                             .in_room(room_id)
                             .action()
-                    }));
+                    }));*/
                 }
             }
             server.react(id, actions);
@@ -528,12 +333,12 @@
                     Some(id) if id == c.id => {
                         c.set_is_master(false);
                         r.master_id = None;
-                        actions.push(
+                        /*actions.push(
                             ClientFlags("-h".to_string(), vec![c.nick.clone()])
                                 .send_all()
                                 .in_room(r.id)
                                 .action(),
-                        );
+                        );*/
                     }
                     Some(_) => unreachable!(),
                     None => {}
@@ -548,12 +353,12 @@
                 let is_fixed = r.is_fixed();
                 r.set_unregistered_players_restriction(is_fixed);
                 if let Some(nick) = new_nick {
-                    actions.push(
+                    /*actions.push(
                         ClientFlags("+h".to_string(), vec![nick])
                             .send_all()
                             .in_room(r.id)
                             .action(),
-                    );
+                    );*/
                 }
             }
             if let Some(id) = new_id {
@@ -564,11 +369,11 @@
         SendRoomUpdate(old_name) => {
             if let (c, Some(r)) = server.client_and_room(client_id) {
                 let name = old_name.unwrap_or_else(|| r.name.clone());
-                let actions = vec![RoomUpdated(name, r.info(Some(&c)))
+                /*let actions = vec![RoomUpdated(name, r.info(Some(&c)))
                     .send_all()
                     .with_protocol(r.protocol_number)
                     .action()];
-                server.react(client_id, actions);
+                server.react(client_id, actions);*/
             }
         }
         StartRoomGame(room_id) => {
@@ -581,15 +386,15 @@
                 let room = &mut server.rooms[room_id];
 
                 if !room.has_multiple_clans() {
-                    vec![Warn(
+                    vec![/*Warn(
                         "The game can't be started with less than two clans!".to_string(),
-                    )]
+                    )*/]
                 } else if room.protocol_number <= 43
                     && room.players_number != room.ready_players_number
                 {
-                    vec![Warn("Not all players are ready".to_string())]
+                    vec![/*Warn("Not all players are ready".to_string())*/]
                 } else if room.game_info.is_some() {
-                    vec![Warn("The game is already in progress".to_string())]
+                    vec![/*Warn("The game is already in progress".to_string())*/]
                 } else {
                     room.start_round();
                     for id in room_clients {
@@ -598,12 +403,12 @@
                         c.team_indices = room.client_team_indices(c.id);
                     }
                     vec![
-                        RunGame.send_all().in_room(room.id).action(),
+                        /*RunGame.send_all().in_room(room.id).action(),*/
                         SendRoomUpdate(None),
-                        ClientFlags("+g".to_string(), room_nicks)
-                            .send_all()
-                            .in_room(room.id)
-                            .action(),
+                        /*ClientFlags("+g".to_string(), room_nicks)
+                        .send_all()
+                        .in_room(room.id)
+                        .action(),*/
                     ]
                 }
             };
@@ -614,13 +419,13 @@
             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(
+                    /*actions.push(
                         ForwardEngineMessage(vec![to_engine_msg(msg)])
                             .send_all()
                             .in_room(r.id)
                             .but_self()
                             .action(),
-                    );
+                    );*/
                     info.teams_in_game -= 1;
                     if info.teams_in_game == 0 {
                         actions.push(FinishRoomGame(r.id));
@@ -633,13 +438,13 @@
                         info.sync_msg = None
                     }
                     info.msg_log.push(remove_msg.clone());
-                    actions.push(
+                    /*actions.push(
                         ForwardEngineMessage(vec![remove_msg])
                             .send_all()
                             .in_room(r.id)
                             .but_self()
                             .action(),
-                    );
+                    );*/
                 }
             }
             server.react(client_id, actions);
@@ -650,7 +455,7 @@
             let r = &mut server.rooms[room_id];
             r.ready_players_number = 1;
             actions.push(SendRoomUpdate(None));
-            actions.push(RoundFinished.send_all().in_room(r.id).action());
+            //actions.push(RoundFinished.send_all().in_room(r.id).action());
 
             if let Some(info) = replace(&mut r.game_info, None) {
                 for (_, c) in server.clients.iter() {
@@ -662,7 +467,7 @@
                             flags: false,
                         });
                         for name in &info.left_teams {
-                            actions.push(TeamRemove(name.clone()).send(c.id).action());
+                            //actions.push(TeamRemove(name.clone()).send(c.id).action());
                         }
                     }
                 }
@@ -692,13 +497,9 @@
                 } else {
                     ClientFlags("-r".to_string(), nicks)
                 };
-                actions.push(msg.send_all().in_room(room_id).action());
+                //actions.push(msg.send_all().in_room(room_id).action());
             }
             server.react(client_id, actions);
         }
-        Warn(msg) => {
-            run_action(server, client_id, Warning(msg).send_self().action());
-        }
-        ProtocolError(msg) => run_action(server, client_id, Error(msg).send_self().action()),
     }
 }
--- a/rust/hedgewars-server/src/server/handlers/common.rs	Tue Feb 05 04:55:40 2019 +0100
+++ b/rust/hedgewars-server/src/server/handlers/common.rs	Tue Feb 05 17:46:43 2019 +0300
@@ -1,12 +1,13 @@
 use crate::server::client::HWClient;
+use crate::server::coretypes::ClientId;
 use crate::server::room::HWRoom;
 use crate::utils::to_engine_msg;
 use crate::{
     protocol::messages::{
         HWProtocolMessage::{self, Rnd},
         HWServerMessage::{
-            self, Bye, ChatMsg, ClientFlags, ForwardEngineMessage, LobbyLeft, RoomLeft, RoomRemove,
-            RoomUpdated, TeamRemove,
+            self, Bye, ChatMsg, ClientFlags, ForwardEngineMessage, LobbyJoined, LobbyLeft, Notice,
+            RoomLeft, RoomRemove, RoomUpdated, Rooms, ServerMessage, TeamRemove,
         },
     },
     server::{actions::Action, core::HWServer},
@@ -28,6 +29,63 @@
     }
 }
 
+pub fn process_login(server: &mut HWServer, response: &mut super::Response) {
+    let client_id = response.client_id();
+    let nick = server.clients[client_id].nick.clone();
+
+    let has_nick_clash = server
+        .clients
+        .iter()
+        .any(|(id, c)| id != client_id && c.nick == nick);
+
+    let client = &mut server.clients[client_id];
+
+    if !client.is_checker() && has_nick_clash {
+        if client.protocol_number < 38 {
+            remove_client(server, response, "Nickname is already in use".to_string());
+        } else {
+            client.nick.clear();
+            response.add(Notice("NickAlreadyInUse".to_string()).send_self());
+        }
+    } else {
+        server.clients[client_id].room_id = Some(server.lobby_id);
+
+        let lobby_nicks: Vec<_> = server
+            .clients
+            .iter()
+            .filter_map(|(_, c)| c.room_id.and(Some(c.nick.clone())))
+            .collect();
+        let joined_msg = LobbyJoined(lobby_nicks);
+
+        let everyone_msg = LobbyJoined(vec![server.clients[client_id].nick.clone()]);
+        let flags_msg = ClientFlags(
+            "+i".to_string(),
+            server
+                .clients
+                .iter()
+                .filter(|(_, c)| c.room_id.is_some())
+                .map(|(_, c)| c.nick.clone())
+                .collect(),
+        );
+        let server_msg = ServerMessage("\u{1f994} is watching".to_string());
+
+        let rooms_msg = Rooms(
+            server
+                .rooms
+                .iter()
+                .filter(|(id, _)| *id != server.lobby_id)
+                .flat_map(|(_, r)| r.info(r.master_id.map(|id| &server.clients[id])))
+                .collect(),
+        );
+
+        response.add(everyone_msg.send_all().but_self());
+        response.add(joined_msg.send_self());
+        response.add(flags_msg.send_self());
+        response.add(server_msg.send_self());
+        response.add(rooms_msg.send_self());
+    }
+}
+
 pub fn remove_teams(
     room: &mut HWRoom,
     team_names: Vec<String>,
@@ -132,10 +190,7 @@
 mod tests {
     use super::*;
     use crate::protocol::messages::HWServerMessage::ChatMsg;
-    use crate::server::actions::{
-        Action::{self, Send},
-        PendingMessage,
-    };
+    use crate::server::actions::PendingMessage;
 
     fn reply2string(r: HWServerMessage) -> String {
         match r {
--- a/rust/hedgewars-server/src/server/handlers/inroom.rs	Tue Feb 05 04:55:40 2019 +0100
+++ b/rust/hedgewars-server/src/server/handlers/inroom.rs	Tue Feb 05 17:46:43 2019 +0300
@@ -113,24 +113,35 @@
             if let (client, Some(room)) = server.client_and_room(client_id) {
                 let msg = match msg {
                     Some(s) => format!("part: {}", s),
-                    None => "part".to_string()
+                    None => "part".to_string(),
                 };
                 super::common::exit_room(client, room, response, &msg);
                 client.room_id = Some(lobby_id);
             }
-        },
+        }
         Chat(msg) => {
             let client = &mut server.clients[client_id];
-            response.add(ChatMsg {nick: client.nick.clone(), msg}.send_all().in_room(room_id));
-        },
+            response.add(
+                ChatMsg {
+                    nick: client.nick.clone(),
+                    msg,
+                }
+                .send_all()
+                .in_room(room_id),
+            );
+        }
         Fix => {
             if let (client, Some(room)) = server.client_and_room(client_id) {
-                if client.is_admin() { room.set_is_fixed(true) }
+                if client.is_admin() {
+                    room.set_is_fixed(true)
+                }
             }
         }
         Unfix => {
             if let (client, Some(room)) = server.client_and_room(client_id) {
-                if client.is_admin() { room.set_is_fixed(false) }
+                if client.is_admin() {
+                    room.set_is_fixed(false)
+                }
             }
         }
         Greeting(text) => {
@@ -146,7 +157,9 @@
             } else if server.rooms[room_id].is_fixed() {
                 response.add(Warning("Access denied.".to_string()).send_self());
             } else if server.has_room(&new_name) {
-                response.add(Warning("A room with the same name already exists.".to_string()).send_self());
+                response.add(
+                    Warning("A room with the same name already exists.".to_string()).send_self(),
+                );
             } else {
                 let mut old_name = new_name.clone();
                 let client = &server.clients[client_id];
@@ -155,7 +168,7 @@
                 let update_msg = RoomUpdated(old_name, room.info(Some(client)));
                 response.add(update_msg.send_all().with_protocol(room.protocol_number));
             };
-        },
+        }
         ToggleReady => {
             if let (client, Some(room)) = server.client_and_room(client_id) {
                 let flags = if client.is_ready() {
@@ -186,63 +199,97 @@
                 } else if room.addable_hedgehogs() == 0 {
                     response.add(Warning("Too many hedgehogs!".to_string()).send_self());
                 } else if room.find_team(|t| t.name == info.name) != None {
-                    response.add(Warning("There's already a team with same name in the list.".to_string()).send_self());
+                    response.add(
+                        Warning("There's already a team with same name in the list.".to_string())
+                            .send_self(),
+                    );
                 } else if room.game_info.is_some() {
-                    response.add(Warning("Joining not possible: Round is in progress.".to_string()).send_self());
+                    response.add(
+                        Warning("Joining not possible: Round is in progress.".to_string())
+                            .send_self(),
+                    );
                 } else if room.is_team_add_restricted() {
-                    response.add(Warning("This room currently does not allow adding new teams.".to_string()).send_self());
+                    response.add(
+                        Warning("This room currently does not allow adding new teams.".to_string())
+                            .send_self(),
+                    );
                 } else {
                     let team = room.add_team(client.id, *info, client.protocol_number < 42);
                     client.teams_in_game += 1;
                     client.clan = Some(team.color);
-                    response.add(TeamAccepted(team.name.clone())
-                        .send_self());
-                    response.add(TeamAdd(HWRoom::team_info(&client, team))
-                        .send_all().in_room(room_id).but_self());
-                    response.add(TeamColor(team.name.clone(), team.color)
-                        .send_all().in_room(room_id));
-                    response.add(HedgehogsNumber(team.name.clone(), team.hedgehogs_number)
-                        .send_all().in_room(room_id));
+                    response.add(TeamAccepted(team.name.clone()).send_self());
+                    response.add(
+                        TeamAdd(HWRoom::team_info(&client, team))
+                            .send_all()
+                            .in_room(room_id)
+                            .but_self(),
+                    );
+                    response.add(
+                        TeamColor(team.name.clone(), team.color)
+                            .send_all()
+                            .in_room(room_id),
+                    );
+                    response.add(
+                        HedgehogsNumber(team.name.clone(), team.hedgehogs_number)
+                            .send_all()
+                            .in_room(room_id),
+                    );
 
                     let update_msg = RoomUpdated(room.name.clone(), room.info(Some(client)));
                     response.add(update_msg.send_all().with_protocol(room.protocol_number));
                 }
             }
-        },
+        }
         RemoveTeam(name) => {
             if let (client, Some(room)) = server.client_and_room(client_id) {
                 match room.find_team_owner(&name) {
-                    None =>
-                        response.add(Warning("Error: The team you tried to remove does not exist.".to_string()).send_self()),
-                    Some((id, _)) if id != client_id =>
-                        response.add(Warning("You can't remove a team you don't own.".to_string()).send_self()),
+                    None => response.add(
+                        Warning("Error: The team you tried to remove does not exist.".to_string())
+                            .send_self(),
+                    ),
+                    Some((id, _)) if id != client_id => response.add(
+                        Warning("You can't remove a team you don't own.".to_string()).send_self(),
+                    ),
                     Some((_, name)) => {
                         client.teams_in_game -= 1;
                         client.clan = room.find_team_color(client.id);
-                        super::common::remove_teams(room, vec![name.to_string()], client.is_in_game(), response);
+                        super::common::remove_teams(
+                            room,
+                            vec![name.to_string()],
+                            client.is_in_game(),
+                            response,
+                        );
                     }
                 }
             }
-        },
+        }
         SetHedgehogsNumber(team_name, number) => {
             if let (client, Some(room)) = server.client_and_room(client_id) {
                 let addable_hedgehogs = room.addable_hedgehogs();
                 if let Some((_, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) {
                     if !client.is_master() {
                         response.add(Error("You're not the room master!".to_string()).send_self());
-                    } else if number < 1 || number > MAX_HEDGEHOGS_PER_TEAM
-                           || number > addable_hedgehogs + team.hedgehogs_number {
-                        response.add(HedgehogsNumber(team.name.clone(), team.hedgehogs_number).send_self());
+                    } else if number < 1
+                        || number > MAX_HEDGEHOGS_PER_TEAM
+                        || number > addable_hedgehogs + team.hedgehogs_number
+                    {
+                        response.add(
+                            HedgehogsNumber(team.name.clone(), team.hedgehogs_number).send_self(),
+                        );
                     } else {
                         team.hedgehogs_number = number;
-                        response.add(HedgehogsNumber(team.name.clone(), number)
-                            .send_all().in_room(room_id).but_self());
+                        response.add(
+                            HedgehogsNumber(team.name.clone(), number)
+                                .send_all()
+                                .in_room(room_id)
+                                .but_self(),
+                        );
                     }
                 } else {
                     response.add(Warning("No such team.".to_string()).send_self());
                 }
             }
-        },
+        }
         SetTeamColor(team_name, color) => {
             if let (client, Some(room)) = server.client_and_room(client_id) {
                 if let Some((owner, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) {
@@ -250,15 +297,19 @@
                         response.add(Error("You're not the room master!".to_string()).send_self());
                     } else {
                         team.color = color;
-                        response.add(TeamColor(team.name.clone(), color)
-                            .send_all().in_room(room_id).but_self());
+                        response.add(
+                            TeamColor(team.name.clone(), color)
+                                .send_all()
+                                .in_room(room_id)
+                                .but_self(),
+                        );
                         server.clients[owner].clan = Some(color);
                     }
                 } else {
                     response.add(Warning("No such team.".to_string()).send_self());
                 }
             }
-        },
+        }
         Cfg(cfg) => {
             if let (client, Some(room)) = server.client_and_room(client_id) {
                 if room.is_fixed() {
@@ -275,34 +326,45 @@
                             }
                             GameCfg::Scheme(name, values)
                         }
-                        cfg => cfg
+                        cfg => cfg,
                     };
 
-                    response.add(cfg.to_server_msg()
-                        .send_all().in_room(room.id).but_self());
+                    response.add(cfg.to_server_msg().send_all().in_room(room.id).but_self());
                     room.set_config(cfg);
                 }
             }
         }
         Save(name, location) => {
-            response.add(server_chat(format!("Room config saved as {}", name))
-                .send_all().in_room(room_id));
+            response.add(
+                server_chat(format!("Room config saved as {}", name))
+                    .send_all()
+                    .in_room(room_id),
+            );
             server.rooms[room_id].save_config(name, location);
         }
         SaveRoom(filename) => {
             if server.clients[client_id].is_admin() {
                 match server.rooms[room_id].get_saves() {
                     Ok(text) => match server.io.write_file(&filename, &text) {
-                        Ok(_) => response.add(server_chat("Room configs saved successfully.".to_string())
-                            .send_self()),
+                        Ok(_) => response.add(
+                            server_chat("Room configs saved successfully.".to_string()).send_self(),
+                        ),
                         Err(e) => {
-                            warn!("Error while writing the config file \"{}\": {}", filename, e);
-                            response.add(Warning("Unable to save the room configs.".to_string()).send_self());
+                            warn!(
+                                "Error while writing the config file \"{}\": {}",
+                                filename, e
+                            );
+                            response.add(
+                                Warning("Unable to save the room configs.".to_string()).send_self(),
+                            );
                         }
-                    }
+                    },
                     Err(e) => {
                         warn!("Error while serializing the room configs: {}", e);
-                        response.add(Warning("Unable to serialize the room configs.".to_string()).send_self())
+                        response.add(
+                            Warning("Unable to serialize the room configs.".to_string())
+                                .send_self(),
+                        )
                     }
                 }
             }
@@ -311,16 +373,26 @@
             if server.clients[client_id].is_admin() {
                 match server.io.read_file(&filename) {
                     Ok(text) => match server.rooms[room_id].set_saves(&text) {
-                        Ok(_) => response.add(server_chat("Room configs loaded successfully.".to_string())
-                            .send_self()),
+                        Ok(_) => response.add(
+                            server_chat("Room configs loaded successfully.".to_string())
+                                .send_self(),
+                        ),
                         Err(e) => {
                             warn!("Error while deserializing the room configs: {}", e);
-                            response.add(Warning("Unable to deserialize the room configs.".to_string()).send_self());
+                            response.add(
+                                Warning("Unable to deserialize the room configs.".to_string())
+                                    .send_self(),
+                            );
                         }
-                    }
+                    },
                     Err(e) => {
-                        warn!("Error while reading the config file \"{}\": {}", filename, e);
-                        response.add(Warning("Unable to load the room configs.".to_string()).send_self());
+                        warn!(
+                            "Error while reading the config file \"{}\": {}",
+                            filename, e
+                        );
+                        response.add(
+                            Warning("Unable to load the room configs.".to_string()).send_self(),
+                        );
                     }
                 }
             }
@@ -329,8 +401,11 @@
             if !server.rooms[room_id].delete_config(&name) {
                 response.add(Warning(format!("Save doesn't exist: {}", name)).send_self());
             } else {
-                response.add(server_chat(format!("Room config {} has been deleted", name))
-                    .send_all().in_room(room_id));
+                response.add(
+                    server_chat(format!("Room config {} has been deleted", name))
+                        .send_all()
+                        .in_room(room_id),
+                );
             }
         }
         CallVote(None) => {
@@ -341,12 +416,16 @@
             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() {
+                    if server
+                        .find_client(&nick)
+                        .filter(|c| c.room_id == Some(room_id))
+                        .is_some()
+                    {
                         None
                     } else {
                         Some("/callvote kick: No such user!".to_string())
                     }
-                },
+                }
                 VoteType::Map(None) => {
                     let names: Vec<_> = server.rooms[room_id].saves.keys().cloned().collect();
                     if names.is_empty() {
@@ -354,29 +433,25 @@
                     } else {
                         Some(format!("Available maps: {}", names.join(", ")))
                     }
-                },
+                }
                 VoteType::Map(Some(name)) => {
                     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!".to_string())
                     }
-                },
-                VoteType::NewSeed => {
-                    None
-                },
-                VoteType::HedgehogsPerTeam(number) => {
-                    match number {
-                        1...MAX_HEDGEHOGS_PER_TEAM => None,
-                        _ => Some("/callvote hedgehogs: Specify number from 1 to 8.".to_string())
-                    }
+                }
+                VoteType::NewSeed => None,
+                VoteType::HedgehogsPerTeam(number) => match number {
+                    1...MAX_HEDGEHOGS_PER_TEAM => None,
+                    _ => Some("/callvote hedgehogs: Specify number from 1 to 8.".to_string()),
                 },
             };
             match error {
@@ -393,15 +468,23 @@
             }
         }
         Vote(vote) => {
-            server.react(client_id, vec![AddVote{ vote, is_forced: false }]);
+            server.react(
+                client_id,
+                vec![AddVote {
+                    vote,
+                    is_forced: false,
+                }],
+            );
         }
         ForceVote(vote) => {
             let is_forced = server.clients[client_id].is_admin();
-            server.react(client_id, vec![AddVote{ vote, is_forced }]);
+            server.react(client_id, vec![AddVote { vote, is_forced }]);
         }
-        ToggleRestrictJoin | ToggleRestrictTeams | ToggleRegisteredOnly  => {
+        ToggleRestrictJoin | ToggleRestrictTeams | ToggleRegisteredOnly => {
             if server.clients[client_id].is_master() {
-                server.rooms[room_id].flags.toggle(room_message_flag(&message));
+                server.rooms[room_id]
+                    .flags
+                    .toggle(room_message_flag(&message));
             }
             server.react(client_id, vec![SendRoomUpdate(None)]);
         }
@@ -416,15 +499,26 @@
                     let messages = by_msg(&decoding);
                     let valid = messages.filter(|m| is_msg_valid(m, &c.team_indices));
                     let non_empty = valid.clone().filter(|m| !is_msg_empty(m));
-                    let sync_msg = valid.clone().filter(|m| is_msg_timed(m))
-                        .last().map(|m| if is_msg_empty(m) {Some(encode(m))} else {None});
+                    let sync_msg = valid.clone().filter(|m| is_msg_timed(m)).last().map(|m| {
+                        if is_msg_empty(m) {
+                            Some(encode(m))
+                        } else {
+                            None
+                        }
+                    });
 
-                    let em_response = encode(&valid.flat_map(|msg| msg).cloned().collect::<Vec<_>>());
+                    let em_response =
+                        encode(&valid.flat_map(|msg| msg).cloned().collect::<Vec<_>>());
                     if !em_response.is_empty() {
-                        actions.push(ForwardEngineMessage(vec![em_response])
-                            .send_all().in_room(r.id).but_self().action());
+                        response.add(
+                            ForwardEngineMessage(vec![em_response])
+                                .send_all()
+                                .in_room(r.id)
+                                .but_self(),
+                        );
                     }
-                    let em_log = encode(&non_empty.flat_map(|msg| msg).cloned().collect::<Vec<_>>());
+                    let em_log =
+                        encode(&non_empty.flat_map(|msg| msg).cloned().collect::<Vec<_>>());
                     if let Some(ref mut info) = r.game_info {
                         if !em_log.is_empty() {
                             info.msg_log.push(em_log);
@@ -442,8 +536,11 @@
             if let (c, Some(r)) = server.client_and_room(client_id) {
                 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());
+                    response.add(
+                        ClientFlags("-g".to_string(), vec![c.nick.clone()])
+                            .send_all()
+                            .in_room(r.id),
+                    );
                     if r.game_info.is_some() {
                         for team in r.client_teams(c.id) {
                             actions.push(SendTeamRemovalMessage(team.name.clone()));
@@ -452,18 +549,18 @@
                 }
             }
             server.react(client_id, actions)
-        },
+        }
         Rnd(v) => {
             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(" ")
+                msg: echo.join(" "),
             };
             response.add(chat_msg.send_all().in_room(room_id));
             response.add(result.send_all().in_room(room_id));
-        },
-        _ => warn!("Unimplemented!")
+        }
+        _ => warn!("Unimplemented!"),
     }
 }
--- a/rust/hedgewars-server/src/server/handlers/loggingin.rs	Tue Feb 05 04:55:40 2019 +0100
+++ b/rust/hedgewars-server/src/server/handlers/loggingin.rs	Tue Feb 05 17:46:43 2019 +0300
@@ -57,7 +57,7 @@
                 response.add(Nick(nick).send_self());
 
                 if client.protocol_number > 0 {
-                    //CheckRegistered
+                    super::common::process_login(server, response);
                 }
             }
         }
@@ -72,7 +72,7 @@
                 response.add(Proto(proto).send_self());
 
                 if client.nick != "" {
-                    // CheckRegistered
+                    super::common::process_login(server, response);
                 }
             }
         }
@@ -84,7 +84,7 @@
             let server_hash = get_hash(c, &c.server_salt, &salt);
             if client_hash == server_hash {
                 response.add(ServerAuth(format!("{:x}", server_hash)).send_self());
-            //JoinLobby
+            //TODO enter lobby
             } else {
                 super::common::remove_client(server, response, "Authentication failed".to_string())
             };