fix rejoining
authoralfadur
Mon, 25 Mar 2024 16:05:11 +0300
changeset 16000 d9f1b239b6d7
parent 15999 d73e6cb37f83
child 16001 8ba2b5007c29
fix rejoining
rust/hedgewars-server/src/core/room.rs
rust/hedgewars-server/src/core/server.rs
rust/hedgewars-server/src/handlers/common.rs
rust/hedgewars-server/src/handlers/inroom.rs
rust/hedgewars-server/src/protocol.rs
rust/hedgewars-server/src/server/network.rs
--- a/rust/hedgewars-server/src/core/room.rs	Mon Mar 25 15:59:14 2024 +0300
+++ b/rust/hedgewars-server/src/core/room.rs	Mon Mar 25 16:05:11 2024 +0300
@@ -14,18 +14,25 @@
 pub const MAX_TEAMS_IN_ROOM: u8 = 8;
 pub const MAX_HEDGEHOGS_IN_ROOM: u8 = MAX_TEAMS_IN_ROOM * MAX_HEDGEHOGS_PER_TEAM;
 
+#[derive(Clone, Debug)]
+pub struct OwnedTeam {
+    pub owner_id: ClientId,
+    pub owner_nick: String,
+    pub info: TeamInfo,
+}
+
 fn client_teams_impl(
-    teams: &[(ClientId, TeamInfo)],
-    client_id: ClientId,
+    teams: &[OwnedTeam],
+    owner_id: ClientId,
 ) -> impl Iterator<Item = &TeamInfo> + Clone {
     teams
         .iter()
-        .filter(move |(id, _)| *id == client_id)
-        .map(|(_, t)| t)
+        .filter(move |team| team.owner_id == owner_id)
+        .map(|team| &team.info)
 }
 
 pub struct GameInfo {
-    pub original_teams: Vec<(ClientId, TeamInfo)>,
+    pub original_teams: Vec<OwnedTeam>,
     pub left_teams: Vec<String>,
     pub msg_log: Vec<String>,
     pub sync_msg: Option<String>,
@@ -34,7 +41,7 @@
 }
 
 impl GameInfo {
-    fn new(teams: Vec<(ClientId, TeamInfo)>, config: RoomConfig) -> GameInfo {
+    fn new(teams: Vec<OwnedTeam>, config: RoomConfig) -> GameInfo {
         GameInfo {
             left_teams: Vec::new(),
             msg_log: Vec::new(),
@@ -45,8 +52,18 @@
         }
     }
 
-    pub fn client_teams(&self, client_id: ClientId) -> impl Iterator<Item = &TeamInfo> + Clone {
-        client_teams_impl(&self.original_teams, client_id)
+    pub fn client_teams(&self, owner_id: ClientId) -> impl Iterator<Item = &TeamInfo> + Clone {
+        client_teams_impl(&self.original_teams, owner_id)
+    }
+
+    pub fn client_teams_by_nick<'a>(
+        &'a self,
+        owner_nick: &'a str,
+    ) -> impl Iterator<Item = &TeamInfo> + Clone + 'a {
+        self.original_teams
+            .iter()
+            .filter(move |team| team.owner_nick == owner_nick)
+            .map(|team| &team.info)
     }
 
     pub fn mark_left_teams<'a, I>(&mut self, team_names: I)
@@ -95,7 +112,7 @@
     pub default_hedgehog_number: u8,
     pub max_teams: u8,
     pub ready_players_number: u8,
-    pub teams: Vec<(ClientId, TeamInfo)>,
+    pub teams: Vec<OwnedTeam>,
     config: RoomConfig,
     pub voting: Option<Voting>,
     pub saves: HashMap<String, RoomSave>,
@@ -125,7 +142,10 @@
     }
 
     pub fn hedgehogs_number(&self) -> u8 {
-        self.teams.iter().map(|(_, t)| t.hedgehogs_number).sum()
+        self.teams
+            .iter()
+            .map(|team| team.info.hedgehogs_number)
+            .sum()
     }
 
     pub fn addable_hedgehogs(&self) -> u8 {
@@ -134,7 +154,7 @@
 
     pub fn add_team(
         &mut self,
-        owner_id: ClientId,
+        owner: &HwClient,
         mut team: TeamInfo,
         preserve_color: bool,
     ) -> &TeamInfo {
@@ -142,24 +162,32 @@
             team.color = iter::repeat(())
                 .enumerate()
                 .map(|(i, _)| i as u8)
-                .take(u8::max_value() as usize + 1)
-                .find(|i| self.teams.iter().all(|(_, t)| t.color != *i))
+                .take(u8::MAX as usize + 1)
+                .find(|i| self.teams.iter().all(|team| team.info.color != *i))
                 .unwrap_or(0u8)
         };
         team.hedgehogs_number = if self.teams.is_empty() {
             self.default_hedgehog_number
         } else {
             self.teams[0]
-                .1
+                .info
                 .hedgehogs_number
                 .min(self.addable_hedgehogs())
         };
-        self.teams.push((owner_id, team));
-        &self.teams.last().unwrap().1
+        self.teams.push(OwnedTeam {
+            owner_id: owner.id,
+            owner_nick: owner.nick.clone(),
+            info: team,
+        });
+        &self.teams.last().unwrap().info
     }
 
     pub fn remove_team(&mut self, team_name: &str) {
-        if let Some(index) = self.teams.iter().position(|(_, t)| t.name == team_name) {
+        if let Some(index) = self
+            .teams
+            .iter()
+            .position(|team| team.info.name == team_name)
+        {
             self.teams.remove(index);
         }
     }
@@ -169,9 +197,9 @@
         let teams = &mut self.teams;
 
         if teams.len() as u8 * n <= MAX_HEDGEHOGS_IN_ROOM {
-            for (_, team) in teams.iter_mut() {
-                team.hedgehogs_number = n;
-                names.push(team.name.clone())
+            for team in teams.iter_mut() {
+                team.info.hedgehogs_number = n;
+                names.push(team.info.name.clone())
             }
             self.default_hedgehog_number = n;
         }
@@ -190,8 +218,8 @@
     {
         self.teams
             .iter_mut()
-            .find(|(_, t)| f(t))
-            .map(|(id, t)| (*id, t))
+            .find(|team| f(&team.info))
+            .map(|team| (team.owner_id, &mut team.info))
     }
 
     pub fn find_team<F>(&self, f: F) -> Option<&TeamInfo>
@@ -200,18 +228,18 @@
     {
         self.teams
             .iter()
-            .find_map(|(_, t)| Some(t).filter(|t| f(&t)))
+            .find_map(|team| Some(&team.info).filter(|t| f(&t)))
     }
 
-    pub fn client_teams(&self, client_id: ClientId) -> impl Iterator<Item = &TeamInfo> {
-        client_teams_impl(&self.teams, client_id)
+    pub fn client_teams(&self, owner_id: ClientId) -> impl Iterator<Item = &TeamInfo> {
+        client_teams_impl(&self.teams, owner_id)
     }
 
     pub fn client_team_indices(&self, client_id: ClientId) -> Vec<u8> {
         self.teams
             .iter()
             .enumerate()
-            .filter(move |(_, (id, _))| *id == client_id)
+            .filter(move |(_, team)| team.owner_id == client_id)
             .map(|(i, _)| i as u8)
             .collect()
     }
@@ -219,15 +247,15 @@
     pub fn clan_team_owners(&self, color: u8) -> impl Iterator<Item = ClientId> + '_ {
         self.teams
             .iter()
-            .filter(move |(_, t)| t.color == color)
-            .map(|(id, _)| *id)
+            .filter(move |team| team.info.color == color)
+            .map(|team| team.owner_id)
     }
 
     pub fn find_team_owner(&self, team_name: &str) -> Option<(ClientId, &str)> {
         self.teams
             .iter()
-            .find(|(_, t)| t.name == team_name)
-            .map(|(id, t)| (*id, &t.name[..]))
+            .find(|team| team.info.name == team_name)
+            .map(|team| (team.owner_id, &team.info.name[..]))
     }
 
     pub fn find_team_color(&self, owner_id: ClientId) -> Option<u8> {
@@ -235,8 +263,8 @@
     }
 
     pub fn has_multiple_clans(&self) -> bool {
-        self.teams.iter().min_by_key(|(_, t)| t.color)
-            != self.teams.iter().max_by_key(|(_, t)| t.color)
+        let colors = self.teams.iter().map(|team| team.info.color);
+        colors.clone().min() != colors.max()
     }
 
     pub fn set_config(&mut self, cfg: GameCfg) {
--- a/rust/hedgewars-server/src/core/server.rs	Mon Mar 25 15:59:14 2024 +0300
+++ b/rust/hedgewars-server/src/core/server.rs	Mon Mar 25 16:05:11 2024 +0300
@@ -361,7 +361,7 @@
             Err(Restricted)
         } else if room.is_registration_required() {
             Err(RegistrationRequired)
-        } else if room.players_number == u8::max_value() {
+        } else if room.players_number == u8::MAX {
             Err(Full)
         } else {
             move_to_room(client, room);
@@ -620,7 +620,10 @@
     }
 
     fn remove_from_room(&mut self, client_id: ClientId) -> LeaveRoomResult {
-        let (client, room) = self.server.client_and_room_mut(client_id).expect("Caller should have ensured the client is in this room");
+        let (client, room) = self
+            .server
+            .client_and_room_mut(client_id)
+            .expect("Caller should have ensured the client is in this room");
         room.players_number -= 1;
         client.room_id = None;
 
@@ -937,7 +940,7 @@
             Err(Restricted)
         } else {
             info.owner = client.nick.clone();
-            let team = room.add_team(client.id, *info, client.protocol_number < 42);
+            let team = room.add_team(&client, *info, client.protocol_number < 42);
             client.teams_in_game += 1;
             client.clan = Some(team.color);
             Ok(team)
@@ -949,7 +952,7 @@
         let (client, room) = self.get_mut();
         match room.find_team_owner(team_name) {
             None => Err(NoTeam),
-            Some((id, _)) if id != client.id => Err(RemoveTeamError::TeamNotOwned),
+            Some((id, _)) if id != client.id => Err(TeamNotOwned),
             Some(_) => {
                 client.teams_in_game -= 1;
                 client.clan = room.find_team_color(client.id);
@@ -1171,14 +1174,22 @@
     client.room_id = Some(room.id);
     client.set_is_in_game(room.game_info.is_some());
 
-    if let Some(ref mut info) = room.game_info {
-        let teams = info.client_teams(client.id);
-        client.teams_in_game = teams.clone().count() as u8;
-        client.clan = teams.clone().next().map(|t| t.color);
-        let team_names: Vec<_> = teams.map(|t| t.name.clone()).collect();
+    #[cfg(feature = "official-server")]
+    let can_rejoin = client.is_registered();
+
+    #[cfg(not(feature = "official-server"))]
+    let can_rejoin = true;
 
-        if !team_names.is_empty() {
-            info.left_teams.retain(|name| !team_names.contains(&name));
+    if can_rejoin {
+        if let Some(ref mut info) = room.game_info {
+            let teams = info.client_teams_by_nick(&client.nick);
+            client.teams_in_game = teams.clone().count() as u8;
+            client.clan = teams.clone().next().map(|t| t.color);
+            let team_names: Vec<_> = teams.map(|t| t.name.clone()).collect();
+
+            if !team_names.is_empty() {
+                info.left_teams.retain(|name| !team_names.contains(&name));
+            }
         }
     }
 }
--- a/rust/hedgewars-server/src/handlers/common.rs	Mon Mar 25 15:59:14 2024 +0300
+++ b/rust/hedgewars-server/src/handlers/common.rs	Mon Mar 25 16:05:11 2024 +0300
@@ -211,20 +211,24 @@
             response.add(ForwardEngineMessage(vec![to_engine_msg(once(b'I'))]).send_self());
         }
 
-        for (_, original_team) in &info.original_teams {
-            if let Some(team) = room.find_team(|team| team.name == original_team.name) {
-                if team != original_team {
-                    response.add(TeamRemove(original_team.name.clone()).send_self());
+        for original_team in &info.original_teams {
+            if let Some(team) = room.find_team(|team| team.name == original_team.info.name) {
+                if *team != original_team.info {
+                    response.add(TeamRemove(original_team.info.name.clone()).send_self());
                     response.add(TeamAdd(team.to_protocol()).send_self());
                 }
             } else {
-                response.add(TeamRemove(original_team.name.clone()).send_self());
+                response.add(TeamRemove(original_team.info.name.clone()).send_self());
             }
         }
 
-        for (_, team) in &room.teams {
-            if !info.original_teams.iter().any(|(_, t)| t.name == team.name) {
-                response.add(TeamAdd(team.to_protocol()).send_self());
+        for team in &room.teams {
+            if !info
+                .original_teams
+                .iter()
+                .any(|original_team| original_team.info.name == team.info.name)
+            {
+                response.add(TeamAdd(team.info.to_protocol()).send_self());
             }
         }
 
@@ -403,7 +407,11 @@
         None => &room.teams,
     };
 
-    get_teams(current_teams.iter().map(|(_, t)| t), destination, response);
+    get_teams(
+        current_teams.iter().map(|team| &team.info),
+        destination,
+        response,
+    );
 }
 
 pub fn get_room_flags(
--- a/rust/hedgewars-server/src/handlers/inroom.rs	Mon Mar 25 15:59:14 2024 +0300
+++ b/rust/hedgewars-server/src/handlers/inroom.rs	Mon Mar 25 16:05:11 2024 +0300
@@ -496,6 +496,6 @@
                 response.warn("The player is not in your room.")
             }
         },
-        _ => warn!("Unimplemented!"),
+        message => warn!("Unimplemented: {:?}", message),
     }
 }
--- a/rust/hedgewars-server/src/protocol.rs	Mon Mar 25 15:59:14 2024 +0300
+++ b/rust/hedgewars-server/src/protocol.rs	Mon Mar 25 16:05:11 2024 +0300
@@ -87,7 +87,10 @@
                 Err(nom::Err::Incomplete(_)) => {}
                 Err(nom::Err::Failure(e) | nom::Err::Error(e)) => {
                     debug!("Invalid message: {:?}", e);
-                    trace!("Buffer content: {:?}", String::from_utf8_lossy(&self.buffer[..]));
+                    trace!(
+                        "Buffer content: {:?}",
+                        String::from_utf8_lossy(&self.buffer[..])
+                    );
                     self.recover();
                 }
             }
--- a/rust/hedgewars-server/src/server/network.rs	Mon Mar 25 15:59:14 2024 +0300
+++ b/rust/hedgewars-server/src/server/network.rs	Mon Mar 25 16:05:11 2024 +0300
@@ -216,7 +216,7 @@
     server_state: ServerState,
     clients: Slab<Sender<Bytes>>,
     update_tx: Sender<ClientUpdate>,
-    update_rx: Receiver<ClientUpdate>
+    update_rx: Receiver<ClientUpdate>,
 }
 
 impl NetworkLayer {
@@ -448,7 +448,7 @@
             server_state,
             clients,
             update_tx,
-            update_rx
+            update_rx,
         }
     }
 }