aboutsummaryrefslogtreecommitdiff
path: root/azalea/src/pathfinder/moves/basic.rs
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2023-08-26 18:08:13 -0500
committermat <git@matdoes.dev>2023-08-26 18:08:13 -0500
commitdea717b68e2945777c68d44ce321639cf09ea226 (patch)
treef3909a036730343def45978f0d59f0a82673b1c2 /azalea/src/pathfinder/moves/basic.rs
parent5d7669f72b02c749a02bf034d382028e62509540 (diff)
downloadazalea-drasl-dea717b68e2945777c68d44ce321639cf09ea226.tar.xz
simplify pathfinder more
Diffstat (limited to 'azalea/src/pathfinder/moves/basic.rs')
-rw-r--r--azalea/src/pathfinder/moves/basic.rs209
1 files changed, 209 insertions, 0 deletions
diff --git a/azalea/src/pathfinder/moves/basic.rs b/azalea/src/pathfinder/moves/basic.rs
new file mode 100644
index 00000000..2d0c47c2
--- /dev/null
+++ b/azalea/src/pathfinder/moves/basic.rs
@@ -0,0 +1,209 @@
+use azalea_client::{SprintDirection, StartSprintEvent};
+use azalea_core::{BlockPos, CardinalDirection};
+use azalea_world::Instance;
+
+use crate::{pathfinder::astar, JumpEvent, LookAtEvent};
+
+use super::{
+ fall_distance, is_block_passable, is_passable, is_standable, Edge, ExecuteCtx, MoveData,
+ FALL_ONE_BLOCK_COST, JUMP_COST, WALK_ONE_BLOCK_COST,
+};
+
+pub fn basic_move(world: &Instance, node: BlockPos) -> Vec<Edge> {
+ let mut edges = Vec::new();
+ edges.extend(forward_move(world, node));
+ edges.extend(ascend_move(world, node));
+ edges.extend(descend_move(world, node));
+ edges.extend(diagonal_move(world, node));
+ edges
+}
+
+fn forward_move(world: &Instance, pos: BlockPos) -> Vec<Edge> {
+ let mut edges = Vec::new();
+ for dir in CardinalDirection::iter() {
+ let offset = BlockPos::new(dir.x(), 0, dir.z());
+
+ if !is_standable(&(pos + offset), world) {
+ continue;
+ }
+
+ let cost = WALK_ONE_BLOCK_COST;
+
+ edges.push(Edge {
+ movement: astar::Movement {
+ target: pos + offset,
+ data: MoveData {
+ execute: &execute_forward_move,
+ },
+ },
+ cost,
+ })
+ }
+
+ edges
+}
+
+fn execute_forward_move(
+ ExecuteCtx {
+ entity,
+ target,
+ look_at_events,
+ sprint_events,
+ ..
+ }: ExecuteCtx,
+) {
+ let center = target.center();
+ look_at_events.send(LookAtEvent {
+ entity,
+ position: center,
+ });
+ sprint_events.send(StartSprintEvent {
+ entity,
+ direction: SprintDirection::Forward,
+ });
+}
+
+fn ascend_move(world: &Instance, pos: BlockPos) -> Vec<Edge> {
+ let mut edges = Vec::new();
+ for dir in CardinalDirection::iter() {
+ let offset = BlockPos::new(dir.x(), 1, dir.z());
+
+ if !is_block_passable(&pos.up(2), world) || !is_standable(&(pos + offset), world) {
+ continue;
+ }
+
+ let cost = WALK_ONE_BLOCK_COST + JUMP_COST;
+
+ edges.push(Edge {
+ movement: astar::Movement {
+ target: pos + offset,
+ data: MoveData {
+ execute: &execute_ascend_move,
+ },
+ },
+ cost,
+ })
+ }
+ edges
+}
+fn execute_ascend_move(
+ ExecuteCtx {
+ entity,
+ target,
+ look_at_events,
+ sprint_events,
+ jump_events,
+ ..
+ }: ExecuteCtx,
+) {
+ let center = target.center();
+ look_at_events.send(LookAtEvent {
+ entity,
+ position: center,
+ });
+ jump_events.send(JumpEvent { entity });
+ sprint_events.send(StartSprintEvent {
+ entity,
+ direction: SprintDirection::Forward,
+ });
+}
+fn descend_move(world: &Instance, pos: BlockPos) -> Vec<Edge> {
+ let mut edges = Vec::new();
+ for dir in CardinalDirection::iter() {
+ let new_horizontal_position = pos + BlockPos::new(dir.x(), 0, dir.z());
+ let fall_distance = fall_distance(&new_horizontal_position, world);
+ if fall_distance == 0 || fall_distance > 3 {
+ continue;
+ }
+ let new_position = new_horizontal_position.down(fall_distance as i32);
+
+ // check whether 3 blocks vertically forward are passable
+ if !is_passable(&new_horizontal_position, world) {
+ continue;
+ }
+
+ let cost = WALK_ONE_BLOCK_COST + FALL_ONE_BLOCK_COST * fall_distance as f32;
+
+ edges.push(Edge {
+ movement: astar::Movement {
+ target: new_position,
+ data: MoveData {
+ execute: &execute_descend_move,
+ },
+ },
+ cost,
+ })
+ }
+ edges
+}
+fn execute_descend_move(
+ ExecuteCtx {
+ entity,
+ target,
+ look_at_events,
+ sprint_events,
+ ..
+ }: ExecuteCtx,
+) {
+ let center = target.center();
+ look_at_events.send(LookAtEvent {
+ entity,
+ position: center,
+ });
+ sprint_events.send(StartSprintEvent {
+ entity,
+ direction: SprintDirection::Forward,
+ });
+}
+
+fn diagonal_move(world: &Instance, pos: BlockPos) -> Vec<Edge> {
+ let mut edges = Vec::new();
+ for dir in CardinalDirection::iter() {
+ let right = dir.right();
+ let offset = BlockPos::new(dir.x() + right.x(), 0, dir.z() + right.z());
+
+ if !is_passable(
+ &BlockPos::new(pos.x + dir.x(), pos.y, pos.z + dir.z()),
+ world,
+ ) && !is_passable(
+ &BlockPos::new(pos.x + dir.right().x(), pos.y, pos.z + dir.right().z()),
+ world,
+ ) {
+ continue;
+ }
+ if !is_standable(&(pos + offset), world) {
+ continue;
+ }
+ let cost = WALK_ONE_BLOCK_COST * 1.4;
+
+ edges.push(Edge {
+ movement: astar::Movement {
+ target: pos + offset,
+ data: MoveData {
+ execute: &execute_diagonal_move,
+ },
+ },
+ cost,
+ })
+ }
+ edges
+}
+fn execute_diagonal_move(
+ ExecuteCtx {
+ entity,
+ target,
+ look_at_events,
+ sprint_events,
+ ..
+ }: ExecuteCtx,
+) {
+ let center = target.center();
+ look_at_events.send(LookAtEvent {
+ entity,
+ position: center,
+ });
+ sprint_events.send(StartSprintEvent {
+ entity,
+ direction: SprintDirection::Forward,
+ });
+}