diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2023-12-15 11:26:40 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-12-15 11:26:40 -0600 |
| commit | a707e2eb82b74994a16083b31fa4576332cf1995 (patch) | |
| tree | db6c2ac94dd73590befd68a9b1b0ef960410b0df /azalea/src/pathfinder/goals.rs | |
| parent | 59e140ddd655c7dc6e35109b91286118c51bcc06 (diff) | |
| download | azalea-drasl-a707e2eb82b74994a16083b31fa4576332cf1995.tar.xz | |
Add mining to the pathfinder (#122)
* basic pathfinder mining poc
* mining descending and autotool
* pathfinder mining descending
* pathfinder fixes
* allow disabling pathfinder miner and other fixes
* small optimization to avoid chunk vec iter lookup sometimes
* seeded rng in pathfinder bench
* consistently use f32::INFINITY
this brings performance much closer to how it was before
* astar heuristic optimization from baritone
* add downward_move
* fix downward move execute
* avoid liquids and falling blocks when mining
* fix COST_HEURISTIC
* fix to not path through flowing liquids
* only reset pathfinder timeout while mining if the block is close enough
* cache mining costs of block positions
* fix mine_while_at_start and move PathfinderDebugParticles to its own module
* add ReachBlockPosGoal
in other news: azalea's sin/cos functions were broken this whole time and i never noticed
* clippy and add things that i accidentally didn't commit
* improve wording on doc for azalea::pathfinder
Diffstat (limited to 'azalea/src/pathfinder/goals.rs')
| -rw-r--r-- | azalea/src/pathfinder/goals.rs | 96 |
1 files changed, 91 insertions, 5 deletions
diff --git a/azalea/src/pathfinder/goals.rs b/azalea/src/pathfinder/goals.rs index 9c01d486..3f8c7993 100644 --- a/azalea/src/pathfinder/goals.rs +++ b/azalea/src/pathfinder/goals.rs @@ -1,12 +1,21 @@ +//! The goals that a pathfinder can try to reach. + use std::f32::consts::SQRT_2; use azalea_core::position::{BlockPos, Vec3}; +use azalea_world::ChunkStorage; + +use super::costs::{COST_HEURISTIC, FALL_N_BLOCKS_COST, JUMP_ONE_BLOCK_COST}; -use super::{ - costs::{FALL_N_BLOCKS_COST, JUMP_ONE_BLOCK_COST}, - Goal, -}; +pub trait Goal { + #[must_use] + fn heuristic(&self, n: BlockPos) -> f32; + #[must_use] + fn success(&self, n: BlockPos) -> bool; +} +/// Move to the given block position. +#[derive(Debug)] pub struct BlockPosGoal(pub BlockPos); impl Goal for BlockPosGoal { fn heuristic(&self, n: BlockPos) -> f32 { @@ -36,9 +45,11 @@ fn xz_heuristic(dx: f32, dz: f32) -> f32 { diagonal = z; } - diagonal * SQRT_2 + straight + (diagonal * SQRT_2 + straight) * COST_HEURISTIC } +/// Move to the given block position, ignoring the y axis. +#[derive(Debug)] pub struct XZGoal { pub x: i32, pub z: i32, @@ -62,6 +73,8 @@ fn y_heuristic(dy: f32) -> f32 { } } +/// Move to the given y coordinate. +#[derive(Debug)] pub struct YGoal { pub y: i32, } @@ -75,6 +88,8 @@ impl Goal for YGoal { } } +/// Get within the given radius of the given position. +#[derive(Debug)] pub struct RadiusGoal { pub pos: Vec3, pub radius: f32, @@ -96,6 +111,8 @@ impl Goal for RadiusGoal { } } +/// Do the opposite of the given goal. +#[derive(Debug)] pub struct InverseGoal<T: Goal>(pub T); impl<T: Goal> Goal for InverseGoal<T> { fn heuristic(&self, n: BlockPos) -> f32 { @@ -106,6 +123,8 @@ impl<T: Goal> Goal for InverseGoal<T> { } } +/// Do either of the given goals, whichever is closer. +#[derive(Debug)] pub struct OrGoal<T: Goal, U: Goal>(pub T, pub U); impl<T: Goal, U: Goal> Goal for OrGoal<T, U> { fn heuristic(&self, n: BlockPos) -> f32 { @@ -116,6 +135,24 @@ impl<T: Goal, U: Goal> Goal for OrGoal<T, U> { } } +/// Do any of the given goals, whichever is closest. +#[derive(Debug)] +pub struct OrGoals<T: Goal>(pub Vec<T>); +impl<T: Goal> Goal for OrGoals<T> { + fn heuristic(&self, n: BlockPos) -> f32 { + self.0 + .iter() + .map(|goal| goal.heuristic(n)) + .min_by(|a, b| a.partial_cmp(b).unwrap()) + .unwrap_or(f32::INFINITY) + } + fn success(&self, n: BlockPos) -> bool { + self.0.iter().any(|goal| goal.success(n)) + } +} + +/// Try to reach both of the given goals. +#[derive(Debug)] pub struct AndGoal<T: Goal, U: Goal>(pub T, pub U); impl<T: Goal, U: Goal> Goal for AndGoal<T, U> { fn heuristic(&self, n: BlockPos) -> f32 { @@ -125,3 +162,52 @@ impl<T: Goal, U: Goal> Goal for AndGoal<T, U> { self.0.success(n) && self.1.success(n) } } + +/// Try to reach all of the given goals. +#[derive(Debug)] +pub struct AndGoals<T: Goal>(pub Vec<T>); +impl<T: Goal> Goal for AndGoals<T> { + fn heuristic(&self, n: BlockPos) -> f32 { + self.0 + .iter() + .map(|goal| goal.heuristic(n)) + .max_by(|a, b| a.partial_cmp(b).unwrap()) + .unwrap_or(f32::INFINITY) + } + fn success(&self, n: BlockPos) -> bool { + self.0.iter().all(|goal| goal.success(n)) + } +} + +/// Move to a position where we can reach the given block. +#[derive(Debug)] +pub struct ReachBlockPosGoal { + pub pos: BlockPos, + pub chunk_storage: ChunkStorage, +} +impl Goal for ReachBlockPosGoal { + fn heuristic(&self, n: BlockPos) -> f32 { + BlockPosGoal(self.pos).heuristic(n) + } + fn success(&self, n: BlockPos) -> bool { + // only do the expensive check if we're close enough + let max_pick_range = 6; + let actual_pick_range = 4.5; + + let distance = (self.pos - n).length_sqr(); + if distance > max_pick_range * max_pick_range { + return false; + } + + let eye_position = n.to_vec3_floored() + Vec3::new(0.5, 1.62, 0.5); + let look_direction = crate::direction_looking_at(&eye_position, &self.pos.center()); + let block_hit_result = azalea_client::interact::pick( + &look_direction, + &eye_position, + &self.chunk_storage, + actual_pick_range, + ); + + block_hit_result.block_pos == self.pos + } +} |
