diff options
| author | mat <git@matdoes.dev> | 2025-09-27 18:41:36 -1030 |
|---|---|---|
| committer | mat <git@matdoes.dev> | 2025-09-27 20:26:41 -0845 |
| commit | 74dcb7b37d953ec4d45dd6aac4c8e598c87def7d (patch) | |
| tree | 22e6ab1849ee01d40f3d484ea0c8db52aa6649b5 | |
| parent | 63bef6486dc1f3c9ef4b4f0d71e139d7035b6432 (diff) | |
| download | azalea-drasl-74dcb7b37d953ec4d45dd6aac4c8e598c87def7d.tar.xz | |
allow picking other bots in hit results
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | azalea-client/src/plugins/interact/mod.rs | 8 | ||||
| -rw-r--r-- | azalea-client/src/plugins/interact/pick.rs | 25 | ||||
| -rw-r--r-- | azalea-client/src/plugins/movement.rs | 17 | ||||
| -rw-r--r-- | azalea-core/src/aabb.rs | 58 | ||||
| -rw-r--r-- | azalea-entity/src/dimensions.rs | 6 | ||||
| -rw-r--r-- | azalea-entity/src/lib.rs | 4 | ||||
| -rw-r--r-- | azalea-physics/src/clip.rs | 8 | ||||
| -rw-r--r-- | azalea-physics/src/collision/entity_collisions.rs | 53 | ||||
| -rw-r--r-- | azalea-physics/src/collision/mod.rs | 24 | ||||
| -rw-r--r-- | azalea-physics/src/collision/shape.rs | 26 | ||||
| -rw-r--r-- | azalea-physics/src/collision/world_collisions.rs | 14 | ||||
| -rw-r--r-- | azalea-physics/src/lib.rs | 9 | ||||
| -rw-r--r-- | azalea-physics/src/travel.rs | 26 | ||||
| -rw-r--r-- | azalea/examples/testbot/commands/debug.rs | 5 |
15 files changed, 162 insertions, 122 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b7ce01e..ee9b0d0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ is breaking anyways, semantic versioning is not followed. - `ClientsideCloseContainerEvent`, `MenuOpenedEvent`, and `CloseContainerEvent` are now triggers instead of events. - `Client::chat` now takes anything with `impl Into<String>`. - Some types related Azalea's bot plugin were moved to `azalea::bot::*`. +- `AABB` was renamed to `Aabb` to follow Rust naming guidelines. ### Fixed diff --git a/azalea-client/src/plugins/interact/mod.rs b/azalea-client/src/plugins/interact/mod.rs index 547d58ff..dc60ef66 100644 --- a/azalea-client/src/plugins/interact/mod.rs +++ b/azalea-client/src/plugins/interact/mod.rs @@ -18,7 +18,9 @@ use azalea_entity::{ clamp_look_direction, }; use azalea_inventory::{ItemStack, ItemStackData, components}; -use azalea_physics::{PhysicsSet, local_player::PhysicsState}; +use azalea_physics::{ + PhysicsSet, collision::entity_collisions::update_last_bounding_box, local_player::PhysicsState, +}; use azalea_protocol::packets::game::{ ServerboundInteract, ServerboundUseItem, s_interact::{self, InteractionHand}, @@ -58,7 +60,9 @@ impl Plugin for InteractPlugin { .in_set(UpdateAttributesSet) .chain(), handle_start_use_item_event, - update_hit_result_component.after(clamp_look_direction), + update_hit_result_component + .after(clamp_look_direction) + .after(update_last_bounding_box), handle_swing_arm_event, ) .after(InventorySet) diff --git a/azalea-client/src/plugins/interact/pick.rs b/azalea-client/src/plugins/interact/pick.rs index ae6c9502..580bb50c 100644 --- a/azalea-client/src/plugins/interact/pick.rs +++ b/azalea-client/src/plugins/interact/pick.rs @@ -1,5 +1,5 @@ use azalea_core::{ - aabb::AABB, + aabb::Aabb, direction::Direction, hit_result::{BlockHitResult, EntityHitResult, HitResult}, position::Vec3, @@ -15,7 +15,7 @@ use azalea_entity::{ }; use azalea_physics::{ clip::{BlockShapeType, ClipContext, FluidPickType}, - collision::entity_collisions::{PhysicsQuery, get_entities}, + collision::entity_collisions::{AabbQuery, get_entities}, }; use azalea_world::{Instance, InstanceContainer, InstanceName}; use bevy_ecs::prelude::*; @@ -44,7 +44,7 @@ pub fn update_hit_result_component( With<LocalEntity>, >, instance_container: Res<InstanceContainer>, - physics_query: PhysicsQuery, + aabb_query: AabbQuery, pickable_query: MaybePickableEntityQuery, ) { for ( @@ -76,7 +76,7 @@ pub fn update_hit_result_component( world: &world, entity_pick_range, block_pick_range, - physics_query: &physics_query, + aabb_query: &aabb_query, pickable_query: &pickable_query, }); if let Some(mut hit_result_ref) = hit_result_ref { @@ -109,7 +109,6 @@ pub type MaybePickableEntityQuery<'world, 'state, 'a> = Query< (With<AbstractLiving>, Without<Dead>), With<AbstractArrow>, )>, - Without<LocalEntity>, ), >; @@ -117,11 +116,11 @@ pub struct PickOpts<'world, 'state, 'a, 'b, 'c> { source_entity: Entity, look_direction: LookDirection, eye_position: Vec3, - aabb: &'a AABB, + aabb: &'a Aabb, world: &'a Instance, entity_pick_range: f64, block_pick_range: f64, - physics_query: &'a PhysicsQuery<'world, 'state, 'b>, + aabb_query: &'a AabbQuery<'world, 'state, 'b>, pickable_query: &'a MaybePickableEntityQuery<'world, 'state, 'c>, } @@ -163,6 +162,10 @@ pub fn pick(opts: PickOpts<'_, '_, '_, '_, '_>) -> HitResult { .inflate_all(inflate_by); let is_pickable = |entity: Entity| { + if entity == opts.source_entity { + return false; + } + // TODO: ender dragon has extra logic here. also, we shouldn't be able to pick // spectators. if let Ok((armor_stand_marker, arrow_in_ground)) = opts.pickable_query.get(entity) { @@ -180,7 +183,7 @@ pub fn pick(opts: PickOpts<'_, '_, '_, '_, '_>) -> HitResult { pick_range_squared: max_range_squared, predicate: &is_pickable, aabb: &pick_aabb, - physics_query: opts.physics_query, + aabb_query: opts.aabb_query, }); if let Some(entity_hit_result) = entity_hit_result @@ -246,8 +249,8 @@ struct PickEntityOpts<'world, 'state, 'a, 'b> { world: &'a azalea_world::Instance, pick_range_squared: f64, predicate: &'a dyn Fn(Entity) -> bool, - aabb: &'a AABB, - physics_query: &'a PhysicsQuery<'world, 'state, 'b>, + aabb: &'a Aabb, + aabb_query: &'a AabbQuery<'world, 'state, 'b>, } // port of getEntityHitResult @@ -260,7 +263,7 @@ fn pick_entity(opts: PickEntityOpts) -> Option<EntityHitResult> { Some(opts.source_entity), opts.aabb, opts.predicate, - opts.physics_query, + opts.aabb_query, ) { // TODO: if the entity is "REDIRECTABLE_PROJECTILE" then this should be 1.0. // azalea needs support for entity tags first for this to be possible. see diff --git a/azalea-client/src/plugins/movement.rs b/azalea-client/src/plugins/movement.rs index ad6779fa..48e7ecea 100644 --- a/azalea-client/src/plugins/movement.rs +++ b/azalea-client/src/plugins/movement.rs @@ -14,7 +14,7 @@ use azalea_entity::{ }; use azalea_physics::{ PhysicsSet, ai_step, - collision::entity_collisions::{CollidableEntityQuery, PhysicsQuery}, + collision::entity_collisions::{AabbQuery, CollidableEntityQuery, update_last_bounding_box}, local_player::{PhysicsState, SprintDirection, WalkDirection}, travel::{no_collision, travel}, }; @@ -73,7 +73,8 @@ impl Plugin for MovementPlugin { (handle_sprint, handle_walk, handle_knockback) .chain() .in_set(MoveEventsSet) - .after(update_bounding_box), + .after(update_bounding_box) + .after(update_last_bounding_box), ) .add_systems( GameTick, @@ -378,7 +379,7 @@ pub fn local_player_ai_step( ), (With<HasClientLoaded>, With<LocalEntity>), >, - physics_query: PhysicsQuery, + aabb_query: AabbQuery, collidable_entity_query: CollidableEntityQuery, ) { for ( @@ -409,7 +410,7 @@ pub fn local_player_ai_step( world: &world, entity, position: *position, - physics_query: &physics_query, + aabb_query: &aabb_query, collidable_entity_query: &collidable_entity_query, physics: &physics, }; @@ -708,7 +709,7 @@ pub fn update_pose( &InstanceHolder, &Position, )>, - physics_query: PhysicsQuery, + aabb_query: AabbQuery, collidable_entity_query: CollidableEntityQuery, ) { for (entity, mut pose, physics, physics_state, game_mode, instance_holder, position) in @@ -720,7 +721,7 @@ pub fn update_pose( world, entity, position: *position, - physics_query: &physics_query, + aabb_query: &aabb_query, collidable_entity_query: &collidable_entity_query, physics, }; @@ -763,7 +764,7 @@ struct CanPlayerFitCtx<'world, 'state, 'a, 'b> { world: &'a Instance, entity: Entity, position: Position, - physics_query: &'a PhysicsQuery<'world, 'state, 'b>, + aabb_query: &'a AabbQuery<'world, 'state, 'b>, collidable_entity_query: &'a CollidableEntityQuery<'world, 'state>, physics: &'a Physics, } @@ -773,7 +774,7 @@ fn can_player_fit_within_blocks_and_entities_when(ctx: &CanPlayerFitCtx, pose: P no_collision( ctx.world, Some(ctx.entity), - ctx.physics_query, + ctx.aabb_query, ctx.collidable_entity_query, ctx.physics, &calculate_dimensions(EntityKind::Player, pose).make_bounding_box(*ctx.position), diff --git a/azalea-core/src/aabb.rs b/azalea-core/src/aabb.rs index 09abf047..4e129ef7 100644 --- a/azalea-core/src/aabb.rs +++ b/azalea-core/src/aabb.rs @@ -5,9 +5,11 @@ use crate::{ position::{BlockPos, Vec3}, }; -/// A rectangular prism with a starting and ending point. +/// An axis-aligned bounding box. +/// +/// In other words, a rectangular prism with a starting and ending point. #[derive(Copy, Clone, Debug, PartialEq, Default)] -pub struct AABB { +pub struct Aabb { pub min: Vec3, pub max: Vec3, } @@ -27,8 +29,8 @@ pub struct ClipPointOpts<'a> { pub start: Vec3, } -impl AABB { - pub fn contract(&self, amount: Vec3) -> AABB { +impl Aabb { + pub fn contract(&self, amount: Vec3) -> Aabb { let mut min = self.min; let mut max = self.max; @@ -50,10 +52,10 @@ impl AABB { max.z -= amount.z; } - AABB { min, max } + Aabb { min, max } } - pub fn expand_towards(&self, other: Vec3) -> AABB { + pub fn expand_towards(&self, other: Vec3) -> Aabb { let mut min = self.min; let mut max = self.max; @@ -75,39 +77,39 @@ impl AABB { max.z += other.z; } - AABB { min, max } + Aabb { min, max } } - pub fn inflate(&self, amount: Vec3) -> AABB { + pub fn inflate(&self, amount: Vec3) -> Aabb { let min = self.min - amount; let max = self.max + amount; - AABB { min, max } + Aabb { min, max } } - pub fn inflate_all(&self, amount: f64) -> AABB { + pub fn inflate_all(&self, amount: f64) -> Aabb { self.inflate(Vec3::new(amount, amount, amount)) } - pub fn intersect(&self, other: &AABB) -> AABB { + pub fn intersect(&self, other: &Aabb) -> Aabb { let min = self.min.max(other.min); let max = self.max.min(other.max); - AABB { min, max } + Aabb { min, max } } - pub fn minmax(&self, other: &AABB) -> AABB { + pub fn minmax(&self, other: &Aabb) -> Aabb { let min = self.min.min(other.min); let max = self.max.max(other.max); - AABB { min, max } + Aabb { min, max } } - pub fn move_relative(&self, delta: Vec3) -> AABB { - AABB { + pub fn move_relative(&self, delta: Vec3) -> Aabb { + Aabb { min: self.min + delta, max: self.max + delta, } } - pub fn intersects_aabb(&self, other: &AABB) -> bool { + pub fn intersects_aabb(&self, other: &Aabb) -> bool { self.min.x < other.max.x && self.max.x > other.min.x && self.min.y < other.max.y @@ -118,7 +120,7 @@ impl AABB { pub fn intersects_vec3(&self, corner1: Vec3, corner2: Vec3) -> bool { let min = corner1.min(corner2); let max = corner1.max(corner2); - self.intersects_aabb(&AABB { min, max }) + self.intersects_aabb(&Aabb { min, max }) } pub fn contains(&self, point: Vec3) -> bool { @@ -146,10 +148,10 @@ impl AABB { ) } - pub fn deflate(&self, amount: Vec3) -> AABB { + pub fn deflate(&self, amount: Vec3) -> Aabb { self.inflate(Vec3::new(-amount.x, -amount.y, -amount.z)) } - pub fn deflate_all(&self, amount: f64) -> AABB { + pub fn deflate_all(&self, amount: f64) -> Aabb { self.deflate(Vec3::new(amount, amount, amount)) } @@ -168,7 +170,7 @@ impl AABB { } pub fn clip_iterable( - boxes: &[AABB], + boxes: &[Aabb], from: Vec3, to: Vec3, pos: BlockPos, @@ -204,7 +206,7 @@ impl AABB { dir: Option<Direction>, delta: Vec3, ) -> Option<Direction> { - AABB::get_direction(self.min, self.max, from, t, dir, delta) + Aabb::get_direction(self.min, self.max, from, t, dir, delta) } fn get_direction( @@ -373,8 +375,8 @@ impl AABB { ) } - pub fn of_size(center: Vec3, dx: f64, dy: f64, dz: f64) -> AABB { - AABB { + pub fn of_size(center: Vec3, dx: f64, dy: f64, dz: f64) -> Aabb { + Aabb { min: Vec3::new( center.x - dx / 2.0, center.y - dy / 2.0, @@ -395,7 +397,7 @@ impl AABB { axis.choose(self.min.x, self.min.y, self.min.z) } - pub fn collided_along_vector(&self, vector: Vec3, boxes: &[AABB]) -> bool { + pub fn collided_along_vector(&self, vector: Vec3, boxes: &[Aabb]) -> bool { let center = self.get_center(); let new_center = center + vector; @@ -419,7 +421,7 @@ impl AABB { } impl BlockPos { - pub fn between_closed_aabb(aabb: &AABB) -> Vec<BlockPos> { + pub fn between_closed_aabb(aabb: &Aabb) -> Vec<BlockPos> { BlockPos::between_closed(BlockPos::from(aabb.min), BlockPos::from(aabb.max)) } @@ -457,8 +459,8 @@ mod tests { #[test] fn test_aabb_clip_iterable() { assert_ne!( - AABB::clip_iterable( - &[AABB { + Aabb::clip_iterable( + &[Aabb { min: Vec3::new(0., 0., 0.), max: Vec3::new(1., 1., 1.), }], diff --git a/azalea-entity/src/dimensions.rs b/azalea-entity/src/dimensions.rs index 92c03e61..b3a69dc1 100644 --- a/azalea-entity/src/dimensions.rs +++ b/azalea-entity/src/dimensions.rs @@ -1,4 +1,4 @@ -use azalea_core::{aabb::AABB, position::Vec3}; +use azalea_core::{aabb::Aabb, position::Vec3}; use azalea_registry::EntityKind; use bevy_ecs::component::Component; @@ -40,10 +40,10 @@ impl EntityDimensions { Self { eye_height, ..self } } - pub fn make_bounding_box(&self, pos: Vec3) -> AABB { + pub fn make_bounding_box(&self, pos: Vec3) -> Aabb { let radius = (self.width / 2.0) as f64; let height = self.height as f64; - AABB { + Aabb { min: Vec3::new(pos.x - radius, pos.y, pos.z - radius), max: Vec3::new(pos.x + radius, pos.y + height, pos.z + radius), } diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index 6c3603e6..1ffce394 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -21,7 +21,7 @@ pub use attributes::Attributes; use azalea_block::{BlockState, fluid_state::FluidKind}; use azalea_buf::AzBuf; use azalea_core::{ - aabb::AABB, + aabb::Aabb, math, position::{BlockPos, ChunkPos, Vec3}, resource_location::ResourceLocation, @@ -355,7 +355,7 @@ pub struct Physics { /// The bounding box of the entity. This is more than just width and height, /// unlike dimensions. - pub bounding_box: AABB, + pub bounding_box: Aabb, pub has_impulse: bool, diff --git a/azalea-physics/src/clip.rs b/azalea-physics/src/clip.rs index 8d2b5dd1..dbab0da6 100644 --- a/azalea-physics/src/clip.rs +++ b/azalea-physics/src/clip.rs @@ -5,7 +5,7 @@ use azalea_block::{ fluid_state::{FluidKind, FluidState}, }; use azalea_core::{ - aabb::AABB, + aabb::Aabb, direction::{Axis, Direction}, hit_result::BlockHitResult, math::{self, EPSILON, lerp}, @@ -255,7 +255,7 @@ pub fn traverse_blocks<C, T>( } } -pub fn box_traverse_blocks(from: Vec3, to: Vec3, aabb: &AABB) -> HashSet<BlockPos> { +pub fn box_traverse_blocks(from: Vec3, to: Vec3, aabb: &Aabb) -> HashSet<BlockPos> { let delta = to - from; let traversed_blocks = BlockPos::between_closed_aabb(aabb); if delta.length_squared() < (0.99999_f32 * 0.99999) as f64 { @@ -279,7 +279,7 @@ pub fn add_collisions_along_travel( collisions: &mut HashSet<BlockPos>, from: Vec3, to: Vec3, - aabb: AABB, + aabb: Aabb, ) { let delta = to - from; let mut min_x = from.x.floor() as i32; @@ -345,7 +345,7 @@ pub fn add_collisions_along_travel( } step_count += 1; - let Some(clip_location) = AABB::clip_with_from_and_to( + let Some(clip_location) = Aabb::clip_with_from_and_to( Vec3::new(min_x as f64, min_y as f64, min_z as f64), Vec3::new((min_x + 1) as f64, (min_y + 1) as f64, (min_z + 1) as f64), from, diff --git a/azalea-physics/src/collision/entity_collisions.rs b/azalea-physics/src/collision/entity_collisions.rs index 1300cf34..af2db1f0 100644 --- a/azalea-physics/src/collision/entity_collisions.rs +++ b/azalea-physics/src/collision/entity_collisions.rs @@ -1,13 +1,14 @@ -use azalea_core::aabb::AABB; +use azalea_core::aabb::Aabb; use azalea_entity::{ - LocalEntity, Physics, + Physics, metadata::{AbstractBoat, Shulker}, }; use azalea_world::Instance; use bevy_ecs::{ + component::Component, entity::Entity, - query::{Or, With, Without}, - system::Query, + query::{Changed, Or, With}, + system::{Commands, Query}, }; use tracing::error; @@ -26,14 +27,34 @@ pub type CollidableEntityQuery<'world, 'state> = Query<'world, 'state, (), Colli /// this. pub type CollidableEntityFilter = Or<(With<AbstractBoat>, With<Shulker>)>; -pub type PhysicsQuery<'world, 'state, 'a> = - Query<'world, 'state, &'a Physics, Without<LocalEntity>>; +/// A component that mirrors the Physics::bounding_box of every entity, but is +/// updated before client-side physics is done. +#[derive(Component)] +pub struct LastBoundingBox(pub Aabb); + +pub type AabbQuery<'world, 'state, 'a> = Query<'world, 'state, &'a LastBoundingBox>; + +/// Update the [`LastBoundingBox`] for every entity. +pub fn update_last_bounding_box( + mut commands: Commands, + mut query: Query<(Entity, Option<&mut LastBoundingBox>, &Physics), Changed<Physics>>, +) { + for (entity, mut last_bounding_box, physics) in &mut query { + if let Some(last_bounding_box) = last_bounding_box.as_mut() { + last_bounding_box.0 = physics.bounding_box; + } else { + commands + .entity(entity) + .insert(LastBoundingBox(physics.bounding_box)); + } + } +} pub fn get_entity_collisions( world: &Instance, - aabb: &AABB, + aabb: &Aabb, source_entity: Option<Entity>, - physics_query: &PhysicsQuery, + aabb_query: &AabbQuery, collidable_entity_query: &CollidableEntityQuery, ) -> Vec<VoxelShape> { if aabb.size() < 1.0E-7 { @@ -47,7 +68,7 @@ pub fn get_entity_collisions( source_entity, &aabb.inflate_all(1.0E-7), &collision_predicate, - physics_query, + aabb_query, ); collidable_entities @@ -64,10 +85,10 @@ pub fn get_entity_collisions( pub fn get_entities( world: &Instance, source_entity: Option<Entity>, - aabb: &AABB, + aabb: &Aabb, predicate: &dyn Fn(Entity) -> bool, - physics_query: &PhysicsQuery, -) -> Vec<(Entity, AABB)> { + aabb_query: &AabbQuery, +) -> Vec<(Entity, Aabb)> { let mut matches = Vec::new(); super::world_collisions::for_entities_in_chunks_colliding_with( @@ -77,16 +98,16 @@ pub fn get_entities( // 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 { + let Ok(candidate_aabb) = aabb_query.get(candidate) else { error!( "Entity {candidate} (found from for_entities_in_chunks_colliding_with) is missing required components." ); continue; }; + let candidate_aabb = &candidate_aabb.0; - let candidate_aabb = physics.bounding_box; - if aabb.intersects_aabb(&candidate_aabb) { - matches.push((candidate, physics.bounding_box)); + if aabb.intersects_aabb(candidate_aabb) { + matches.push((candidate, candidate_aabb.to_owned())); } } } diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs index d8ac3a95..3702c8c1 100644 --- a/azalea-physics/src/collision/mod.rs +++ b/azalea-physics/src/collision/mod.rs @@ -9,7 +9,7 @@ use std::{ops::Add, sync::LazyLock}; use azalea_block::{BlockState, fluid_state::FluidState}; use azalea_core::{ - aabb::AABB, + aabb::Aabb, direction::Axis, math::{self, EPSILON}, position::{BlockPos, Vec3}, @@ -22,12 +22,14 @@ use azalea_world::{ChunkStorage, Instance, MoveEntityError}; use bevy_ecs::{entity::Entity, world::Mut}; pub use blocks::BlockWithShape; pub use discrete_voxel_shape::*; -use entity_collisions::{CollidableEntityQuery, PhysicsQuery, get_entity_collisions}; +use entity_collisions::{CollidableEntityQuery, get_entity_collisions}; pub use shape::*; use tracing::warn; use self::world_collisions::get_block_collisions; -use crate::{local_player::PhysicsState, travel::no_collision}; +use crate::{ + collision::entity_collisions::AabbQuery, local_player::PhysicsState, travel::no_collision, +}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MoverType { @@ -45,7 +47,7 @@ fn collide(ctx: &MoveCtx, movement: Vec3) -> Vec3 { ctx.world, &entity_bounding_box.expand_towards(movement), Some(ctx.source_entity), - ctx.physics_query, + ctx.aabb_query, ctx.collidable_entity_query, ); let world = ctx.world; @@ -111,7 +113,7 @@ pub struct MoveCtx<'world, 'state, 'a, 'b> { pub position: Mut<'a, Position>, pub physics: &'a mut Physics, pub source_entity: Entity, - pub physics_query: &'a PhysicsQuery<'world, 'state, 'b>, + pub aabb_query: &'a AabbQuery<'world, 'state, 'b>, pub collidable_entity_query: &'a CollidableEntityQuery<'world, 'state>, pub physics_state: Option<&'a PhysicsState>, pub attributes: &'a Attributes, @@ -269,7 +271,7 @@ fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 physics: move_ctx.physics, world: move_ctx.world, source_entity: move_ctx.source_entity, - physics_query: move_ctx.physics_query, + aabb_query: move_ctx.aabb_query, collidable_entity_query: move_ctx.collidable_entity_query, }; @@ -340,7 +342,7 @@ pub struct CanFallAtLeastCtx<'world, 'state, 'a, 'b> { physics: &'a Physics, world: &'a Instance, source_entity: Entity, - physics_query: &'a PhysicsQuery<'world, 'state, 'b>, + aabb_query: &'a AabbQuery<'world, 'state, 'b>, collidable_entity_query: &'a CollidableEntityQuery<'world, 'state>, } @@ -351,7 +353,7 @@ fn can_fall_at_least( max_up_step: f64, ) -> bool { let aabb = ctx.physics.bounding_box; - let aabb = AABB { + let aabb = Aabb { min: Vec3 { x: aabb.min.x + EPSILON + delta_x, y: aabb.min.y - max_up_step - EPSILON, @@ -366,7 +368,7 @@ fn can_fall_at_least( no_collision( ctx.world, Some(ctx.source_entity), - ctx.physics_query, + ctx.aabb_query, ctx.collidable_entity_query, ctx.physics, &aabb, @@ -376,7 +378,7 @@ fn can_fall_at_least( fn collide_bounding_box( movement: Vec3, - entity_bounding_box: &AABB, + entity_bounding_box: &Aabb, world: &Instance, entity_collisions: &[VoxelShape], ) -> Vec3 { @@ -396,7 +398,7 @@ fn collide_bounding_box( fn collide_with_shapes( mut movement: Vec3, - mut entity_box: AABB, + mut entity_box: Aabb, collision_boxes: &[VoxelShape], ) -> Vec3 { if collision_boxes.is_empty() { diff --git a/azalea-physics/src/collision/shape.rs b/azalea-physics/src/collision/shape.rs index 9caae590..96506922 100644 --- a/azalea-physics/src/collision/shape.rs +++ b/azalea-physics/src/collision/shape.rs @@ -8,7 +8,7 @@ use azalea_core::{ }; use super::mergers::IndexMerger; -use crate::collision::{AABB, BitSetDiscreteVoxelShape, DiscreteVoxelShape}; +use crate::collision::{Aabb, BitSetDiscreteVoxelShape, DiscreteVoxelShape}; pub struct Shapes; @@ -99,7 +99,7 @@ impl Shapes { pub fn collide( axis: Axis, - entity_box: &AABB, + entity_box: &Aabb, collision_boxes: &[VoxelShape], mut movement: f64, ) -> f64 { @@ -432,14 +432,14 @@ impl VoxelShape { world_border: false, }) } else { - AABB::clip_iterable(&self.to_aabbs(), from, to, block_pos) + Aabb::clip_iterable(&self.to_aabbs(), from, to, block_pos) } } - pub fn collide(&self, axis: Axis, entity_box: &AABB, movement: f64) -> f64 { + pub fn collide(&self, axis: Axis, entity_box: &Aabb, movement: f64) -> f64 { self.collide_x(AxisCycle::between(axis, Axis::X), entity_box, movement) } - pub fn collide_x(&self, axis_cycle: AxisCycle, entity_box: &AABB, mut movement: f64) -> f64 { + pub fn collide_x(&self, axis_cycle: AxisCycle, entity_box: &Aabb, mut movement: f64) -> f64 { if self.shape().is_empty() { return movement; } @@ -550,10 +550,10 @@ impl VoxelShape { ); } - pub fn to_aabbs(&self) -> Vec<AABB> { + pub fn to_aabbs(&self) -> Vec<Aabb> { let mut aabbs = Vec::new(); self.for_all_boxes(|min_x, min_y, min_z, max_x, max_y, max_z| { - aabbs.push(AABB { + aabbs.push(Aabb { min: Vec3::new(min_x, min_y, min_z), max: Vec3::new(max_x, max_y, max_z), }); @@ -561,24 +561,24 @@ impl VoxelShape { aabbs } - pub fn bounds(&self) -> AABB { + pub fn bounds(&self) -> Aabb { assert!(!self.is_empty(), "Can't get bounds for empty shape"); - AABB { + Aabb { min: Vec3::new(self.min(Axis::X), self.min(Axis::Y), self.min(Axis::Z)), max: Vec3::new(self.max(Axis::X), self.max(Axis::Y), self.max(Axis::Z)), } } } -impl From<&AABB> for VoxelShape { - fn from(aabb: &AABB) -> Self { +impl From<&Aabb> for VoxelShape { + fn from(aabb: &Aabb) -> Self { box_shape( aabb.min.x, aabb.min.y, aabb.min.z, aabb.max.x, aabb.max.y, aabb.max.z, ) } } -impl From<AABB> for VoxelShape { - fn from(aabb: AABB) -> Self { +impl From<Aabb> for VoxelShape { + fn from(aabb: Aabb) -> Self { VoxelShape::from(&aabb) } } diff --git a/azalea-physics/src/collision/world_collisions.rs b/azalea-physics/src/collision/world_collisions.rs index 11e8946f..cd883649 100644 --- a/azalea-physics/src/collision/world_collisions.rs +++ b/azalea-physics/src/collision/world_collisions.rs @@ -12,9 +12,9 @@ use bevy_ecs::entity::Entity; use parking_lot::RwLock; use super::{BLOCK_SHAPE, Shapes}; -use crate::collision::{AABB, BlockWithShape, VoxelShape}; +use crate::collision::{Aabb, BlockWithShape, VoxelShape}; -pub fn get_block_collisions(world: &Instance, aabb: &AABB) -> Vec<VoxelShape> { +pub fn get_block_collisions(world: &Instance, aabb: &Aabb) -> Vec<VoxelShape> { let mut state = BlockCollisionsState::new(world, aabb, EntityCollisionContext::of(None)); let mut block_collisions = Vec::new(); @@ -34,7 +34,7 @@ pub fn get_block_collisions(world: &Instance, aabb: &AABB) -> Vec<VoxelShape> { block_collisions } -pub fn get_block_and_liquid_collisions(world: &Instance, aabb: &AABB) -> Vec<VoxelShape> { +pub fn get_block_and_liquid_collisions(world: &Instance, aabb: &Aabb) -> Vec<VoxelShape> { let mut state = BlockCollisionsState::new( world, aabb, @@ -60,7 +60,7 @@ pub fn get_block_and_liquid_collisions(world: &Instance, aabb: &AABB) -> Vec<Vox pub struct BlockCollisionsState<'a> { pub world: &'a Instance, - pub aabb: &'a AABB, + pub aabb: &'a Aabb, pub entity_shape: VoxelShape, pub cursor: Cursor3d, @@ -104,7 +104,7 @@ impl<'a> BlockCollisionsState<'a> { // if it's a full block do a faster collision check if block_state.is_collision_shape_full() { - if !self.aabb.intersects_aabb(&AABB { + if !self.aabb.intersects_aabb(&Aabb { min: item.pos.to_vec3_floored(), max: (item.pos + 1).to_vec3_floored(), }) { @@ -126,7 +126,7 @@ impl<'a> BlockCollisionsState<'a> { block_collisions.push(block_shape); } - pub fn new(world: &'a Instance, aabb: &'a AABB, context: EntityCollisionContext) -> Self { + pub fn new(world: &'a Instance, aabb: &'a Aabb, context: EntityCollisionContext) -> Self { let origin = BlockPos { x: (aabb.min.x - EPSILON).floor() as i32 - 1, y: (aabb.min.y - EPSILON).floor() as i32 - 1, @@ -284,7 +284,7 @@ impl CanStandOnFluidPredicate { /// then maybe you should try having it do that instead. pub fn for_entities_in_chunks_colliding_with( world: &Instance, - aabb: &AABB, + aabb: &Aabb, mut consumer: impl FnMut(ChunkPos, &HashSet<Entity>), ) { let min_section = ChunkSectionPos::from(aabb.min - Vec3::new(2., 4., 2.)); diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index fb62b48b..19b58e5c 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -22,12 +22,12 @@ use azalea_entity::{ }; use azalea_registry::{Block, EntityKind}; use azalea_world::{Instance, InstanceContainer, InstanceName}; -use bevy_app::{App, Plugin}; +use bevy_app::{App, Plugin, Update}; use bevy_ecs::prelude::*; use clip::box_traverse_blocks; use collision::{BLOCK_SHAPE, BlockWithShape, VoxelShape, move_colliding}; -use crate::collision::MoveCtx; +use crate::collision::{MoveCtx, entity_collisions::update_last_bounding_box}; /// A Bevy [`SystemSet`] for running physics that makes entities do things. #[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)] @@ -49,6 +49,11 @@ impl Plugin for PhysicsPlugin { .chain() .in_set(PhysicsSet) .after(azalea_entity::update_in_loaded_chunk), + ) + // we want this to happen after packets are handled but before physics + .add_systems( + Update, + update_last_bounding_box.after(azalea_entity::update_bounding_box), ); } } diff --git a/azalea-physics/src/travel.rs b/azalea-physics/src/travel.rs index 1c473a45..e5391bba 100644 --- a/azalea-physics/src/travel.rs +++ b/azalea-physics/src/travel.rs @@ -1,6 +1,6 @@ use azalea_block::{BlockState, BlockTrait, fluid_state::FluidState}; use azalea_core::{ - aabb::AABB, + aabb::Aabb, position::{BlockPos, Vec3}, }; use azalea_entity::{ @@ -13,7 +13,7 @@ use bevy_ecs::prelude::*; use crate::{ collision::{ MoveCtx, MoverType, Shapes, - entity_collisions::{CollidableEntityQuery, PhysicsQuery, get_entity_collisions}, + entity_collisions::{AabbQuery, CollidableEntityQuery, get_entity_collisions}, move_colliding, world_collisions::{get_block_and_liquid_collisions, get_block_collisions}, }, @@ -43,7 +43,7 @@ pub fn travel( (With<LocalEntity>, With<HasClientLoaded>), >, instance_container: Res<InstanceContainer>, - physics_query: PhysicsQuery, + aabb_query: AabbQuery, collidable_entity_query: CollidableEntityQuery, ) { for ( @@ -76,7 +76,7 @@ pub fn travel( position, physics: &mut physics, source_entity: entity, - physics_query: &physics_query, + aabb_query: &aabb_query, collidable_entity_query: &collidable_entity_query, physics_state, attributes, @@ -214,7 +214,7 @@ fn travel_in_fluid(ctx: &mut MoveCtx) { && is_free( ctx.world, ctx.source_entity, - ctx.physics_query, + ctx.aabb_query, ctx.collidable_entity_query, ctx.physics, ctx.physics.bounding_box, @@ -254,10 +254,10 @@ fn get_fluid_falling_adjusted_movement( fn is_free( world: &Instance, source_entity: Entity, - physics_query: &PhysicsQuery, + aabb_query: &AabbQuery, collidable_entity_query: &CollidableEntityQuery, entity_physics: &Physics, - bounding_box: AABB, + bounding_box: Aabb, delta: Vec3, ) -> bool { let bounding_box = bounding_box.move_relative(delta); @@ -265,7 +265,7 @@ fn is_free( no_collision( world, Some(source_entity), - physics_query, + aabb_query, collidable_entity_query, entity_physics, &bounding_box, @@ -276,10 +276,10 @@ fn is_free( pub fn no_collision( world: &Instance, source_entity: Option<Entity>, - physics_query: &PhysicsQuery, + aabb_query: &AabbQuery, collidable_entity_query: &CollidableEntityQuery, entity_physics: &Physics, - aabb: &AABB, + aabb: &Aabb, include_liquid_collisions: bool, ) -> bool { let collisions = if include_liquid_collisions { @@ -298,7 +298,7 @@ pub fn no_collision( world, aabb, source_entity, - physics_query, + aabb_query, collidable_entity_query, ) .is_empty() @@ -317,13 +317,13 @@ pub fn no_collision( } } -fn border_collision(_entity_physics: &Physics, _aabb: &AABB) -> Option<AABB> { +fn border_collision(_entity_physics: &Physics, _aabb: &Aabb) -> Option<Aabb> { // TODO: implement world border, see CollisionGetter.borderCollision None } -fn contains_any_liquid(world: &Instance, bounding_box: AABB) -> bool { +fn contains_any_liquid(world: &Instance, bounding_box: Aabb) -> bool { let min = bounding_box.min.to_block_pos_floor(); let max = bounding_box.max.to_block_pos_ceil(); diff --git a/azalea/examples/testbot/commands/debug.rs b/azalea/examples/testbot/commands/debug.rs index 06a49ce2..23e29b00 100644 --- a/azalea/examples/testbot/commands/debug.rs +++ b/azalea/examples/testbot/commands/debug.rs @@ -79,9 +79,10 @@ pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) { commands.register(literal("whoareyou").executes(|ctx: &Ctx| { let source = ctx.source.lock(); source.reply(format!( - "I am {} ({})", + "I am {} ({}, {})", source.bot.username(), - source.bot.uuid() + source.bot.uuid(), + source.bot.entity )); 1 })); |
