diff options
| author | mat <git@matdoes.dev> | 2025-06-02 06:55:38 -1030 |
|---|---|---|
| committer | mat <git@matdoes.dev> | 2025-06-02 06:55:38 -1030 |
| commit | 2c5f293210a09c99577a6999afd52357c898eaeb (patch) | |
| tree | 6611f914ba33dd3a9f8e9abe2e6221a0e280ca95 /azalea-world/src | |
| parent | 5adf67fe04f1f95ec7b6ac7008874e16ed3bf41b (diff) | |
| download | azalea-drasl-2c5f293210a09c99577a6999afd52357c898eaeb.tar.xz | |
add Event::ReceiveChunk and find_blocks_in_chunk function
Diffstat (limited to 'azalea-world/src')
| -rw-r--r-- | azalea-world/src/find_blocks.rs | 141 |
1 files changed, 73 insertions, 68 deletions
diff --git a/azalea-world/src/find_blocks.rs b/azalea-world/src/find_blocks.rs index b266d799..10068243 100644 --- a/azalea-world/src/find_blocks.rs +++ b/azalea-world/src/find_blocks.rs @@ -1,16 +1,7 @@ use azalea_block::{BlockState, BlockStates}; use azalea_core::position::{BlockPos, ChunkPos}; -use crate::{ChunkStorage, Instance, iterators::ChunkIterator, palette::Palette}; - -fn palette_maybe_has_block(palette: &Palette<BlockState>, block_states: &BlockStates) -> bool { - match &palette { - Palette::SingleValue(id) => block_states.contains(id), - Palette::Linear(ids) => ids.iter().any(|id| block_states.contains(id)), - Palette::Hashmap(ids) => ids.iter().any(|id| block_states.contains(id)), - Palette::Global => true, - } -} +use crate::{Chunk, ChunkStorage, Instance, iterators::ChunkIterator, palette::Palette}; impl Instance { /// Find the coordinates of a block in the world. @@ -52,35 +43,20 @@ impl Instance { continue; }; - for (section_index, section) in chunk.read().sections.iter().enumerate() { - let maybe_has_block = - palette_maybe_has_block(§ion.states.palette, block_states); - if !maybe_has_block { - continue; - } - - for i in 0..4096 { - let block_state = section.states.get_at_index(i); - - if block_states.contains(&block_state) { - let section_pos = section.states.coords_from_index(i); - let (x, y, z) = ( - chunk_pos.x * 16 + (section_pos.x as i32), - self.chunks.min_y + (section_index * 16) as i32 + section_pos.y as i32, - chunk_pos.z * 16 + (section_pos.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; - } + find_blocks_in_chunk( + block_states, + chunk_pos, + &chunk.read(), + self.chunks.min_y, + |this_block_pos| { + 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 @@ -179,38 +155,22 @@ impl Iterator for FindBlocks<'_> { continue; }; - for (section_index, section) in chunk.read().sections.iter().enumerate() { - let maybe_has_block = - palette_maybe_has_block(§ion.states.palette, self.block_states); - if !maybe_has_block { - continue; - } + find_blocks_in_chunk( + self.block_states, + chunk_pos, + &chunk.read(), + self.chunks.min_y, + |this_block_pos| { + let this_block_distance = (self.nearest_to - this_block_pos).length_manhattan(); - for i in 0..4096 { - let block_state = section.states.get_at_index(i); - - if self.block_states.contains(&block_state) { - let section_pos = section.states.coords_from_index(i); - let (x, y, z) = ( - chunk_pos.x * 16 + (section_pos.x as i32), - self.chunks.min_y + (section_index * 16) as i32 + section_pos.y as i32, - chunk_pos.z * 16 + (section_pos.z as i32), - ); - let this_block_pos = BlockPos { x, y, z }; - let this_block_distance = - (self.nearest_to - this_block_pos).length_manhattan(); - - found.push((this_block_pos, this_block_distance)); - - 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; - } + found.push((this_block_pos, this_block_distance)); + + 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 @@ -242,6 +202,51 @@ impl Iterator for FindBlocks<'_> { } } +/// An optimized function for finding the block positions in a chunk that match +/// the given block states. +/// +/// This is used internally by [`Instance::find_block`] and +/// [`Instance::find_blocks`]. +pub fn find_blocks_in_chunk( + block_states: &BlockStates, + chunk_pos: ChunkPos, + chunk: &Chunk, + min_y: i32, + mut cb: impl FnMut(BlockPos), +) { + for (section_index, section) in chunk.sections.iter().enumerate() { + let maybe_has_block = palette_maybe_has_block(§ion.states.palette, block_states); + if !maybe_has_block { + continue; + } + + for i in 0..4096 { + let block_state = section.states.get_at_index(i); + + if block_states.contains(&block_state) { + let section_pos = section.states.coords_from_index(i); + let (x, y, z) = ( + chunk_pos.x * 16 + (section_pos.x as i32), + min_y + (section_index * 16) as i32 + section_pos.y as i32, + chunk_pos.z * 16 + (section_pos.z as i32), + ); + let this_block_pos = BlockPos { x, y, z }; + + cb(this_block_pos); + } + } + } +} + +fn palette_maybe_has_block(palette: &Palette<BlockState>, block_states: &BlockStates) -> bool { + match &palette { + Palette::SingleValue(id) => block_states.contains(id), + Palette::Linear(ids) => ids.iter().any(|id| block_states.contains(id)), + Palette::Hashmap(ids) => ids.iter().any(|id| block_states.contains(id)), + Palette::Global => true, + } +} + #[cfg(test)] mod tests { use azalea_registry::Block; |
