Skip to content

Commit

Permalink
Merge #482
Browse files Browse the repository at this point in the history
482: Attempt to Fix Multiplayer Desync r=zicklag a=zicklag

This is based on the guess that the desync came from the lack of determinism in the scenario when you grab an item while touching multiple items, and it isn't necessarily specified which one you pick up.

Co-authored-by: Zicklag <[email protected]>
  • Loading branch information
bors[bot] and zicklag authored Nov 23, 2022
2 parents fb8c96a + 55a1a68 commit 091da95
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 34 deletions.
28 changes: 17 additions & 11 deletions src/player/state/states/idle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn player_state_transition(
pub fn handle_player_state(
mut commands: Commands,
player_inputs: Res<PlayerInputs>,
items: Query<(Option<&Parent>, &KinematicBody), (With<Item>, Without<PlayerIdx>)>,
items: Query<(Option<&Parent>, &Rollback), With<Item>>,
mut players: Query<(
Entity,
&PlayerState,
Expand Down Expand Up @@ -62,16 +62,22 @@ pub fn handle_player_state(
if control.grab_just_pressed {
// If we don't have an item
if !has_item {
// For each actor colliding with the player
'colliders: for collider in collision_world.actor_collisions(player_ent) {
// If this is an item
if let Ok((.., item_body)) = items.get(collider) {
if !item_body.is_deactivated {
commands
.add(PlayerSetInventoryCommand::new(player_ent, Some(collider)));
break 'colliders;
}
}
let mut colliders = collision_world
// Get all things colliding with the player
.actor_collisions(player_ent)
.into_iter()
// Filter out anything not an item
.filter_map(|ent| items.get(ent).ok().map(|x| (ent, x)))
// Filter out any items that are being held by another player
.filter(|(_ent, (parent, _))| parent.is_none())
.collect::<Vec<_>>();

// Sort the items to provide deterministic item selection if we hare touching multiples
colliders.sort_by_key(|(_, (_, rollback))| rollback.id());

// Grab the first item we are touching
if let Some((item, _)) = colliders.get(0) {
commands.add(PlayerSetInventoryCommand::new(player_ent, Some(*item)));
}

// If we are already carrying an item
Expand Down
28 changes: 17 additions & 11 deletions src/player/state/states/midair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub fn player_state_transition(mut players: Query<(&mut PlayerState, &KinematicB
pub fn handle_player_state(
mut commands: Commands,
player_inputs: Res<PlayerInputs>,
items: Query<(Option<&Parent>, &KinematicBody), (With<Item>, Without<PlayerIdx>)>,
items: Query<(Option<&Parent>, &Rollback), With<Item>>,
mut players: Query<(
Entity,
&PlayerState,
Expand Down Expand Up @@ -53,17 +53,23 @@ pub fn handle_player_state(

// If we are grabbing
if control.grab_just_pressed {
// If we don't have an item
if !has_item {
// For each actor colliding with the player
'colliders: for collider in collision_world.actor_collisions(player_ent) {
if let Ok((.., item_body)) = items.get(collider) {
if !item_body.is_deactivated {
commands
.add(PlayerSetInventoryCommand::new(player_ent, Some(collider)));
break 'colliders;
}
}
let mut colliders = collision_world
// Get all things colliding with the player
.actor_collisions(player_ent)
.into_iter()
// Filter out anything not an item
.filter_map(|ent| items.get(ent).ok().map(|x| (ent, x)))
// Filter out any items that are being held by another player
.filter(|(_ent, (parent, _))| parent.is_none())
.collect::<Vec<_>>();

// Sort the items to provide deterministic item selection if we hare touching multiples
colliders.sort_by_key(|(_, (_, rollback))| rollback.id());

// Grab the first item we are touching
if let Some((item, _)) = colliders.get(0) {
commands.add(PlayerSetInventoryCommand::new(player_ent, Some(*item)));
}

// If we are already carrying an item
Expand Down
25 changes: 13 additions & 12 deletions src/player/state/states/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub fn player_state_transition(
pub fn handle_player_state(
mut commands: Commands,
player_inputs: Res<PlayerInputs>,
items: Query<(Option<&Parent>, &KinematicBody), (With<Item>, Without<PlayerIdx>)>,
items: Query<(Option<&Parent>, &Rollback), With<Item>>,
mut players: Query<(
Entity,
&PlayerState,
Expand Down Expand Up @@ -63,17 +63,18 @@ pub fn handle_player_state(
if control.grab_just_pressed {
// If we don't have an item
if !has_item {
// For each actor colliding with the player
'colliders: for collider in collision_world.actor_collisions(player_ent) {
// If this is an item
if let Ok((.., item_body)) = items.get(collider) {
if !item_body.is_deactivated {
commands
.add(PlayerSetInventoryCommand::new(player_ent, Some(collider)));
break 'colliders;
}
}
}
let mut colliders = collision_world
// Get all things colliding with the player
.actor_collisions(player_ent)
.into_iter()
// Filter out anything not an item
.filter_map(|ent| items.get(ent).ok().map(|x| (ent, x)))
// Filter out any items that are being held by another player
.filter(|(_ent, (parent, _))| parent.is_none())
.collect::<Vec<_>>();

// Sort the items to provide deterministic item selection if we hare touching multiples
colliders.sort_by_key(|(_, (_, rollback))| rollback.id());

// If we are already carrying an item
} else {
Expand Down

0 comments on commit 091da95

Please sign in to comment.