diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2025-03-16 13:41:17 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-16 13:41:17 -0500 |
| commit | b0bd992adcff71ee294dd05060e00e652f62a7b2 (patch) | |
| tree | 0a36d8b37befbc75c8c65cc2c8779c3df66bd87b /azalea-physics/src/collision/entity_collisions.rs | |
| parent | a95408cbcc05b5bd04a084b0a286b571069206f6 (diff) | |
| download | azalea-drasl-b0bd992adcff71ee294dd05060e00e652f62a7b2.tar.xz | |
Fluid physics fixes (#210)
* start fixing code related to fluid physics
* implement force_solid for blocks
* afk pool test
Diffstat (limited to 'azalea-physics/src/collision/entity_collisions.rs')
| -rw-r--r-- | azalea-physics/src/collision/entity_collisions.rs | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/azalea-physics/src/collision/entity_collisions.rs b/azalea-physics/src/collision/entity_collisions.rs new file mode 100644 index 00000000..1300cf34 --- /dev/null +++ b/azalea-physics/src/collision/entity_collisions.rs @@ -0,0 +1,97 @@ +use azalea_core::aabb::AABB; +use azalea_entity::{ + LocalEntity, Physics, + metadata::{AbstractBoat, Shulker}, +}; +use azalea_world::Instance; +use bevy_ecs::{ + entity::Entity, + query::{Or, With, Without}, + system::Query, +}; +use tracing::error; + +use super::VoxelShape; + +/// This query matches on entities that we can collide with. That is, boats and +/// shulkers. +/// +/// If you want to use this in a more complex query, use +/// [`CollidableEntityFilter`] as a filter instead. +pub type CollidableEntityQuery<'world, 'state> = Query<'world, 'state, (), CollidableEntityFilter>; +/// This filter matches on entities that we can collide with (boats and +/// shulkers). +/// +/// Use [`CollidableEntityQuery`] if you want an empty query that matches with +/// this. +pub type CollidableEntityFilter = Or<(With<AbstractBoat>, With<Shulker>)>; + +pub type PhysicsQuery<'world, 'state, 'a> = + Query<'world, 'state, &'a Physics, Without<LocalEntity>>; + +pub fn get_entity_collisions( + world: &Instance, + aabb: &AABB, + source_entity: Option<Entity>, + physics_query: &PhysicsQuery, + collidable_entity_query: &CollidableEntityQuery, +) -> Vec<VoxelShape> { + if aabb.size() < 1.0E-7 { + return vec![]; + } + + let collision_predicate = |entity| collidable_entity_query.get(entity).is_ok(); + + let collidable_entities = get_entities( + world, + source_entity, + &aabb.inflate_all(1.0E-7), + &collision_predicate, + physics_query, + ); + + collidable_entities + .into_iter() + .map(|(_entity, aabb)| VoxelShape::from(aabb)) + .collect() +} + +/// Return all entities that are colliding with the given bounding box and match +/// the given predicate. +/// +/// `source_entity` is the entity that the bounding box belongs to, and won't be +/// one of the returned entities. +pub fn get_entities( + world: &Instance, + source_entity: Option<Entity>, + aabb: &AABB, + predicate: &dyn Fn(Entity) -> bool, + physics_query: &PhysicsQuery, +) -> Vec<(Entity, AABB)> { + let mut matches = Vec::new(); + + super::world_collisions::for_entities_in_chunks_colliding_with( + world, + aabb, + |_chunk_pos, entities_in_chunk| { + // now check if the entity itself collides + for &candidate in entities_in_chunk { + if Some(candidate) != source_entity && predicate(candidate) { + let Ok(physics) = physics_query.get(candidate) else { + error!( + "Entity {candidate} (found from for_entities_in_chunks_colliding_with) is missing required components." + ); + continue; + }; + + let candidate_aabb = physics.bounding_box; + if aabb.intersects_aabb(&candidate_aabb) { + matches.push((candidate, physics.bounding_box)); + } + } + } + }, + ); + + matches +} |
