aboutsummaryrefslogtreecommitdiff
path: root/azalea
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2026-01-06 04:26:29 +0200
committermat <git@matdoes.dev>2026-01-05 17:57:54 -0900
commit9c2c7c3497a74e80d7186fdcd97ce2518520faa6 (patch)
tree3c4984e3a42ecaf4dcc5fa7503d83c734a03477e /azalea
parent28fe2d21dc03b96baa61c3b142baff3af5b92a76 (diff)
downloadazalea-drasl-9c2c7c3497a74e80d7186fdcd97ce2518520faa6.tar.xz
pathfinder fixes and api improvements
don't pathfind on magma, fix mining blocks while swimming, fix RadiusGoal heuristic, and add Client::physics, is_executing_path, and is_calculating_path
Diffstat (limited to 'azalea')
-rw-r--r--azalea/src/entity_ref/shared_impls.rs14
-rw-r--r--azalea/src/pathfinder/goals.rs3
-rw-r--r--azalea/src/pathfinder/mod.rs24
-rw-r--r--azalea/src/pathfinder/moves/basic.rs8
-rw-r--r--azalea/src/pathfinder/world.rs8
5 files changed, 47 insertions, 10 deletions
diff --git a/azalea/src/entity_ref/shared_impls.rs b/azalea/src/entity_ref/shared_impls.rs
index 1dafbde2..9ef396a0 100644
--- a/azalea/src/entity_ref/shared_impls.rs
+++ b/azalea/src/entity_ref/shared_impls.rs
@@ -1,6 +1,6 @@
use azalea_core::position::Vec3;
use azalea_entity::{
- Attributes, Dead, EntityUuid, Position, dimensions::EntityDimensions, metadata::Health,
+ Attributes, Dead, EntityUuid, Physics, Position, dimensions::EntityDimensions, metadata::Health,
};
use azalea_world::{InstanceName, MinecraftEntityId};
use uuid::Uuid;
@@ -191,4 +191,16 @@ impl_entity_functions! {
pub fn exists(&self) -> bool {
self.try_query_self::<Option<&MinecraftEntityId>, _>(|entity_id| entity_id.is_some()).unwrap_or(false)
}
+
+ Client:
+ /// Returns the complete [`Physics`] data for this client, including velocity, bounding box,
+ /// collisions, etc.
+ EntityRef:
+ /// Returns the complete [`Physics`] data for this entity, including velocity, bounding box,
+ /// collisions, etc.
+ ///
+ /// Also see [`Client::physics`].
+ pub fn physics(&self) -> Physics {
+ self.component::<Physics>().clone()
+ }
}
diff --git a/azalea/src/pathfinder/goals.rs b/azalea/src/pathfinder/goals.rs
index 068bcb2e..8ec921c2 100644
--- a/azalea/src/pathfinder/goals.rs
+++ b/azalea/src/pathfinder/goals.rs
@@ -116,7 +116,8 @@ impl Goal for RadiusGoal {
let dx = (self.pos.x - n.x) as f32;
let dy = (self.pos.y - n.y) as f32;
let dz = (self.pos.z - n.z) as f32;
- dx.powi(2) + dy.powi(2) + dz.powi(2)
+
+ xz_heuristic(dx, dz) + y_heuristic(dy)
}
fn success(&self, n: BlockPos) -> bool {
let n = n.center();
diff --git a/azalea/src/pathfinder/mod.rs b/azalea/src/pathfinder/mod.rs
index 905a90fe..fe94e42d 100644
--- a/azalea/src/pathfinder/mod.rs
+++ b/azalea/src/pathfinder/mod.rs
@@ -227,6 +227,16 @@ pub trait PathfinderClientExt {
/// Returns true if the pathfinder has no active goal and isn't calculating
/// a path.
fn is_goto_target_reached(&self) -> bool;
+ /// Whether the pathfinder is currently following a path.
+ ///
+ /// Also see [`Self::is_calculating_path`] and
+ /// [`Self::is_goto_target_reached`].
+ fn is_executing_path(&self) -> bool;
+ /// Whether the pathfinder is currently calculating a path.
+ ///
+ /// Also see [`Self::is_executing_path`] and
+ /// [`Self::is_goto_target_reached`].
+ fn is_calculating_path(&self) -> bool;
}
impl PathfinderClientExt for Client {
@@ -257,6 +267,7 @@ impl PathfinderClientExt for Client {
force: true,
});
}
+
async fn wait_until_goto_target_reached(&self) {
// we do this to make sure the event got handled before we start checking
// is_goto_target_reached
@@ -273,10 +284,15 @@ impl PathfinderClientExt for Client {
}
}
fn is_goto_target_reached(&self) -> bool {
- self.query_self::<Option<&Pathfinder>, _>(|p| {
- p.map(|p| p.goal.is_none() && !p.is_calculating)
- .unwrap_or(true)
- })
+ self.get_component::<Pathfinder>()
+ .is_none_or(|p| p.goal.is_none() && !p.is_calculating)
+ }
+ fn is_executing_path(&self) -> bool {
+ self.get_component::<ExecutingPath>().is_some()
+ }
+ fn is_calculating_path(&self) -> bool {
+ self.get_component::<Pathfinder>()
+ .is_some_and(|p| p.is_calculating)
}
}
diff --git a/azalea/src/pathfinder/moves/basic.rs b/azalea/src/pathfinder/moves/basic.rs
index 128a6daf..b0fea827 100644
--- a/azalea/src/pathfinder/moves/basic.rs
+++ b/azalea/src/pathfinder/moves/basic.rs
@@ -53,6 +53,7 @@ fn forward_move(ctx: &mut PathfinderCtx, pos: RelBlockPos) {
fn execute_forward_move(mut ctx: ExecuteCtx) {
let center = ctx.target.center();
+ ctx.jump_if_in_water();
if ctx.mine_while_at_start(ctx.target.up(1)) {
return;
@@ -62,7 +63,6 @@ fn execute_forward_move(mut ctx: ExecuteCtx) {
}
ctx.look_at(center);
- ctx.jump_if_in_water();
ctx.sprint(SprintDirection::Forward);
}
@@ -135,6 +135,8 @@ fn execute_ascend_move(mut ctx: ExecuteCtx) {
..
} = ctx;
+ ctx.jump_if_in_water();
+
if ctx.mine_while_at_start(start.up(2)) {
return;
}
@@ -149,7 +151,6 @@ fn execute_ascend_move(mut ctx: ExecuteCtx) {
ctx.look_at(target_center);
ctx.walk(WalkDirection::Forward);
- ctx.jump_if_in_water();
// these checks are to make sure we don't fall if our velocity is too high in
// the wrong direction
@@ -461,9 +462,10 @@ fn diagonal_move(ctx: &mut PathfinderCtx, pos: RelBlockPos) {
fn execute_diagonal_move(mut ctx: ExecuteCtx) {
let target_center = ctx.target.center();
+ ctx.jump_if_in_water();
+
ctx.look_at(target_center);
ctx.sprint(SprintDirection::Forward);
- ctx.jump_if_in_water();
}
/// Go directly down, usually by mining.
diff --git a/azalea/src/pathfinder/world.rs b/azalea/src/pathfinder/world.rs
index 956b0226..13d60162 100644
--- a/azalea/src/pathfinder/world.rs
+++ b/azalea/src/pathfinder/world.rs
@@ -623,6 +623,12 @@ pub fn is_block_state_solid(block_state: BlockState) -> bool {
// fast path
return false;
}
+
+ // hazard
+ if block_state == BlockState::from(BlockKind::MagmaBlock) {
+ return false;
+ };
+
if block_state.is_collision_shape_full() {
return true;
}
@@ -692,7 +698,7 @@ mod tests {
let ctx = CachedWorld::new(Arc::new(RwLock::new(world.into())), BlockPos::default());
assert!(!ctx.is_block_pos_passable(BlockPos::new(0, 0, 0)));
- assert!(ctx.is_block_pos_passable(BlockPos::new(0, 1, 0),));
+ assert!(ctx.is_block_pos_passable(BlockPos::new(0, 1, 0)));
}
#[test]