diff --git a/src/player/state/states/idle.rs b/src/player/state/states/idle.rs index aa2e71c822..3a27674e40 100644 --- a/src/player/state/states/idle.rs +++ b/src/player/state/states/idle.rs @@ -26,7 +26,7 @@ pub fn player_state_transition( pub fn handle_player_state( mut commands: Commands, player_inputs: Res, - items: Query<(Option<&Parent>, &KinematicBody), (With, Without)>, + items: Query<(Option<&Parent>, &Rollback), With>, mut players: Query<( Entity, &PlayerState, @@ -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::>(); + + // 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 diff --git a/src/player/state/states/midair.rs b/src/player/state/states/midair.rs index f633a141b1..1cb1f9ced9 100644 --- a/src/player/state/states/midair.rs +++ b/src/player/state/states/midair.rs @@ -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, - items: Query<(Option<&Parent>, &KinematicBody), (With, Without)>, + items: Query<(Option<&Parent>, &Rollback), With>, mut players: Query<( Entity, &PlayerState, @@ -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::>(); + + // 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 diff --git a/src/player/state/states/walk.rs b/src/player/state/states/walk.rs index 20a0627f80..5970474a50 100644 --- a/src/player/state/states/walk.rs +++ b/src/player/state/states/walk.rs @@ -27,7 +27,7 @@ pub fn player_state_transition( pub fn handle_player_state( mut commands: Commands, player_inputs: Res, - items: Query<(Option<&Parent>, &KinematicBody), (With, Without)>, + items: Query<(Option<&Parent>, &Rollback), With>, mut players: Query<( Entity, &PlayerState, @@ -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::>(); + + // 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 {