Skip to content

Commit

Permalink
start implementing MineForever process
Browse files Browse the repository at this point in the history
  • Loading branch information
mat-1 committed Dec 18, 2023
1 parent 6b90194 commit 4242cfe
Show file tree
Hide file tree
Showing 11 changed files with 361 additions and 222 deletions.
16 changes: 16 additions & 0 deletions azalea-block/src/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,19 @@ impl Add for BlockStates {
}
}
}

impl From<HashSet<azalea_registry::Block>> for BlockStates {
fn from(set: HashSet<azalea_registry::Block>) -> Self {
Self {
set: set.into_iter().map(|block| block.into()).collect(),
}
}
}

impl From<&HashSet<azalea_registry::Block>> for BlockStates {
fn from(set: &HashSet<azalea_registry::Block>) -> Self {
Self {
set: set.iter().map(|&block| block.into()).collect(),
}
}
}
73 changes: 51 additions & 22 deletions azalea-entity/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use bevy_ecs::{bundle::Bundle, component::Component};
pub use data::*;
use derive_more::{Deref, DerefMut};
pub use dimensions::EntityDimensions;
use std::fmt::Debug;
use std::{f64::consts::PI, fmt::Debug};
use uuid::Uuid;

pub use crate::plugin::*;
Expand Down Expand Up @@ -390,24 +390,53 @@ impl FluidOnEyes {
#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)]
pub struct OnClimbable(bool);

// #[cfg(test)]
// mod tests {
// use super::*;
// use crate::PartialWorld;

// #[test]
// fn from_mut_entity_to_ref_entity() {
// let mut world = PartialWorld::default();
// let uuid = Uuid::from_u128(100);
// world.add_entity(
// 0,
// EntityData::new(
// uuid,
// Vec3::default(),
// EntityMetadata::Player(metadata::Player::default()),
// ),
// );
// let entity: Entity = world.entity_mut(0).unwrap();
// assert_eq!(entity.uuid, uuid);
// }
// }
/// Return the look direction that would make a client at `current` be
/// looking at `target`.
pub fn direction_looking_at(current: &Vec3, target: &Vec3) -> LookDirection {
// borrowed from mineflayer's Bot.lookAt because i didn't want to do math
let delta = target - current;
let y_rot = (PI - f64::atan2(-delta.x, -delta.z)) * (180.0 / PI);
let ground_distance = f64::sqrt(delta.x * delta.x + delta.z * delta.z);
let x_rot = f64::atan2(delta.y, ground_distance) * -(180.0 / PI);

// clamp
let y_rot = y_rot.rem_euclid(360.0);
let x_rot = x_rot.clamp(-90.0, 90.0) % 360.0;

LookDirection {
x_rot: x_rot as f32,
y_rot: y_rot as f32,
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_direction_looking_at() {
let direction = direction_looking_at(&Vec3::new(0.0, 0.0, 0.0), &Vec3::new(0.0, 0.0, 1.0));
assert_eq!(direction.y_rot, 0.0);
assert_eq!(direction.x_rot, 0.0);

let direction = direction_looking_at(&Vec3::new(0.0, 0.0, 0.0), &Vec3::new(1.0, 0.0, 0.0));
assert_eq!(direction.y_rot, 270.0);
assert_eq!(direction.x_rot, 0.0);

let direction = direction_looking_at(&Vec3::new(0.0, 0.0, 0.0), &Vec3::new(0.0, 0.0, -1.0));
assert_eq!(direction.y_rot, 180.0);
assert_eq!(direction.x_rot, 0.0);

let direction = direction_looking_at(&Vec3::new(0.0, 0.0, 0.0), &Vec3::new(-1.0, 0.0, 0.0));
assert_eq!(direction.y_rot, 90.0);
assert_eq!(direction.x_rot, 0.0);

let direction = direction_looking_at(&Vec3::new(0.0, 0.0, 0.0), &Vec3::new(0.0, 1.0, 0.0));
assert_eq!(direction.y_rot, 0.0);
assert_eq!(direction.x_rot, -90.0);

let direction = direction_looking_at(&Vec3::new(0.0, 0.0, 0.0), &Vec3::new(0.0, -1.0, 0.0));
assert_eq!(direction.y_rot, 0.0);
assert_eq!(direction.x_rot, 90.0);
}
}
2 changes: 1 addition & 1 deletion azalea/src/bot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ use crate::ecs::{
system::{Commands, Query},
};
use crate::pathfinder_extras::PathfinderExtrasPlugin;
use crate::utils::direction_looking_at;
use azalea_client::interact::SwingArmEvent;
use azalea_client::mining::Mining;
use azalea_client::TickBroadcast;
use azalea_core::position::{BlockPos, Vec3};
use azalea_core::tick::GameTick;
use azalea_entity::direction_looking_at;
use azalea_entity::{
clamp_look_direction, metadata::Player, EyeHeight, Jumping, LocalEntity, LookDirection,
Position,
Expand Down
1 change: 0 additions & 1 deletion azalea/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ pub mod pathfinder;
pub mod pathfinder_extras;
pub mod prelude;
pub mod swarm;
pub mod utils;

use app::Plugins;
pub use azalea_auth as auth;
Expand Down
113 changes: 3 additions & 110 deletions azalea/src/pathfinder/goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,8 @@
use std::f32::consts::SQRT_2;

use azalea_core::position::{BlockPos, Vec3};
use azalea_world::ChunkStorage;

use crate::utils::get_hit_result_while_looking_at;

use super::{
block_box::BlockBox,
costs::{COST_HEURISTIC, FALL_N_BLOCKS_COST, JUMP_ONE_BLOCK_COST},
};
use super::costs::{COST_HEURISTIC, FALL_N_BLOCKS_COST, JUMP_ONE_BLOCK_COST};

pub trait Goal: Send + Sync {
#[must_use]
Expand All @@ -35,7 +29,7 @@ impl Goal for BlockPosGoal {
}
}

fn xz_heuristic(dx: f32, dz: f32) -> f32 {
pub fn xz_heuristic(dx: f32, dz: f32) -> f32 {
let x = dx.abs();
let z = dz.abs();

Expand Down Expand Up @@ -70,7 +64,7 @@ impl Goal for XZGoal {
}
}

fn y_heuristic(dy: f32) -> f32 {
pub fn y_heuristic(dy: f32) -> f32 {
if dy > 0.0 {
*JUMP_ONE_BLOCK_COST * dy
} else {
Expand Down Expand Up @@ -183,104 +177,3 @@ impl<T: Goal> Goal for AndGoals<T> {
self.0.iter().all(|goal| goal.success(n))
}
}

/// Move to a position where we can reach the given block.
#[derive(Debug)]
pub struct ReachBlockPosGoal {
pub pos: BlockPos,
pub chunk_storage: ChunkStorage,
}
impl Goal for ReachBlockPosGoal {
fn heuristic(&self, n: BlockPos) -> f32 {
BlockPosGoal(self.pos).heuristic(n)
}
fn success(&self, n: BlockPos) -> bool {
// only do the expensive check if we're close enough
let max_pick_range = 6;

let distance = (self.pos - n).length_squared();
if distance > max_pick_range * max_pick_range {
return false;
}

let block_hit_result = get_hit_result_while_looking_at(&self.chunk_storage, n, self.pos);

block_hit_result == self.pos
}
}

/// Move to a position inside of the given box (inclusive, so the corners are
/// included in the box).
#[derive(Debug)]
pub struct BoxGoal(pub BlockBox);

impl Goal for BoxGoal {
fn heuristic(&self, n: BlockPos) -> f32 {
let dx = if n.x < self.0.min().x {
self.0.min().x - n.x
} else if n.x > self.0.max().x {
n.x - self.0.max().x
} else {
0
};
let dy = if n.y < self.0.min().y {
self.0.min().y - n.y
} else if n.y > self.0.max().y {
n.y - self.0.max().y
} else {
0
};
let dz = if n.z < self.0.min().z {
self.0.min().z - n.z
} else if n.z > self.0.max().z {
n.z - self.0.max().z
} else {
0
};

xz_heuristic(dx as f32, dz as f32) + y_heuristic(dy as f32)
}

fn success(&self, n: BlockPos) -> bool {
n.x >= self.0.min().x
&& n.x <= self.0.max().x
&& n.y >= self.0.min().y
&& n.y <= self.0.max().y
&& n.z >= self.0.min().z
&& n.z <= self.0.max().z
}
}

/// Move to a position where we can reach at least one block from the given box.
/// This is usually used when digging out an area.
#[derive(Debug)]
pub struct ReachBoxGoal {
pub bb: BlockBox,
pub chunk_storage: ChunkStorage,
}
impl Goal for ReachBoxGoal {
fn heuristic(&self, n: BlockPos) -> f32 {
BoxGoal(self.bb.clone()).heuristic(n)
}

fn success(&self, n: BlockPos) -> bool {
// succeed if we're already in the box
if self.bb.contains(n) {
return true;
}

// only do the expensive check if we're close enough
let max_pick_range = 6;

let distance = self.bb.distance_squared_to(n);
if distance > max_pick_range * max_pick_range {
return false;
}

// look at the closest block
let look_target = self.bb.closest_block_pos(n);
let hit_result = get_hit_result_while_looking_at(&self.chunk_storage, n, look_target);

self.bb.contains(hit_result)
}
}
113 changes: 113 additions & 0 deletions azalea/src/pathfinder_extras/goals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//! Slightly more unusual goals than the normal
//! [pathfinder ones](crate::pathfinder::goals).
use azalea_core::position::BlockPos;
use azalea_world::ChunkStorage;

use crate::pathfinder::{
block_box::BlockBox,
goals::{xz_heuristic, y_heuristic, BlockPosGoal, Goal},
};

use super::utils::get_hit_result_while_looking_at;

/// Move to a position where we can reach the given block.
#[derive(Debug)]
pub struct ReachBlockPosGoal {
pub pos: BlockPos,
pub chunk_storage: ChunkStorage,
}
impl Goal for ReachBlockPosGoal {
fn heuristic(&self, n: BlockPos) -> f32 {
BlockPosGoal(self.pos).heuristic(n)
}
fn success(&self, n: BlockPos) -> bool {
// only do the expensive check if we're close enough
let max_pick_range = 6;

let distance = (self.pos - n).length_squared();
if distance > max_pick_range * max_pick_range {
return false;
}

let block_hit_result = get_hit_result_while_looking_at(&self.chunk_storage, n, self.pos);

block_hit_result == self.pos
}
}

/// Move to a position inside of the given box (inclusive, so the corners are
/// included in the box).
#[derive(Debug)]
pub struct BoxGoal(pub BlockBox);

impl Goal for BoxGoal {
fn heuristic(&self, n: BlockPos) -> f32 {
let dx = if n.x < self.0.min().x {
self.0.min().x - n.x
} else if n.x > self.0.max().x {
n.x - self.0.max().x
} else {
0
};
let dy = if n.y < self.0.min().y {
self.0.min().y - n.y
} else if n.y > self.0.max().y {
n.y - self.0.max().y
} else {
0
};
let dz = if n.z < self.0.min().z {
self.0.min().z - n.z
} else if n.z > self.0.max().z {
n.z - self.0.max().z
} else {
0
};

xz_heuristic(dx as f32, dz as f32) + y_heuristic(dy as f32)
}

fn success(&self, n: BlockPos) -> bool {
n.x >= self.0.min().x
&& n.x <= self.0.max().x
&& n.y >= self.0.min().y
&& n.y <= self.0.max().y
&& n.z >= self.0.min().z
&& n.z <= self.0.max().z
}
}

/// Move to a position where we can reach at least one block from the given box.
/// This is usually used when digging out an area.
#[derive(Debug)]
pub struct ReachBoxGoal {
pub bb: BlockBox,
pub chunk_storage: ChunkStorage,
}
impl Goal for ReachBoxGoal {
fn heuristic(&self, n: BlockPos) -> f32 {
BoxGoal(self.bb.clone()).heuristic(n)
}

fn success(&self, n: BlockPos) -> bool {
// succeed if we're already in the box
if self.bb.contains(n) {
return true;
}

// only do the expensive check if we're close enough
let max_pick_range = 6;

let distance = self.bb.distance_squared_to(n);
if distance > max_pick_range * max_pick_range {
return false;
}

// look at the closest block
let look_target = self.bb.closest_block_pos(n);
let hit_result = get_hit_result_while_looking_at(&self.chunk_storage, n, look_target);

self.bb.contains(hit_result)
}
}
Loading

0 comments on commit 4242cfe

Please sign in to comment.