Skip to content

Commit

Permalink
Multiplayer: Fix entity de-registering (#765)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Indy2222 authored Oct 11, 2023
1 parent 9eef4fe commit 72681cc
Showing 1 changed file with 9 additions and 6 deletions.
15 changes: 9 additions & 6 deletions crates/multiplayer/src/playermsg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Entity> {
self.map.deregister(remote)
}

Expand Down Expand Up @@ -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<Entity> {
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
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 72681cc

Please sign in to comment.