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

fix world being locked while pathfinding

This commit is contained in:
mat 2023-10-03 22:08:18 -05:00
parent 9c6459a73b
commit bffa28e706
4 changed files with 31 additions and 24 deletions

View file

@ -1,4 +1,4 @@
use std::{hint::black_box, time::Duration}; use std::{hint::black_box, sync::Arc, time::Duration};
use azalea::{ use azalea::{
pathfinder::{ pathfinder::{
@ -12,6 +12,7 @@ use azalea::{
use azalea_core::position::{ChunkBlockPos, ChunkPos}; use azalea_core::position::{ChunkBlockPos, ChunkPos};
use azalea_world::{Chunk, ChunkStorage, PartialChunkStorage}; use azalea_world::{Chunk, ChunkStorage, PartialChunkStorage};
use criterion::{criterion_group, criterion_main, Criterion}; use criterion::{criterion_group, criterion_main, Criterion};
use parking_lot::RwLock;
use rand::Rng; use rand::Rng;
fn generate_bedrock_world( fn generate_bedrock_world(
@ -78,7 +79,7 @@ fn bench_pathfinder(c: &mut Criterion) {
b.iter(|| { b.iter(|| {
let (world, start, end) = generate_bedrock_world(&mut partial_chunks, 4); let (world, start, end) = generate_bedrock_world(&mut partial_chunks, 4);
let ctx = PathfinderCtx::new(&world); 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| successors_fn(&ctx, pos);

View file

@ -178,8 +178,7 @@ fn goto_listener(
let task = thread_pool.spawn(async move { let task = thread_pool.spawn(async move {
debug!("start: {start:?}"); debug!("start: {start:?}");
let world = &world_lock.read().chunks; let ctx = PathfinderCtx::new(world_lock);
let ctx = PathfinderCtx::new(world);
let successors = |pos: BlockPos| successors_fn(&ctx, pos); let successors = |pos: BlockPos| successors_fn(&ctx, pos);
let mut attempt_number = 0; let mut attempt_number = 0;
@ -282,8 +281,7 @@ fn path_found_listener(
let world_lock = instance_container.get(instance_name).expect( let world_lock = instance_container.get(instance_name).expect(
"Entity tried to pathfind but the entity isn't in a valid world", "Entity tried to pathfind but the entity isn't in a valid world",
); );
let world = &world_lock.read().chunks; let ctx = PathfinderCtx::new(world_lock);
let ctx = PathfinderCtx::new(world);
let successors_fn: moves::SuccessorsFn = event.successors_fn; let successors_fn: moves::SuccessorsFn = event.successors_fn;
let successors = |pos: BlockPos| successors_fn(&ctx, pos); let successors = |pos: BlockPos| successors_fn(&ctx, pos);
@ -445,8 +443,7 @@ fn tick_execute_path(
{ {
// obstruction check (the path we're executing isn't possible anymore) // obstruction check (the path we're executing isn't possible anymore)
let world = &world_lock.read().chunks; let ctx = PathfinderCtx::new(world_lock);
let ctx = PathfinderCtx::new(world);
let successors = |pos: BlockPos| successors_fn(&ctx, pos); let successors = |pos: BlockPos| successors_fn(&ctx, pos);
if let Some(last_reached_node) = pathfinder.last_reached_node { if let Some(last_reached_node) = pathfinder.last_reached_node {
@ -728,7 +725,7 @@ mod tests {
BlockPos::new(0, 67, 3), BlockPos::new(0, 67, 3),
], ],
); );
for _ in 0..40 { for _ in 0..60 {
simulation.tick(); simulation.tick();
} }
assert_eq!( assert_eq!(

View file

@ -211,7 +211,6 @@ fn execute_descend_move(
); );
if BlockPos::from(position) != target || horizontal_distance_from_target > 0.25 { if BlockPos::from(position) != target || horizontal_distance_from_target > 0.25 {
// if we're only falling one block then it's fine to try to overshoot
if horizontal_distance_from_start < 1.25 { if horizontal_distance_from_start < 1.25 {
// this basically just exists to avoid doing spins while we're falling // this basically just exists to avoid doing spins while we're falling
look_at_events.send(LookAtEvent { look_at_events.send(LookAtEvent {
@ -232,6 +231,11 @@ fn execute_descend_move(
direction: WalkDirection::Forward, direction: WalkDirection::Forward,
}); });
} }
} else {
walk_events.send(StartWalkEvent {
entity,
direction: WalkDirection::None,
});
} }
} }

View file

@ -1,7 +1,7 @@
pub mod basic; pub mod basic;
pub mod parkour; pub mod parkour;
use std::{cell::RefCell, fmt::Debug}; use std::{cell::RefCell, fmt::Debug, sync::Arc};
use crate::{JumpEvent, LookAtEvent}; use crate::{JumpEvent, LookAtEvent};
@ -10,8 +10,9 @@ use azalea_block::BlockState;
use azalea_client::{StartSprintEvent, StartWalkEvent}; use azalea_client::{StartSprintEvent, StartWalkEvent};
use azalea_core::position::{BlockPos, ChunkBlockPos, ChunkPos, Vec3}; use azalea_core::position::{BlockPos, ChunkBlockPos, ChunkPos, Vec3};
use azalea_physics::collision::BlockWithShape; use azalea_physics::collision::BlockWithShape;
use azalea_world::ChunkStorage; use azalea_world::Instance;
use bevy_ecs::{entity::Entity, event::EventWriter}; use bevy_ecs::{entity::Entity, event::EventWriter};
use parking_lot::RwLock;
type Edge = astar::Edge<BlockPos, MoveData>; type Edge = astar::Edge<BlockPos, MoveData>;
@ -33,15 +34,18 @@ impl Debug for MoveData {
} }
} }
pub struct PathfinderCtx<'a> { pub struct PathfinderCtx {
world: &'a ChunkStorage, min_y: i32,
world_lock: Arc<RwLock<Instance>>,
cached_chunks: RefCell<Vec<(ChunkPos, Vec<azalea_world::Section>)>>, cached_chunks: RefCell<Vec<(ChunkPos, Vec<azalea_world::Section>)>>,
} }
impl<'a> PathfinderCtx<'a> { impl PathfinderCtx {
pub fn new(world: &'a ChunkStorage) -> Self { pub fn new(world_lock: Arc<RwLock<Instance>>) -> Self {
let min_y = world_lock.read().chunks.min_y;
Self { Self {
world, min_y,
world_lock,
cached_chunks: Default::default(), cached_chunks: Default::default(),
} }
} }
@ -61,11 +65,12 @@ impl<'a> PathfinderCtx<'a> {
return azalea_world::chunk_storage::get_block_state_from_sections( return azalea_world::chunk_storage::get_block_state_from_sections(
sections, sections,
&chunk_block_pos, &chunk_block_pos,
self.world.min_y, self.min_y,
); );
} }
let chunk = self.world.get(&chunk_pos)?; let world = self.world_lock.read();
let chunk = world.chunks.get(&chunk_pos)?;
let chunk = chunk.read(); let chunk = chunk.read();
cached_chunks.push((chunk_pos, chunk.sections.clone())); cached_chunks.push((chunk_pos, chunk.sections.clone()));
@ -73,7 +78,7 @@ impl<'a> PathfinderCtx<'a> {
azalea_world::chunk_storage::get_block_state_from_sections( azalea_world::chunk_storage::get_block_state_from_sections(
&chunk.sections, &chunk.sections,
&chunk_block_pos, &chunk_block_pos,
self.world.min_y, self.min_y,
) )
} }
@ -136,7 +141,7 @@ impl<'a> PathfinderCtx<'a> {
distance += 1; distance += 1;
current_pos = current_pos.down(1); current_pos = current_pos.down(1);
if current_pos.y < self.world.min_y { if current_pos.y < self.min_y {
return u32::MAX; return u32::MAX;
} }
} }
@ -209,7 +214,7 @@ mod tests {
.chunks .chunks
.set_block_state(&BlockPos::new(0, 1, 0), BlockState::AIR, &world); .set_block_state(&BlockPos::new(0, 1, 0), BlockState::AIR, &world);
let ctx = PathfinderCtx::new(&world); let ctx = PathfinderCtx::new(Arc::new(RwLock::new(world.into())));
assert!(!ctx.is_block_passable(&BlockPos::new(0, 0, 0))); assert!(!ctx.is_block_passable(&BlockPos::new(0, 0, 0)));
assert!(ctx.is_block_passable(&BlockPos::new(0, 1, 0),)); assert!(ctx.is_block_passable(&BlockPos::new(0, 1, 0),));
} }
@ -230,7 +235,7 @@ mod tests {
.chunks .chunks
.set_block_state(&BlockPos::new(0, 1, 0), BlockState::AIR, &world); .set_block_state(&BlockPos::new(0, 1, 0), BlockState::AIR, &world);
let ctx = PathfinderCtx::new(&world); let ctx = PathfinderCtx::new(Arc::new(RwLock::new(world.into())));
assert!(ctx.is_block_solid(&BlockPos::new(0, 0, 0))); assert!(ctx.is_block_solid(&BlockPos::new(0, 0, 0)));
assert!(!ctx.is_block_solid(&BlockPos::new(0, 1, 0))); assert!(!ctx.is_block_solid(&BlockPos::new(0, 1, 0)));
} }
@ -257,7 +262,7 @@ mod tests {
.chunks .chunks
.set_block_state(&BlockPos::new(0, 3, 0), BlockState::AIR, &world); .set_block_state(&BlockPos::new(0, 3, 0), BlockState::AIR, &world);
let ctx = PathfinderCtx::new(&world); let ctx = PathfinderCtx::new(Arc::new(RwLock::new(world.into())));
assert!(ctx.is_standable(&BlockPos::new(0, 1, 0))); assert!(ctx.is_standable(&BlockPos::new(0, 1, 0)));
assert!(!ctx.is_standable(&BlockPos::new(0, 0, 0))); assert!(!ctx.is_standable(&BlockPos::new(0, 0, 0)));
assert!(!ctx.is_standable(&BlockPos::new(0, 2, 0))); assert!(!ctx.is_standable(&BlockPos::new(0, 2, 0)));