aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--azalea/src/pathfinder/execute/mod.rs35
-rw-r--r--azalea/src/pathfinder/execute/simulation.rs0
-rw-r--r--azalea/src/pathfinder/mod.rs32
-rw-r--r--azalea/src/pathfinder/moves/mod.rs21
-rw-r--r--azalea/src/pathfinder/moves/parkour.rs25
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