mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
entity collisions
This commit is contained in:
parent
b0bd992adc
commit
ca2e0b3922
5 changed files with 86 additions and 74 deletions
|
@ -17,7 +17,7 @@ _Currently supported Minecraft version: `1.21.4`._
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- [Accurate physics](https://github.com/azalea-rs/azalea/blob/main/azalea-physics/src/lib.rs) (but some features like entity collisions and elytras aren't yet implemented)
|
- [Accurate physics](https://github.com/azalea-rs/azalea/blob/main/azalea-physics/src/lib.rs) (but some features like entity pushing and elytras aren't yet implemented)
|
||||||
- [Pathfinder](https://azalea.matdoes.dev/azalea/pathfinder/index.html)
|
- [Pathfinder](https://azalea.matdoes.dev/azalea/pathfinder/index.html)
|
||||||
- [Swarms](https://azalea.matdoes.dev/azalea/swarm/index.html)
|
- [Swarms](https://azalea.matdoes.dev/azalea/swarm/index.html)
|
||||||
- [Breaking blocks](https://azalea.matdoes.dev/azalea/struct.Client.html#method.mine)
|
- [Breaking blocks](https://azalea.matdoes.dev/azalea/struct.Client.html#method.mine)
|
||||||
|
|
|
@ -125,6 +125,16 @@ macro_rules! vec3_impl {
|
||||||
z: self.z,
|
z: self.z,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_x(&self, x: $type) -> Self {
|
||||||
|
Self { x, ..*self }
|
||||||
|
}
|
||||||
|
pub fn with_y(&self, y: $type) -> Self {
|
||||||
|
Self { y, ..*self }
|
||||||
|
}
|
||||||
|
pub fn with_z(&self, z: $type) -> Self {
|
||||||
|
Self { z, ..*self }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add for &$name {
|
impl Add for &$name {
|
||||||
|
|
|
@ -15,9 +15,10 @@ use azalea_core::{
|
||||||
position::{BlockPos, Vec3},
|
position::{BlockPos, Vec3},
|
||||||
};
|
};
|
||||||
use azalea_world::{ChunkStorage, Instance, MoveEntityError};
|
use azalea_world::{ChunkStorage, Instance, MoveEntityError};
|
||||||
use bevy_ecs::world::Mut;
|
use bevy_ecs::{entity::Entity, world::Mut};
|
||||||
pub use blocks::BlockWithShape;
|
pub use blocks::BlockWithShape;
|
||||||
pub use discrete_voxel_shape::*;
|
pub use discrete_voxel_shape::*;
|
||||||
|
use entity_collisions::{CollidableEntityQuery, PhysicsQuery, get_entity_collisions};
|
||||||
pub use shape::*;
|
pub use shape::*;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
|
@ -32,50 +33,27 @@ pub enum MoverType {
|
||||||
Shulker,
|
Shulker,
|
||||||
}
|
}
|
||||||
|
|
||||||
// private Vec3 collide(Vec3 var1) {
|
// Entity.collide
|
||||||
// AABB var2 = this.getBoundingBox();
|
fn collide(
|
||||||
// List var3 = this.level.getEntityCollisions(this,
|
movement: &Vec3,
|
||||||
// var2.expandTowards(var1)); Vec3 var4 = var1.lengthSqr() == 0.0D ?
|
world: &Instance,
|
||||||
// var1 : collideBoundingBox(this, var1, var2, this.level, var3);
|
physics: &azalea_entity::Physics,
|
||||||
// boolean var5 = var1.x != var4.x;
|
source_entity: Option<Entity>,
|
||||||
// boolean var6 = var1.y != var4.y;
|
physics_query: &PhysicsQuery,
|
||||||
// boolean var7 = var1.z != var4.z;
|
collidable_entity_query: &CollidableEntityQuery,
|
||||||
// boolean var8 = this.onGround || var6 && var1.y < 0.0D;
|
) -> Vec3 {
|
||||||
// if (this.maxUpStep > 0.0F && var8 && (var5 || var7)) {
|
|
||||||
// Vec3 var9 = collideBoundingBox(this, new Vec3(var1.x,
|
|
||||||
// (double)this.maxUpStep, var1.z), var2, this.level, var3); Vec3
|
|
||||||
// var10 = collideBoundingBox(this, new Vec3(0.0D, (double)this.maxUpStep,
|
|
||||||
// 0.0D), var2.expandTowards(var1.x, 0.0D, var1.z), this.level, var3);
|
|
||||||
// if (var10.y < (double)this.maxUpStep) {
|
|
||||||
// Vec3 var11 = collideBoundingBox(this, new Vec3(var1.x, 0.0D,
|
|
||||||
// var1.z), var2.move(var10), this.level, var3).add(var10); if
|
|
||||||
// (var11.horizontalDistanceSqr() > var9.horizontalDistanceSqr()) {
|
|
||||||
// var9 = var11;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (var9.horizontalDistanceSqr() > var4.horizontalDistanceSqr()) {
|
|
||||||
// return var9.add(collideBoundingBox(this, new Vec3(0.0D, -var9.y +
|
|
||||||
// var1.y, 0.0D), var2.move(var9), this.level, var3)); }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return var4;
|
|
||||||
// }
|
|
||||||
fn collide(movement: &Vec3, world: &Instance, physics: &azalea_entity::Physics) -> Vec3 {
|
|
||||||
let entity_bounding_box = physics.bounding_box;
|
let entity_bounding_box = physics.bounding_box;
|
||||||
// TODO: get_entity_collisions
|
let entity_collisions = get_entity_collisions(
|
||||||
// let entity_collisions = world.get_entity_collisions(self,
|
world,
|
||||||
// entity_bounding_box.expand_towards(movement));
|
&entity_bounding_box.expand_towards(movement),
|
||||||
let entity_collisions = Vec::new();
|
source_entity,
|
||||||
|
physics_query,
|
||||||
|
collidable_entity_query,
|
||||||
|
);
|
||||||
let collided_delta = if movement.length_squared() == 0.0 {
|
let collided_delta = if movement.length_squared() == 0.0 {
|
||||||
*movement
|
*movement
|
||||||
} else {
|
} else {
|
||||||
collide_bounding_box(
|
collide_bounding_box(movement, &entity_bounding_box, world, &entity_collisions)
|
||||||
movement,
|
|
||||||
&entity_bounding_box,
|
|
||||||
world,
|
|
||||||
entity_collisions.clone(),
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let x_collision = movement.x != collided_delta.x;
|
let x_collision = movement.x != collided_delta.x;
|
||||||
|
@ -87,35 +65,23 @@ fn collide(movement: &Vec3, world: &Instance, physics: &azalea_entity::Physics)
|
||||||
let max_up_step = 0.6;
|
let max_up_step = 0.6;
|
||||||
if max_up_step > 0. && on_ground && (x_collision || z_collision) {
|
if max_up_step > 0. && on_ground && (x_collision || z_collision) {
|
||||||
let mut step_to_delta = collide_bounding_box(
|
let mut step_to_delta = collide_bounding_box(
|
||||||
&Vec3 {
|
&movement.with_y(max_up_step),
|
||||||
x: movement.x,
|
|
||||||
y: max_up_step,
|
|
||||||
z: movement.z,
|
|
||||||
},
|
|
||||||
&entity_bounding_box,
|
&entity_bounding_box,
|
||||||
world,
|
world,
|
||||||
entity_collisions.clone(),
|
&entity_collisions,
|
||||||
);
|
);
|
||||||
let directly_up_delta = collide_bounding_box(
|
let directly_up_delta = collide_bounding_box(
|
||||||
&Vec3 {
|
&Vec3::ZERO.with_y(max_up_step),
|
||||||
x: 0.,
|
|
||||||
y: max_up_step,
|
|
||||||
z: 0.,
|
|
||||||
},
|
|
||||||
&entity_bounding_box.expand_towards(&Vec3::new(movement.x, 0., movement.z)),
|
&entity_bounding_box.expand_towards(&Vec3::new(movement.x, 0., movement.z)),
|
||||||
world,
|
world,
|
||||||
entity_collisions.clone(),
|
&entity_collisions,
|
||||||
);
|
);
|
||||||
if directly_up_delta.y < max_up_step {
|
if directly_up_delta.y < max_up_step {
|
||||||
let target_movement = collide_bounding_box(
|
let target_movement = collide_bounding_box(
|
||||||
&Vec3 {
|
&movement.with_y(0.),
|
||||||
x: movement.x,
|
|
||||||
y: 0.,
|
|
||||||
z: movement.z,
|
|
||||||
},
|
|
||||||
&entity_bounding_box.move_relative(directly_up_delta),
|
&entity_bounding_box.move_relative(directly_up_delta),
|
||||||
world,
|
world,
|
||||||
entity_collisions.clone(),
|
&entity_collisions,
|
||||||
)
|
)
|
||||||
.add(directly_up_delta);
|
.add(directly_up_delta);
|
||||||
if target_movement.horizontal_distance_squared()
|
if target_movement.horizontal_distance_squared()
|
||||||
|
@ -129,14 +95,10 @@ fn collide(movement: &Vec3, world: &Instance, physics: &azalea_entity::Physics)
|
||||||
> collided_delta.horizontal_distance_squared()
|
> collided_delta.horizontal_distance_squared()
|
||||||
{
|
{
|
||||||
return step_to_delta.add(collide_bounding_box(
|
return step_to_delta.add(collide_bounding_box(
|
||||||
&Vec3 {
|
&Vec3::ZERO.with_y(-step_to_delta.y + movement.y),
|
||||||
x: 0.,
|
|
||||||
y: -step_to_delta.y + movement.y,
|
|
||||||
z: 0.,
|
|
||||||
},
|
|
||||||
&entity_bounding_box.move_relative(step_to_delta),
|
&entity_bounding_box.move_relative(step_to_delta),
|
||||||
world,
|
world,
|
||||||
entity_collisions.clone(),
|
&entity_collisions,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,12 +109,16 @@ fn collide(movement: &Vec3, world: &Instance, physics: &azalea_entity::Physics)
|
||||||
/// Move an entity by a given delta, checking for collisions.
|
/// Move an entity by a given delta, checking for collisions.
|
||||||
///
|
///
|
||||||
/// In Mojmap, this is `Entity.move`.
|
/// In Mojmap, this is `Entity.move`.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn move_colliding(
|
pub fn move_colliding(
|
||||||
_mover_type: MoverType,
|
_mover_type: MoverType,
|
||||||
movement: &Vec3,
|
movement: &Vec3,
|
||||||
world: &Instance,
|
world: &Instance,
|
||||||
position: &mut Mut<azalea_entity::Position>,
|
position: &mut Mut<azalea_entity::Position>,
|
||||||
physics: &mut azalea_entity::Physics,
|
physics: &mut azalea_entity::Physics,
|
||||||
|
source_entity: Option<Entity>,
|
||||||
|
physics_query: &PhysicsQuery,
|
||||||
|
collidable_entity_query: &CollidableEntityQuery,
|
||||||
) -> Result<(), MoveEntityError> {
|
) -> Result<(), MoveEntityError> {
|
||||||
// TODO: do all these
|
// TODO: do all these
|
||||||
|
|
||||||
|
@ -175,7 +141,14 @@ pub fn move_colliding(
|
||||||
|
|
||||||
// movement = this.maybeBackOffFromEdge(movement, moverType);
|
// movement = this.maybeBackOffFromEdge(movement, moverType);
|
||||||
|
|
||||||
let collide_result = collide(movement, world, physics);
|
let collide_result = collide(
|
||||||
|
movement,
|
||||||
|
world,
|
||||||
|
physics,
|
||||||
|
source_entity,
|
||||||
|
physics_query,
|
||||||
|
collidable_entity_query,
|
||||||
|
);
|
||||||
|
|
||||||
let move_distance = collide_result.length_squared();
|
let move_distance = collide_result.length_squared();
|
||||||
|
|
||||||
|
@ -269,12 +242,12 @@ fn collide_bounding_box(
|
||||||
movement: &Vec3,
|
movement: &Vec3,
|
||||||
entity_bounding_box: &AABB,
|
entity_bounding_box: &AABB,
|
||||||
world: &Instance,
|
world: &Instance,
|
||||||
entity_collisions: Vec<VoxelShape>,
|
entity_collisions: &[VoxelShape],
|
||||||
) -> Vec3 {
|
) -> Vec3 {
|
||||||
let mut collision_boxes: Vec<VoxelShape> = Vec::with_capacity(entity_collisions.len() + 1);
|
let mut collision_boxes: Vec<VoxelShape> = Vec::with_capacity(entity_collisions.len() + 1);
|
||||||
|
|
||||||
if !entity_collisions.is_empty() {
|
if !entity_collisions.is_empty() {
|
||||||
collision_boxes.extend(entity_collisions);
|
collision_boxes.extend_from_slice(entity_collisions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: world border
|
// TODO: world border
|
||||||
|
|
|
@ -21,13 +21,18 @@ use azalea_entity::{
|
||||||
use azalea_world::{Instance, InstanceContainer, InstanceName};
|
use azalea_world::{Instance, InstanceContainer, InstanceName};
|
||||||
use bevy_app::{App, Plugin};
|
use bevy_app::{App, Plugin};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
|
entity::Entity,
|
||||||
query::With,
|
query::With,
|
||||||
schedule::{IntoSystemConfigs, SystemSet},
|
schedule::{IntoSystemConfigs, SystemSet},
|
||||||
system::{Query, Res},
|
system::{Query, Res},
|
||||||
world::Mut,
|
world::Mut,
|
||||||
};
|
};
|
||||||
use clip::box_traverse_blocks;
|
use clip::box_traverse_blocks;
|
||||||
use collision::{BLOCK_SHAPE, BlockWithShape, MoverType, VoxelShape, move_colliding};
|
use collision::{
|
||||||
|
BLOCK_SHAPE, BlockWithShape, MoverType, VoxelShape,
|
||||||
|
entity_collisions::{CollidableEntityQuery, PhysicsQuery},
|
||||||
|
move_colliding,
|
||||||
|
};
|
||||||
|
|
||||||
/// A Bevy [`SystemSet`] for running physics that makes entities do things.
|
/// A Bevy [`SystemSet`] for running physics that makes entities do things.
|
||||||
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
|
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
|
||||||
|
@ -352,7 +357,7 @@ fn get_block_pos_below_that_affects_movement(position: &Position) -> BlockPos {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Options for [`handle_relative_friction_and_calculate_movement`]
|
/// Options for [`handle_relative_friction_and_calculate_movement`]
|
||||||
struct HandleRelativeFrictionAndCalculateMovementOpts<'a> {
|
struct HandleRelativeFrictionAndCalculateMovementOpts<'a, 'b, 'world, 'state> {
|
||||||
block_friction: f32,
|
block_friction: f32,
|
||||||
world: &'a Instance,
|
world: &'a Instance,
|
||||||
physics: &'a mut Physics,
|
physics: &'a mut Physics,
|
||||||
|
@ -363,6 +368,9 @@ struct HandleRelativeFrictionAndCalculateMovementOpts<'a> {
|
||||||
on_climbable: &'a OnClimbable,
|
on_climbable: &'a OnClimbable,
|
||||||
pose: Option<&'a Pose>,
|
pose: Option<&'a Pose>,
|
||||||
jumping: &'a Jumping,
|
jumping: &'a Jumping,
|
||||||
|
entity: Entity,
|
||||||
|
physics_query: &'a PhysicsQuery<'world, 'state, 'b>,
|
||||||
|
collidable_entity_query: &'a CollidableEntityQuery<'world, 'state>,
|
||||||
}
|
}
|
||||||
fn handle_relative_friction_and_calculate_movement(
|
fn handle_relative_friction_and_calculate_movement(
|
||||||
HandleRelativeFrictionAndCalculateMovementOpts {
|
HandleRelativeFrictionAndCalculateMovementOpts {
|
||||||
|
@ -376,7 +384,10 @@ fn handle_relative_friction_and_calculate_movement(
|
||||||
on_climbable,
|
on_climbable,
|
||||||
pose,
|
pose,
|
||||||
jumping,
|
jumping,
|
||||||
}: HandleRelativeFrictionAndCalculateMovementOpts<'_>,
|
entity,
|
||||||
|
physics_query,
|
||||||
|
collidable_entity_query,
|
||||||
|
}: HandleRelativeFrictionAndCalculateMovementOpts<'_, '_, '_, '_>,
|
||||||
) -> Vec3 {
|
) -> Vec3 {
|
||||||
move_relative(
|
move_relative(
|
||||||
physics,
|
physics,
|
||||||
|
@ -397,6 +408,9 @@ fn handle_relative_friction_and_calculate_movement(
|
||||||
world,
|
world,
|
||||||
&mut position,
|
&mut position,
|
||||||
physics,
|
physics,
|
||||||
|
Some(entity),
|
||||||
|
physics_query,
|
||||||
|
collidable_entity_query,
|
||||||
)
|
)
|
||||||
.expect("Entity should exist");
|
.expect("Entity should exist");
|
||||||
// let delta_movement = entity.delta;
|
// let delta_movement = entity.delta;
|
||||||
|
|
|
@ -83,6 +83,8 @@ pub fn travel(
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
travel_in_air(
|
travel_in_air(
|
||||||
|
&world,
|
||||||
|
entity,
|
||||||
&mut physics,
|
&mut physics,
|
||||||
&direction,
|
&direction,
|
||||||
position,
|
position,
|
||||||
|
@ -91,7 +93,8 @@ pub fn travel(
|
||||||
on_climbable,
|
on_climbable,
|
||||||
pose,
|
pose,
|
||||||
jumping,
|
jumping,
|
||||||
&world,
|
&physics_query,
|
||||||
|
&collidable_entity_query,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,6 +103,8 @@ pub fn travel(
|
||||||
/// The usual movement when we're not in water or using an elytra.
|
/// The usual movement when we're not in water or using an elytra.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn travel_in_air(
|
fn travel_in_air(
|
||||||
|
world: &Instance,
|
||||||
|
entity: Entity,
|
||||||
physics: &mut Physics,
|
physics: &mut Physics,
|
||||||
direction: &LookDirection,
|
direction: &LookDirection,
|
||||||
position: Mut<Position>,
|
position: Mut<Position>,
|
||||||
|
@ -108,7 +113,8 @@ fn travel_in_air(
|
||||||
on_climbable: &OnClimbable,
|
on_climbable: &OnClimbable,
|
||||||
pose: Option<&Pose>,
|
pose: Option<&Pose>,
|
||||||
jumping: &Jumping,
|
jumping: &Jumping,
|
||||||
world: &Instance,
|
physics_query: &PhysicsQuery,
|
||||||
|
collidable_entity_query: &CollidableEntityQuery,
|
||||||
) {
|
) {
|
||||||
let gravity = get_effective_gravity();
|
let gravity = get_effective_gravity();
|
||||||
|
|
||||||
|
@ -140,6 +146,9 @@ fn travel_in_air(
|
||||||
on_climbable,
|
on_climbable,
|
||||||
pose,
|
pose,
|
||||||
jumping,
|
jumping,
|
||||||
|
entity,
|
||||||
|
physics_query,
|
||||||
|
collidable_entity_query,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -210,6 +219,9 @@ fn travel_in_fluid(
|
||||||
world,
|
world,
|
||||||
&mut position,
|
&mut position,
|
||||||
physics,
|
physics,
|
||||||
|
Some(entity),
|
||||||
|
physics_query,
|
||||||
|
collidable_entity_query,
|
||||||
)
|
)
|
||||||
.expect("Entity should exist");
|
.expect("Entity should exist");
|
||||||
|
|
||||||
|
@ -231,6 +243,9 @@ fn travel_in_fluid(
|
||||||
world,
|
world,
|
||||||
&mut position,
|
&mut position,
|
||||||
physics,
|
physics,
|
||||||
|
Some(entity),
|
||||||
|
physics_query,
|
||||||
|
collidable_entity_query,
|
||||||
)
|
)
|
||||||
.expect("Entity should exist");
|
.expect("Entity should exist");
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue