From bffa28e7069669198906566058aaa668922c54bc Mon Sep 17 00:00:00 2001 From: mat Date: Tue, 3 Oct 2023 22:08:18 -0500 Subject: [PATCH] fix world being locked while pathfinding --- azalea/benches/pathfinder.rs | 5 +++-- azalea/src/pathfinder/mod.rs | 11 ++++------ azalea/src/pathfinder/moves/basic.rs | 6 ++++- azalea/src/pathfinder/moves/mod.rs | 33 ++++++++++++++++------------ 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/azalea/benches/pathfinder.rs b/azalea/benches/pathfinder.rs index e7c52d57..eaeaa9fb 100644 --- a/azalea/benches/pathfinder.rs +++ b/azalea/benches/pathfinder.rs @@ -1,4 +1,4 @@ -use std::{hint::black_box, time::Duration}; +use std::{hint::black_box, sync::Arc, time::Duration}; use azalea::{ pathfinder::{ @@ -12,6 +12,7 @@ use azalea::{ use azalea_core::position::{ChunkBlockPos, ChunkPos}; use azalea_world::{Chunk, ChunkStorage, PartialChunkStorage}; use criterion::{criterion_group, criterion_main, Criterion}; +use parking_lot::RwLock; use rand::Rng; fn generate_bedrock_world( @@ -78,7 +79,7 @@ fn bench_pathfinder(c: &mut Criterion) { b.iter(|| { 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 successors = |pos: BlockPos| successors_fn(&ctx, pos); diff --git a/azalea/src/pathfinder/mod.rs b/azalea/src/pathfinder/mod.rs index 99bc7787..c71d0b42 100644 --- a/azalea/src/pathfinder/mod.rs +++ b/azalea/src/pathfinder/mod.rs @@ -178,8 +178,7 @@ fn goto_listener( let task = thread_pool.spawn(async move { debug!("start: {start:?}"); - let world = &world_lock.read().chunks; - let ctx = PathfinderCtx::new(world); + let ctx = PathfinderCtx::new(world_lock); let successors = |pos: BlockPos| successors_fn(&ctx, pos); let mut attempt_number = 0; @@ -282,8 +281,7 @@ fn path_found_listener( let world_lock = instance_container.get(instance_name).expect( "Entity tried to pathfind but the entity isn't in a valid world", ); - let world = &world_lock.read().chunks; - let ctx = PathfinderCtx::new(world); + let ctx = PathfinderCtx::new(world_lock); let successors_fn: moves::SuccessorsFn = event.successors_fn; 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) - let world = &world_lock.read().chunks; - let ctx = PathfinderCtx::new(world); + let ctx = PathfinderCtx::new(world_lock); let successors = |pos: BlockPos| successors_fn(&ctx, pos); if let Some(last_reached_node) = pathfinder.last_reached_node { @@ -728,7 +725,7 @@ mod tests { BlockPos::new(0, 67, 3), ], ); - for _ in 0..40 { + for _ in 0..60 { simulation.tick(); } assert_eq!( diff --git a/azalea/src/pathfinder/moves/basic.rs b/azalea/src/pathfinder/moves/basic.rs index 26a77f4e..412f463e 100644 --- a/azalea/src/pathfinder/moves/basic.rs +++ b/azalea/src/pathfinder/moves/basic.rs @@ -211,7 +211,6 @@ fn execute_descend_move( ); 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 { // this basically just exists to avoid doing spins while we're falling look_at_events.send(LookAtEvent { @@ -232,6 +231,11 @@ fn execute_descend_move( direction: WalkDirection::Forward, }); } + } else { + walk_events.send(StartWalkEvent { + entity, + direction: WalkDirection::None, + }); } } diff --git a/azalea/src/pathfinder/moves/mod.rs b/azalea/src/pathfinder/moves/mod.rs index 39e5374f..1a626c1c 100644 --- a/azalea/src/pathfinder/moves/mod.rs +++ b/azalea/src/pathfinder/moves/mod.rs @@ -1,7 +1,7 @@ pub mod basic; pub mod parkour; -use std::{cell::RefCell, fmt::Debug}; +use std::{cell::RefCell, fmt::Debug, sync::Arc}; use crate::{JumpEvent, LookAtEvent}; @@ -10,8 +10,9 @@ use azalea_block::BlockState; use azalea_client::{StartSprintEvent, StartWalkEvent}; use azalea_core::position::{BlockPos, ChunkBlockPos, ChunkPos, Vec3}; use azalea_physics::collision::BlockWithShape; -use azalea_world::ChunkStorage; +use azalea_world::Instance; use bevy_ecs::{entity::Entity, event::EventWriter}; +use parking_lot::RwLock; type Edge = astar::Edge; @@ -33,15 +34,18 @@ impl Debug for MoveData { } } -pub struct PathfinderCtx<'a> { - world: &'a ChunkStorage, +pub struct PathfinderCtx { + min_y: i32, + world_lock: Arc>, cached_chunks: RefCell)>>, } -impl<'a> PathfinderCtx<'a> { - pub fn new(world: &'a ChunkStorage) -> Self { +impl PathfinderCtx { + pub fn new(world_lock: Arc>) -> Self { + let min_y = world_lock.read().chunks.min_y; Self { - world, + min_y, + world_lock, cached_chunks: Default::default(), } } @@ -61,11 +65,12 @@ impl<'a> PathfinderCtx<'a> { return azalea_world::chunk_storage::get_block_state_from_sections( sections, &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(); 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( &chunk.sections, &chunk_block_pos, - self.world.min_y, + self.min_y, ) } @@ -136,7 +141,7 @@ impl<'a> PathfinderCtx<'a> { distance += 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; } } @@ -209,7 +214,7 @@ mod tests { .chunks .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, 1, 0),)); } @@ -230,7 +235,7 @@ mod tests { .chunks .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, 1, 0))); } @@ -257,7 +262,7 @@ mod tests { .chunks .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, 0, 0))); assert!(!ctx.is_standable(&BlockPos::new(0, 2, 0)));