1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

simplify part of pathfinder

This commit is contained in:
mat 2023-10-05 00:15:32 -05:00
parent 074bb61983
commit dbf7776656
2 changed files with 78 additions and 55 deletions

View file

@ -82,7 +82,11 @@ fn bench_pathfinder(c: &mut Criterion) {
let ctx = PathfinderCtx::new(Arc::new(RwLock::new(world.into())));
let goal = BlockPosGoal(end);
let successors = |pos: BlockPos| successors_fn(&ctx, pos);
let successors = |pos: BlockPos| {
let mut edges = Vec::with_capacity(16);
successors_fn(&mut edges, &ctx, pos);
edges
};
let astar::Path { movements, partial } = a_star(
start,

View file

@ -14,7 +14,7 @@ use azalea_block::BlockState;
use azalea_client::{StartSprintEvent, StartWalkEvent};
use azalea_core::{
bitset::FixedBitSet,
position::{BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos, ChunkSectionPos, Vec3},
position::{BlockPos, ChunkPos, ChunkSectionBlockPos, ChunkSectionPos, Vec3},
};
use azalea_physics::collision::BlockWithShape;
use azalea_world::Instance;
@ -74,8 +74,12 @@ impl PathfinderCtx {
}
fn get_block_state(&self, pos: BlockPos) -> Option<BlockState> {
if pos.y < self.min_y {
// y position is out of bounds
return None;
}
let chunk_pos = ChunkPos::from(pos);
let chunk_block_pos = ChunkBlockPos::from(pos);
let mut cached_chunks = self.cached_chunks.borrow_mut();
if let Some(sections) = cached_chunks.iter().find_map(|(pos, sections)| {
@ -85,11 +89,15 @@ impl PathfinderCtx {
None
}
}) {
return azalea_world::chunk_storage::get_block_state_from_sections(
sections,
&chunk_block_pos,
self.min_y,
);
let section_index =
azalea_world::chunk_storage::section_index(pos.y, self.min_y) as usize;
if section_index >= sections.len() {
// y position is out of bounds
return None;
};
let section = &sections[section_index];
let chunk_section_pos = ChunkSectionBlockPos::from(pos);
return Some(section.get(chunk_section_pos));
}
let world = self.world_lock.read();
@ -98,38 +106,14 @@ impl PathfinderCtx {
cached_chunks.push((chunk_pos, chunk.sections.clone()));
azalea_world::chunk_storage::get_block_state_from_sections(
&chunk.sections,
&chunk_block_pos,
self.min_y,
)
}
/// whether this block is passable
fn uncached_is_block_passable(&self, pos: BlockPos) -> bool {
let Some(block) = self.get_block_state(pos) else {
return false;
let section_index = azalea_world::chunk_storage::section_index(pos.y, self.min_y) as usize;
if section_index >= chunk.sections.len() {
// y position is out of bounds
return None;
};
if block.is_air() {
// fast path
return true;
}
if !block.is_shape_empty() {
return false;
}
if block == azalea_registry::Block::Water.into() {
return false;
}
if block.waterlogged() {
return false;
}
// block.waterlogged currently doesn't account for seagrass and some other water
// blocks
if block == azalea_registry::Block::Seagrass.into() {
return false;
}
true
let section = &chunk.sections[section_index];
let chunk_section_pos = ChunkSectionBlockPos::from(pos);
Some(section.get(chunk_section_pos))
}
pub fn is_block_passable(&self, pos: BlockPos) -> bool {
@ -148,7 +132,11 @@ impl PathfinderCtx {
if cached.present.index(index) {
return cached.value.index(index);
} else {
let passable = self.uncached_is_block_passable(pos);
let Some(block) = self.get_block_state(pos) else {
return false;
};
let passable = is_block_state_passable(block);
cached.present.set(index);
if passable {
cached.value.set(index);
@ -157,9 +145,13 @@ impl PathfinderCtx {
}
}
let passable = self.uncached_is_block_passable(pos);
let Some(block) = self.get_block_state(pos) else {
return false;
};
let passable = is_block_state_passable(block);
let mut present_bitset = FixedBitSet::new();
let mut value_bitset = FixedBitSet::new();
present_bitset.set(index);
if passable {
value_bitset.set(index);
@ -173,18 +165,6 @@ impl PathfinderCtx {
passable
}
/// whether this block has a solid hitbox (i.e. we can stand on it)
fn uncached_is_block_solid(&self, pos: BlockPos) -> bool {
let Some(block) = self.get_block_state(pos) else {
return false;
};
if block.is_air() {
// fast path
return false;
}
block.is_shape_full()
}
pub fn is_block_solid(&self, pos: BlockPos) -> bool {
let (section_pos, section_block_pos) =
(ChunkSectionPos::from(pos), ChunkSectionBlockPos::from(pos));
@ -201,7 +181,10 @@ impl PathfinderCtx {
if cached.present.index(index) {
return cached.value.index(index);
} else {
let solid = self.uncached_is_block_solid(pos);
let Some(block) = self.get_block_state(pos) else {
return false;
};
let solid = is_block_state_solid(block);
cached.present.set(index);
if solid {
cached.value.set(index);
@ -210,7 +193,10 @@ impl PathfinderCtx {
}
}
let solid = self.uncached_is_block_solid(pos);
let Some(block) = self.get_block_state(pos) else {
return false;
};
let solid = is_block_state_solid(block);
let mut present_bitset = FixedBitSet::new();
let mut value_bitset = FixedBitSet::new();
present_bitset.set(index);
@ -254,6 +240,39 @@ impl PathfinderCtx {
}
}
/// whether this block is passable
fn is_block_state_passable(block: BlockState) -> bool {
if block.is_air() {
// fast path
return true;
}
if !block.is_shape_empty() {
return false;
}
if block == azalea_registry::Block::Water.into() {
return false;
}
if block.waterlogged() {
return false;
}
// block.waterlogged currently doesn't account for seagrass and some other water
// blocks
if block == azalea_registry::Block::Seagrass.into() {
return false;
}
true
}
/// whether this block has a solid hitbox (i.e. we can stand on it)
fn is_block_state_solid(block: BlockState) -> bool {
if block.is_air() {
// fast path
return false;
}
block.is_shape_full()
}
pub struct ExecuteCtx<'w1, 'w2, 'w3, 'w4, 'a> {
pub entity: Entity,
/// The node that we're trying to reach.