aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--azalea-client/src/plugins/interact/mod.rs8
-rw-r--r--azalea-client/src/plugins/interact/pick.rs25
-rw-r--r--azalea-client/src/plugins/movement.rs17
-rw-r--r--azalea-core/src/aabb.rs58
-rw-r--r--azalea-entity/src/dimensions.rs6
-rw-r--r--azalea-entity/src/lib.rs4
-rw-r--r--azalea-physics/src/clip.rs8
-rw-r--r--azalea-physics/src/collision/entity_collisions.rs53
-rw-r--r--azalea-physics/src/collision/mod.rs24
-rw-r--r--azalea-physics/src/collision/shape.rs26
-rw-r--r--azalea-physics/src/collision/world_collisions.rs14
-rw-r--r--azalea-physics/src/lib.rs9
-rw-r--r--azalea-physics/src/travel.rs26
-rw-r--r--azalea/examples/testbot/commands/debug.rs5
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
}));