diff options
| author | mat <git@matdoes.dev> | 2026-01-06 04:26:29 +0200 |
|---|---|---|
| committer | mat <git@matdoes.dev> | 2026-01-05 17:57:54 -0900 |
| commit | 9c2c7c3497a74e80d7186fdcd97ce2518520faa6 (patch) | |
| tree | 3c4984e3a42ecaf4dcc5fa7503d83c734a03477e /azalea | |
| parent | 28fe2d21dc03b96baa61c3b142baff3af5b92a76 (diff) | |
| download | azalea-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.rs | 14 | ||||
| -rw-r--r-- | azalea/src/pathfinder/goals.rs | 3 | ||||
| -rw-r--r-- | azalea/src/pathfinder/mod.rs | 24 | ||||
| -rw-r--r-- | azalea/src/pathfinder/moves/basic.rs | 8 | ||||
| -rw-r--r-- | azalea/src/pathfinder/world.rs | 8 |
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] |
