aboutsummaryrefslogtreecommitdiff
path: root/azalea-world/src/world.rs
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2023-12-15 11:26:40 -0600
committerGitHub <noreply@github.com>2023-12-15 11:26:40 -0600
commita707e2eb82b74994a16083b31fa4576332cf1995 (patch)
treedb6c2ac94dd73590befd68a9b1b0ef960410b0df /azalea-world/src/world.rs
parent59e140ddd655c7dc6e35109b91286118c51bcc06 (diff)
downloadazalea-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-world/src/world.rs')
-rw-r--r--azalea-world/src/world.rs144
1 files changed, 2 insertions, 142 deletions
diff --git a/azalea-world/src/world.rs b/azalea-world/src/world.rs
index 7b6854f7..84a5857c 100644
--- a/azalea-world/src/world.rs
+++ b/azalea-world/src/world.rs
@@ -1,5 +1,5 @@
-use crate::{iterators::ChunkIterator, palette::Palette, ChunkStorage, PartialChunkStorage};
-use azalea_block::{BlockState, BlockStates, FluidState};
+use crate::{ChunkStorage, PartialChunkStorage};
+use azalea_block::{BlockState, FluidState};
use azalea_core::position::{BlockPos, ChunkPos};
use azalea_core::registry_holder::RegistryHolder;
use bevy_ecs::{component::Component, entity::Entity};
@@ -104,110 +104,6 @@ impl Instance {
pub fn set_block_state(&self, pos: &BlockPos, state: BlockState) -> Option<BlockState> {
self.chunks.set_block_state(pos, state)
}
-
- /// Find the coordinates of a block in the world.
- ///
- /// Note that this is sorted by `x+y+z` and not `x^2+y^2+z^2` for
- /// optimization purposes.
- ///
- /// ```
- /// # fn example(client: &azalea_client::Client) {
- /// client.world().read().find_block(client.position(), &azalea_registry::Block::Chest.into());
- /// # }
- /// ```
- pub fn find_block(
- &self,
- nearest_to: impl Into<BlockPos>,
- block_states: &BlockStates,
- ) -> Option<BlockPos> {
- // iterate over every chunk in a 3d spiral pattern
- // and then check the palette for the block state
-
- let nearest_to: BlockPos = nearest_to.into();
- let start_chunk: ChunkPos = (&nearest_to).into();
- let mut iter = ChunkIterator::new(start_chunk, 32);
-
- let mut nearest_found_pos: Option<BlockPos> = None;
- let mut nearest_found_distance = 0;
-
- // we do `while` instead of `for` so we can access iter later
- while let Some(chunk_pos) = iter.next() {
- let Some(chunk) = self.chunks.get(&chunk_pos) else {
- // if the chunk isn't loaded then we skip it.
- // we don't just return since it *could* cause issues if there's a random
- // unloaded chunk and then more that are loaded.
- // unlikely but still something to consider, and it's not like this slows it
- // down much anyways.
- continue;
- };
-
- for (section_index, section) in chunk.read().sections.iter().enumerate() {
- let maybe_has_block = match &section.states.palette {
- Palette::SingleValue(id) => block_states.contains(&BlockState { id: *id }),
- Palette::Linear(ids) => ids
- .iter()
- .any(|&id| block_states.contains(&BlockState { id })),
- Palette::Hashmap(ids) => ids
- .iter()
- .any(|&id| block_states.contains(&BlockState { id })),
- Palette::Global => true,
- };
- if !maybe_has_block {
- continue;
- }
-
- for i in 0..4096 {
- let block_state = section.states.get_at_index(i);
- let block_state = BlockState { id: block_state };
-
- if block_states.contains(&block_state) {
- let (section_x, section_y, section_z) = section.states.coords_from_index(i);
- let (x, y, z) = (
- chunk_pos.x * 16 + (section_x as i32),
- self.chunks.min_y + (section_index * 16) as i32 + section_y as i32,
- chunk_pos.z * 16 + (section_z as i32),
- );
- let this_block_pos = BlockPos { x, y, z };
- let this_block_distance = (nearest_to - this_block_pos).length_manhattan();
- // only update if it's closer
- if nearest_found_pos.is_none()
- || this_block_distance < nearest_found_distance
- {
- nearest_found_pos = Some(this_block_pos);
- nearest_found_distance = this_block_distance;
- }
- }
- }
- }
-
- if let Some(nearest_found_pos) = nearest_found_pos {
- // this is required because find_block searches chunk-by-chunk, which can cause
- // us to find blocks first that aren't actually the closest
- let required_chunk_distance = u32::max(
- u32::max(
- (chunk_pos.x - start_chunk.x).unsigned_abs(),
- (chunk_pos.z - start_chunk.z).unsigned_abs(),
- ),
- (nearest_to.y - nearest_found_pos.y)
- .unsigned_abs()
- .div_ceil(16),
- );
- let nearest_chunk_distance = iter.layer;
-
- // if we found the position and there's no chance there's something closer,
- // return it
- if nearest_chunk_distance >= required_chunk_distance {
- return Some(nearest_found_pos);
- }
- }
- }
-
- if nearest_found_pos.is_some() {
- nearest_found_pos
- } else {
- None
- }
- }
}
impl Debug for PartialInstance {
@@ -244,39 +140,3 @@ impl From<ChunkStorage> for Instance {
}
}
}
-
-#[cfg(test)]
-mod tests {
- use azalea_registry::Block;
-
- use crate::Chunk;
-
- use super::*;
-
- #[test]
- fn find_block() {
- let mut instance = Instance::default();
-
- let chunk_storage = &mut instance.chunks;
- let mut partial_chunk_storage = PartialChunkStorage::default();
-
- // block at (17, 0, 0) and (0, 18, 0)
-
- partial_chunk_storage.set(
- &ChunkPos { x: 0, z: 0 },
- Some(Chunk::default()),
- chunk_storage,
- );
- partial_chunk_storage.set(
- &ChunkPos { x: 1, z: 0 },
- Some(Chunk::default()),
- chunk_storage,
- );
-
- chunk_storage.set_block_state(&BlockPos { x: 17, y: 0, z: 0 }, Block::Stone.into());
- chunk_storage.set_block_state(&BlockPos { x: 0, y: 18, z: 0 }, Block::Stone.into());
-
- let pos = instance.find_block(BlockPos { x: 0, y: 0, z: 0 }, &Block::Stone.into());
- assert_eq!(pos, Some(BlockPos { x: 17, y: 0, z: 0 }));
- }
-}