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:
parent
074bb61983
commit
dbf7776656
2 changed files with 78 additions and 55 deletions
|
@ -82,7 +82,11 @@ fn bench_pathfinder(c: &mut Criterion) {
|
||||||
let ctx = PathfinderCtx::new(Arc::new(RwLock::new(world.into())));
|
let ctx = PathfinderCtx::new(Arc::new(RwLock::new(world.into())));
|
||||||
let goal = BlockPosGoal(end);
|
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(
|
let astar::Path { movements, partial } = a_star(
|
||||||
start,
|
start,
|
||||||
|
|
|
@ -14,7 +14,7 @@ use azalea_block::BlockState;
|
||||||
use azalea_client::{StartSprintEvent, StartWalkEvent};
|
use azalea_client::{StartSprintEvent, StartWalkEvent};
|
||||||
use azalea_core::{
|
use azalea_core::{
|
||||||
bitset::FixedBitSet,
|
bitset::FixedBitSet,
|
||||||
position::{BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos, ChunkSectionPos, Vec3},
|
position::{BlockPos, ChunkPos, ChunkSectionBlockPos, ChunkSectionPos, Vec3},
|
||||||
};
|
};
|
||||||
use azalea_physics::collision::BlockWithShape;
|
use azalea_physics::collision::BlockWithShape;
|
||||||
use azalea_world::Instance;
|
use azalea_world::Instance;
|
||||||
|
@ -74,8 +74,12 @@ impl PathfinderCtx {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_block_state(&self, pos: BlockPos) -> Option<BlockState> {
|
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_pos = ChunkPos::from(pos);
|
||||||
let chunk_block_pos = ChunkBlockPos::from(pos);
|
|
||||||
|
|
||||||
let mut cached_chunks = self.cached_chunks.borrow_mut();
|
let mut cached_chunks = self.cached_chunks.borrow_mut();
|
||||||
if let Some(sections) = cached_chunks.iter().find_map(|(pos, sections)| {
|
if let Some(sections) = cached_chunks.iter().find_map(|(pos, sections)| {
|
||||||
|
@ -85,11 +89,15 @@ impl PathfinderCtx {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
return azalea_world::chunk_storage::get_block_state_from_sections(
|
let section_index =
|
||||||
sections,
|
azalea_world::chunk_storage::section_index(pos.y, self.min_y) as usize;
|
||||||
&chunk_block_pos,
|
if section_index >= sections.len() {
|
||||||
self.min_y,
|
// y position is out of bounds
|
||||||
);
|
return None;
|
||||||
|
};
|
||||||
|
let section = §ions[section_index];
|
||||||
|
let chunk_section_pos = ChunkSectionBlockPos::from(pos);
|
||||||
|
return Some(section.get(chunk_section_pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
let world = self.world_lock.read();
|
let world = self.world_lock.read();
|
||||||
|
@ -98,38 +106,14 @@ impl PathfinderCtx {
|
||||||
|
|
||||||
cached_chunks.push((chunk_pos, chunk.sections.clone()));
|
cached_chunks.push((chunk_pos, chunk.sections.clone()));
|
||||||
|
|
||||||
azalea_world::chunk_storage::get_block_state_from_sections(
|
let section_index = azalea_world::chunk_storage::section_index(pos.y, self.min_y) as usize;
|
||||||
&chunk.sections,
|
if section_index >= chunk.sections.len() {
|
||||||
&chunk_block_pos,
|
// y position is out of bounds
|
||||||
self.min_y,
|
return None;
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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;
|
|
||||||
};
|
};
|
||||||
if block.is_air() {
|
let section = &chunk.sections[section_index];
|
||||||
// fast path
|
let chunk_section_pos = ChunkSectionBlockPos::from(pos);
|
||||||
return true;
|
Some(section.get(chunk_section_pos))
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_block_passable(&self, pos: BlockPos) -> bool {
|
pub fn is_block_passable(&self, pos: BlockPos) -> bool {
|
||||||
|
@ -148,7 +132,11 @@ impl PathfinderCtx {
|
||||||
if cached.present.index(index) {
|
if cached.present.index(index) {
|
||||||
return cached.value.index(index);
|
return cached.value.index(index);
|
||||||
} else {
|
} 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);
|
cached.present.set(index);
|
||||||
if passable {
|
if passable {
|
||||||
cached.value.set(index);
|
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 present_bitset = FixedBitSet::new();
|
||||||
let mut value_bitset = FixedBitSet::new();
|
let mut value_bitset = FixedBitSet::new();
|
||||||
|
|
||||||
present_bitset.set(index);
|
present_bitset.set(index);
|
||||||
if passable {
|
if passable {
|
||||||
value_bitset.set(index);
|
value_bitset.set(index);
|
||||||
|
@ -173,18 +165,6 @@ impl PathfinderCtx {
|
||||||
passable
|
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 {
|
pub fn is_block_solid(&self, pos: BlockPos) -> bool {
|
||||||
let (section_pos, section_block_pos) =
|
let (section_pos, section_block_pos) =
|
||||||
(ChunkSectionPos::from(pos), ChunkSectionBlockPos::from(pos));
|
(ChunkSectionPos::from(pos), ChunkSectionBlockPos::from(pos));
|
||||||
|
@ -201,7 +181,10 @@ impl PathfinderCtx {
|
||||||
if cached.present.index(index) {
|
if cached.present.index(index) {
|
||||||
return cached.value.index(index);
|
return cached.value.index(index);
|
||||||
} else {
|
} 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);
|
cached.present.set(index);
|
||||||
if solid {
|
if solid {
|
||||||
cached.value.set(index);
|
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 present_bitset = FixedBitSet::new();
|
||||||
let mut value_bitset = FixedBitSet::new();
|
let mut value_bitset = FixedBitSet::new();
|
||||||
present_bitset.set(index);
|
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 struct ExecuteCtx<'w1, 'w2, 'w3, 'w4, 'a> {
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
/// The node that we're trying to reach.
|
/// The node that we're trying to reach.
|
||||||
|
|
Loading…
Add table
Reference in a new issue