From 72681ccfe84e828a65f58324297d8e6f55ad772d Mon Sep 17 00:00:00 2001 From: Martin Indra Date: Wed, 11 Oct 2023 22:40:26 +0200 Subject: [PATCH] Multiplayer: Fix entity de-registering (#765) This fixes: thread 'Compute Task Pool (4)' panicked at 'called `Option::unwrap()` on a `None` value', crates/multiplayer/src/playermsg.rs:270:78 Which was due to receiving a deregister message after the player left the game. This can happen as a race-condition just after game end or if the other player is kicked out due to network issues (but sends a message around the time of the kick). Fixes #757. --- crates/multiplayer/src/playermsg.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/crates/multiplayer/src/playermsg.rs b/crates/multiplayer/src/playermsg.rs index a6827f98..3a839682 100644 --- a/crates/multiplayer/src/playermsg.rs +++ b/crates/multiplayer/src/playermsg.rs @@ -209,7 +209,7 @@ impl<'w> NetEntityCommands<'w> { self.map.register(remote, local) } - fn deregister(&mut self, remote: EntityNet) -> Entity { + fn deregister(&mut self, remote: EntityNet) -> Option { self.map.deregister(remote) } @@ -261,16 +261,18 @@ impl EntityIdMapRes { /// De-registers an existing remote entity. /// + /// Returns None if the player does no longer exist. + /// /// See [`Self::register`]. /// /// # Panics /// /// Panics if the entity is not registered. - fn deregister(&mut self, remote: EntityNet) -> Entity { - let player_entities = self.remote_to_local.get_mut(&remote.player()).unwrap(); + fn deregister(&mut self, remote: EntityNet) -> Option { + let player_entities = self.remote_to_local.get_mut(&remote.player())?; let local = player_entities.remove(remote.index()).unwrap(); self.local_to_remote.remove(&local).unwrap(); - local + Some(local) } /// Translates local entity ID to a remote entity ID in case the entity is @@ -374,8 +376,9 @@ fn recv_messages( )); } ToPlayers::Despawn { entity } => { - let local = net_commands.deregister(*entity); - despawn_events.send(NetRecvDespawnActiveEvent::new(local)); + if let Some(local) = net_commands.deregister(*entity) { + despawn_events.send(NetRecvDespawnActiveEvent::new(local)); + } } ToPlayers::SetPath { entity, waypoints } => { let Some(local) = net_commands.remote_local_id(*entity) else {