diff options
| -rw-r--r-- | azalea/src/pathfinder/execute/mod.rs | 35 | ||||
| -rw-r--r-- | azalea/src/pathfinder/execute/simulation.rs | 0 | ||||
| -rw-r--r-- | azalea/src/pathfinder/mod.rs | 32 | ||||
| -rw-r--r-- | azalea/src/pathfinder/moves/mod.rs | 21 | ||||
| -rw-r--r-- | azalea/src/pathfinder/moves/parkour.rs | 25 |
5 files changed, 84 insertions, 29 deletions
diff --git a/azalea/src/pathfinder/execute/mod.rs b/azalea/src/pathfinder/execute/mod.rs index a94bc994..7b5336b4 100644 --- a/azalea/src/pathfinder/execute/mod.rs +++ b/azalea/src/pathfinder/execute/mod.rs @@ -6,11 +6,13 @@ use azalea_block::{BlockState, BlockTrait}; use azalea_client::{ StartSprintEvent, StartWalkEvent, local_player::WorldHolder, - mining::{Mining, StartMiningBlockEvent}, + mining::{Mining, MiningSystems, StartMiningBlockEvent}, }; +use azalea_core::tick::GameTick; use azalea_entity::{Physics, Position, inventory::Inventory}; -use azalea_physics::get_block_pos_below_that_affects_movement; +use azalea_physics::{PhysicsSystems, get_block_pos_below_that_affects_movement}; use azalea_world::{WorldName, Worlds}; +use bevy_app::{App, Plugin}; use bevy_ecs::prelude::*; use tracing::{debug, info, trace, warn}; @@ -26,11 +28,37 @@ use crate::{ ExecutingPath, GotoEvent, Pathfinder, astar::PathfinderTimeout, custom_state::CustomPathfinderState, + debug::debug_render_path_with_particles, + execute, moves::{ExecuteCtx, IsReachedCtx}, player_pos_to_block_pos, }, }; +pub struct DefaultPathfinderExecutionPlugin; +impl Plugin for DefaultPathfinderExecutionPlugin { + fn build(&self, app: &mut App) { + app.add_systems( + // putting systems in the GameTick schedule makes them run every Minecraft tick + // (every 50 milliseconds). + GameTick, + ( + execute::timeout_movement, + execute::patching::check_for_path_obstruction, + execute::check_node_reached, + execute::tick_execute_path, + execute::recalculate_near_end_of_path, + execute::recalculate_if_has_goal_but_no_path, + ) + .chain() + .after(PhysicsSystems) + .after(azalea_client::movement::send_position) + .after(MiningSystems) + .after(debug_render_path_with_particles), + ); + } +} + #[allow(clippy::type_complexity)] pub fn tick_execute_path( mut commands: Commands, @@ -62,7 +90,7 @@ pub fn tick_execute_path( executing_path.ticks_since_last_node_reached += 1; if let Some(edge) = executing_path.path.front() { - let ctx = ExecuteCtx { + let mut ctx = ExecuteCtx { entity, target: edge.movement.target, position: **position, @@ -79,6 +107,7 @@ pub fn tick_execute_path( jump_events: &mut jump_events, start_mining_events: &mut start_mining_events, }; + ctx.on_tick_start(); trace!( "executing move, position: {}, last_reached_node: {}", **position, executing_path.last_reached_node diff --git a/azalea/src/pathfinder/execute/simulation.rs b/azalea/src/pathfinder/execute/simulation.rs new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/azalea/src/pathfinder/execute/simulation.rs diff --git a/azalea/src/pathfinder/mod.rs b/azalea/src/pathfinder/mod.rs index ee5c50c0..04c1d58c 100644 --- a/azalea/src/pathfinder/mod.rs +++ b/azalea/src/pathfinder/mod.rs @@ -31,15 +31,12 @@ use std::{ }; use astar::Edge; -use azalea_client::{ - StartWalkEvent, inventory::InventorySystems, mining::MiningSystems, movement::MoveEventsSystems, -}; +use azalea_client::{StartWalkEvent, inventory::InventorySystems, movement::MoveEventsSystems}; use azalea_core::{ position::{BlockPos, Vec3}, tick::GameTick, }; use azalea_entity::{LocalEntity, Position, inventory::Inventory, metadata::Player}; -use azalea_physics::PhysicsSystems; use azalea_world::{WorldName, Worlds}; use bevy_app::{PreUpdate, Update}; use bevy_ecs::prelude::*; @@ -64,7 +61,10 @@ use crate::{ query::{With, Without}, system::{Commands, Query, Res}, }, - pathfinder::{astar::a_star, moves::MovesCtx, world::CachedWorld}, + pathfinder::{ + astar::a_star, execute::DefaultPathfinderExecutionPlugin, moves::MovesCtx, + world::CachedWorld, + }, }; #[derive(Clone, Default)] @@ -74,24 +74,7 @@ impl Plugin for PathfinderPlugin { app.add_message::<GotoEvent>() .add_message::<PathFoundEvent>() .add_message::<StopPathfindingEvent>() - .add_systems( - // putting systems in the GameTick schedule makes them run every Minecraft tick - // (every 50 milliseconds). - GameTick, - ( - execute::timeout_movement, - execute::patching::check_for_path_obstruction, - execute::check_node_reached, - execute::tick_execute_path, - debug_render_path_with_particles, - execute::recalculate_near_end_of_path, - execute::recalculate_if_has_goal_but_no_path, - ) - .chain() - .after(PhysicsSystems) - .after(azalea_client::movement::send_position) - .after(MiningSystems), - ) + .add_systems(GameTick, debug_render_path_with_particles) .add_systems(PreUpdate, add_default_pathfinder) .add_systems( Update, @@ -105,7 +88,8 @@ impl Plugin for PathfinderPlugin { .chain() .before(MoveEventsSystems) .before(InventorySystems), - ); + ) + .add_plugins(DefaultPathfinderExecutionPlugin); } } diff --git a/azalea/src/pathfinder/moves/mod.rs b/azalea/src/pathfinder/moves/mod.rs index 1ce541c8..d977c7bd 100644 --- a/azalea/src/pathfinder/moves/mod.rs +++ b/azalea/src/pathfinder/moves/mod.rs @@ -9,13 +9,13 @@ use std::{ use azalea_block::BlockState; use azalea_client::{ - SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection, + PhysicsState, SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection, inventory::SetSelectedHotbarSlotEvent, mining::StartMiningBlockEvent, }; use azalea_core::position::{BlockPos, Vec3}; use azalea_inventory::Menu; use azalea_world::World; -use bevy_ecs::{entity::Entity, message::MessageWriter, system::Commands}; +use bevy_ecs::{entity::Entity, message::MessageWriter, system::Commands, world::EntityWorldMut}; use parking_lot::RwLock; use tracing::debug; @@ -85,6 +85,10 @@ pub struct ExecuteCtx<'s, 'w1, 'w2, 'w3, 'w4, 'w5, 'w6, 'a> { } impl ExecuteCtx<'_, '_, '_, '_, '_, '_, '_, '_> { + pub fn on_tick_start(&mut self) { + self.set_sneaking(false); + } + pub fn look_at(&mut self, position: Vec3) { self.look_at_events.write(LookAtEvent { entity: self.entity, @@ -124,6 +128,19 @@ impl ExecuteCtx<'_, '_, '_, '_, '_, '_, '_, '_> { }); } + fn set_sneaking(&mut self, sneaking: bool) { + self.commands + .entity(self.entity) + .queue(move |mut entity: EntityWorldMut<'_>| { + if let Some(mut physics_state) = entity.get_mut::<PhysicsState>() { + physics_state.trying_to_crouch = sneaking; + } + }); + } + pub fn sneak(&mut self) { + self.set_sneaking(true); + } + pub fn jump_if_in_water(&mut self) { if self.physics.is_in_water() { self.jump(); diff --git a/azalea/src/pathfinder/moves/parkour.rs b/azalea/src/pathfinder/moves/parkour.rs index 4550ab95..d37c5751 100644 --- a/azalea/src/pathfinder/moves/parkour.rs +++ b/azalea/src/pathfinder/moves/parkour.rs @@ -1,5 +1,6 @@ use azalea_client::{SprintDirection, WalkDirection}; use azalea_core::{direction::CardinalDirection, position::BlockPos}; +use azalea_physics::collision::BlockWithShape; use tracing::trace; use super::{Edge, ExecuteCtx, IsReachedCtx, MoveData, MovesCtx}; @@ -232,6 +233,30 @@ fn execute_parkour_move(mut ctx: ExecuteCtx) { } else { ctx.look_at(target_center); trace!("looking at target_center"); + + // it's possible to hit our heads on a block when doing certain jumps (which + // resets our horizontal velocity), but we can avoid that by sneaking + if !ctx.physics.on_ground() && ctx.physics.velocity.y.abs() < 0.1 { + let should_sneak = { + let world = ctx.world.read(); + let pos_above = ctx.position.up(1.62 + 0.3); + let block_pos_above = BlockPos::from(pos_above); + let block_pos_above_plus_velocity = + BlockPos::from(pos_above + ctx.physics.velocity.with_y(0.) * 4.); + + let block_above = world.get_block_state(block_pos_above).unwrap_or_default(); + let block_above_plus_velocity = world + .get_block_state(block_pos_above_plus_velocity) + .unwrap_or_default(); + + // these checks are overly lenient but it doesn't matter much + !block_above.is_collision_shape_full() + && !block_above_plus_velocity.is_collision_shape_empty() + }; + if should_sneak { + ctx.sneak(); + } + } } if !is_at_start_block && is_at_jump_block && distance_from_start > required_distance_from_center |
