aboutsummaryrefslogtreecommitdiff
path: root/azalea-physics/src/travel.rs
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2025-03-16 13:41:17 -0500
committerGitHub <noreply@github.com>2025-03-16 13:41:17 -0500
commitb0bd992adcff71ee294dd05060e00e652f62a7b2 (patch)
tree0a36d8b37befbc75c8c65cc2c8779c3df66bd87b /azalea-physics/src/travel.rs
parenta95408cbcc05b5bd04a084b0a286b571069206f6 (diff)
downloadazalea-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/travel.rs')
-rw-r--r--azalea-physics/src/travel.rs131
1 files changed, 117 insertions, 14 deletions
diff --git a/azalea-physics/src/travel.rs b/azalea-physics/src/travel.rs
index e6145c18..0ee39f73 100644
--- a/azalea-physics/src/travel.rs
+++ b/azalea-physics/src/travel.rs
@@ -1,5 +1,8 @@
-use azalea_block::{Block, BlockState};
-use azalea_core::{aabb::AABB, position::Vec3};
+use azalea_block::{Block, BlockState, fluid_state::FluidState};
+use azalea_core::{
+ aabb::AABB,
+ position::{BlockPos, Vec3},
+};
use azalea_entity::{
Attributes, InLoadedChunk, Jumping, LocalEntity, LookDirection, OnClimbable, Physics, Pose,
Position, metadata::Sprinting, move_relative,
@@ -9,7 +12,11 @@ use bevy_ecs::prelude::*;
use crate::{
HandleRelativeFrictionAndCalculateMovementOpts,
- collision::{MoverType, move_colliding},
+ collision::{
+ MoverType, Shapes,
+ entity_collisions::{CollidableEntityQuery, PhysicsQuery, get_entity_collisions},
+ move_colliding,
+ },
get_block_pos_below_that_affects_movement, handle_relative_friction_and_calculate_movement,
};
@@ -19,6 +26,7 @@ use crate::{
pub fn travel(
mut query: Query<
(
+ Entity,
&mut Physics,
&mut LookDirection,
&mut Position,
@@ -32,8 +40,11 @@ pub fn travel(
(With<LocalEntity>, With<InLoadedChunk>),
>,
instance_container: Res<InstanceContainer>,
+ physics_query: PhysicsQuery,
+ collidable_entity_query: CollidableEntityQuery,
) {
for (
+ entity,
mut physics,
direction,
position,
@@ -59,13 +70,16 @@ pub fn travel(
// !this.canStandOnFluid(fluidAtBlock)` here but it doesn't matter
// for players
travel_in_fluid(
+ &world,
+ entity,
&mut physics,
&direction,
position,
attributes,
sprinting,
on_climbable,
- &world,
+ &physics_query,
+ &collidable_entity_query,
);
} else {
travel_in_air(
@@ -149,14 +163,18 @@ fn travel_in_air(
}
}
+#[allow(clippy::too_many_arguments)]
fn travel_in_fluid(
+ world: &Instance,
+ entity: Entity,
physics: &mut Physics,
direction: &LookDirection,
mut position: Mut<Position>,
attributes: &Attributes,
sprinting: Sprinting,
on_climbable: &OnClimbable,
- world: &Instance,
+ physics_query: &PhysicsQuery,
+ collidable_entity_query: &CollidableEntityQuery,
) {
let moving_down = physics.velocity.y <= 0.;
let y = position.y;
@@ -239,11 +257,13 @@ fn travel_in_fluid(
let velocity = physics.velocity;
if physics.horizontal_collision
&& is_free(
- physics.bounding_box,
world,
- velocity.x,
- velocity.y + 0.6 - position.y + y,
- velocity.z,
+ entity,
+ physics_query,
+ collidable_entity_query,
+ physics,
+ physics.bounding_box,
+ velocity.up(0.6).down(position.y).up(y),
)
{
physics.velocity.y = 0.3;
@@ -276,14 +296,97 @@ fn get_fluid_falling_adjusted_movement(
}
}
-fn is_free(bounding_box: AABB, world: &Instance, x: f64, y: f64, z: f64) -> bool {
- // let bounding_box = bounding_box.move_relative(Vec3::new(x, y, z));
+fn is_free(
+ world: &Instance,
+ source_entity: Entity,
+ physics_query: &PhysicsQuery,
+ collidable_entity_query: &CollidableEntityQuery,
+ entity_physics: &mut Physics,
+ bounding_box: AABB,
+ delta: Vec3,
+) -> bool {
+ let bounding_box = bounding_box.move_relative(delta);
+
+ no_collision(
+ world,
+ Some(source_entity),
+ physics_query,
+ collidable_entity_query,
+ entity_physics,
+ &bounding_box,
+ false,
+ ) && !contains_any_liquid(world, bounding_box)
+}
- let _ = (bounding_box, world, x, y, z);
+fn no_collision(
+ world: &Instance,
+ source_entity: Option<Entity>,
+ physics_query: &PhysicsQuery,
+ collidable_entity_query: &CollidableEntityQuery,
+ entity_physics: &mut Physics,
+ aabb: &AABB,
+ include_liquid_collisions: bool,
+) -> bool {
+ let collisions = if include_liquid_collisions {
+ crate::collision::world_collisions::get_block_and_liquid_collisions(world, aabb)
+ } else {
+ crate::collision::world_collisions::get_block_collisions(world, aabb)
+ };
- // TODO: implement this, see Entity.isFree
+ for collision in collisions {
+ if !collision.is_empty() {
+ return false;
+ }
+ }
+
+ if !get_entity_collisions(
+ world,
+ aabb,
+ source_entity,
+ physics_query,
+ collidable_entity_query,
+ )
+ .is_empty()
+ {
+ false
+ } else if source_entity.is_none() {
+ true
+ } else {
+ let collision = border_collision(entity_physics, aabb);
+ if let Some(collision) = collision {
+ // !Shapes.joinIsNotEmpty(collision, Shapes.create(aabb), BooleanOp.AND);
+ !Shapes::matches_anywhere(&collision.into(), &aabb.into(), |a, b| a && b)
+ } else {
+ true
+ }
+ }
+}
+
+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 {
+ let min = bounding_box.min.to_block_pos_floor();
+ let max = bounding_box.max.to_block_pos_ceil();
+
+ for x in min.x..max.x {
+ for y in min.y..max.y {
+ for z in min.z..max.z {
+ let block_state = world
+ .chunks
+ .get_block_state(&BlockPos::new(x, y, z))
+ .unwrap_or_default();
+ if !FluidState::from(block_state).is_empty() {
+ return true;
+ }
+ }
+ }
+ }
- true
+ false
}
fn get_effective_gravity() -> f64 {