aboutsummaryrefslogtreecommitdiff
path: root/azalea/src/pathfinder/moves
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2026-01-18 10:15:41 +0800
committermat <git@matdoes.dev>2026-01-18 11:18:36 +0900
commit5c3ea8e1d97d92b4ea9c406bbb59f928ee0c6a66 (patch)
treec7acff524da2229a0bc933ef1bf8a9c3e91d0bc6 /azalea/src/pathfinder/moves
parent81e5a0200a4fe5438ab67c82600f063410d637c0 (diff)
downloadazalea-drasl-5c3ea8e1d97d92b4ea9c406bbb59f928ee0c6a66.tar.xz
don't fail parkour jumps that collide with ceiling blocks horizontally
Diffstat (limited to 'azalea/src/pathfinder/moves')
-rw-r--r--azalea/src/pathfinder/moves/mod.rs21
-rw-r--r--azalea/src/pathfinder/moves/parkour.rs25
2 files changed, 44 insertions, 2 deletions
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