Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pathfinder extras #123

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
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(),
}
}
}
2 changes: 1 addition & 1 deletion azalea-client/src/chunks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub struct ChunkBatchFinishedEvent {
pub batch_size: u32,
}

fn handle_receive_chunk_events(
pub fn handle_receive_chunk_events(
mut events: EventReader<ReceiveChunkEvent>,
mut query: Query<&mut InstanceHolder>,
) {
Expand Down
55 changes: 55 additions & 0 deletions azalea-client/src/interact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,3 +370,58 @@ fn update_modifiers_for_held_item(
));
}
}

#[cfg(test)]
mod tests {
use azalea_core::position::ChunkPos;
use azalea_world::{Chunk, ChunkStorage, PartialInstance};

use super::*;

#[test]
fn test_pick() {
let mut partial_world = PartialInstance::default();
let mut world = ChunkStorage::default();

partial_world
.chunks
.update_view_center(ChunkPos { x: -184, z: -2 });
partial_world.chunks.set(
&ChunkPos { x: -184, z: -2 },
Some(Chunk::default()),
&mut world,
);

let set_block = |x, y, z| {
partial_world
.chunks
.set_block_state(
&BlockPos::new(x, y, z),
azalea_registry::Block::Stone.into(),
&world,
)
.expect(&format!("failed to set block at {x} {y} {z}"));
};

for x in -2940..=-2936 {
for z in -24..=-20 {
set_block(x, 64, z);
set_block(x, 65, z);
}
}

let hit_result = pick(
&LookDirection {
y_rot: 45.,
x_rot: 35.66751,
// x_rot: 35.,
},
&Vec3::new(-2936.5, 66. + 1.53, -22.5),
&world,
4.5,
);

assert!(!hit_result.miss);
assert_eq!(hit_result.block_pos, BlockPos::new(-2939, 65, -21));
}
}
2 changes: 1 addition & 1 deletion azalea-client/src/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,7 @@ pub struct SetSelectedHotbarSlotEvent {
/// The hotbar slot to select. This should be in the range 0..=8.
pub slot: u8,
}
fn handle_set_selected_hotbar_slot_event(
pub fn handle_set_selected_hotbar_slot_event(
mut events: EventReader<SetSelectedHotbarSlotEvent>,
mut send_packet_events: EventWriter<SendPacketEvent>,
mut query: Query<&mut InventoryComponent>,
Expand Down
6 changes: 3 additions & 3 deletions azalea-client/src/mining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,16 +396,16 @@ impl MineProgress {
/// A component that stores the number of ticks that we've been mining the same
/// block for. This is a float even though it should only ever be a round
/// number.
#[derive(Component, Debug, Default, Deref, DerefMut)]
#[derive(Component, Clone, Debug, Default, Deref, DerefMut)]
pub struct MineTicks(pub f32);

/// A component that stores the position of the block we're currently mining.
#[derive(Component, Debug, Default, Deref, DerefMut)]
#[derive(Component, Clone, Debug, Default, Deref, DerefMut)]
pub struct MineBlockPos(pub Option<BlockPos>);

/// A component that contains the item we're currently using to mine. If we're
/// not mining anything, it'll be [`ItemSlot::Empty`].
#[derive(Component, Debug, Default, Deref, DerefMut)]
#[derive(Component, Clone, Debug, Default, Deref, DerefMut)]
pub struct MineItem(pub ItemSlot);

/// Sent when we completed mining a block.
Expand Down
4 changes: 0 additions & 4 deletions azalea-core/src/delta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ impl Vec3 {
}
}

pub fn length_squared(&self) -> f64 {
self.x * self.x + self.y * self.y + self.z * self.z
}

pub fn normalize(&self) -> Vec3 {
let length = f64::sqrt(self.x * self.x + self.y * self.y + self.z * self.z);
if length < 1e-4 {
Expand Down
8 changes: 7 additions & 1 deletion azalea-core/src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub fn cos(x: f32) -> f32 {
}

// TODO: make this generic
pub fn binary_search(mut min: i32, max: i32, predicate: &dyn Fn(i32) -> bool) -> i32 {
pub fn binary_search(mut min: i32, max: i32, predicate: impl Fn(i32) -> bool) -> i32 {
let mut diff = max - min;
while diff > 0 {
let diff_mid = diff / 2;
Expand Down Expand Up @@ -62,6 +62,12 @@ pub fn ceil_log2(x: u32) -> u32 {
u32::BITS - x.leading_zeros()
}

pub fn fract(x: f64) -> f64 {
let x_int = x as i64 as f64;
let floor = if x < x_int { x_int - 1. } else { x_int };
x - floor
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
54 changes: 47 additions & 7 deletions azalea-core/src/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,25 @@ macro_rules! vec3_impl {
/// Get the distance of this vector to the origin by doing `x^2 + y^2 +
/// z^2`.
#[inline]
pub fn length_sqr(&self) -> $type {
pub fn length_squared(&self) -> $type {
self.x * self.x + self.y * self.y + self.z * self.z
}

/// Get the squared distance from this position to another position.
/// Equivalent to `(self - other).length_sqr()`.
/// Equivalent to `(self - other).length_squared()`.
#[inline]
pub fn distance_to_sqr(&self, other: &Self) -> $type {
(self - other).length_sqr()
pub fn distance_squared_to(&self, other: &Self) -> $type {
(self - other).length_squared()
}

#[inline]
pub fn horizontal_distance_sqr(&self) -> $type {
pub fn horizontal_distance_squared(&self) -> $type {
self.x * self.x + self.z * self.z
}

#[inline]
pub fn horizontal_distance_to_sqr(&self, other: &Self) -> $type {
(self - other).horizontal_distance_sqr()
pub fn horizontal_distance_squared_to(&self, other: &Self) -> $type {
(self - other).horizontal_distance_squared()
}

/// Return a new instance of this position with the y coordinate
Expand Down Expand Up @@ -266,6 +266,46 @@ impl BlockPos {
pub fn length_manhattan(&self) -> u32 {
(self.x.abs() + self.y.abs() + self.z.abs()) as u32
}

/// Make a new BlockPos with the lower coordinates for each axis.
///
/// ```
/// # use azalea_core::position::BlockPos;
/// assert_eq!(
/// BlockPos::min(
/// &BlockPos::new(1, 20, 300),
/// &BlockPos::new(50, 40, 30),
/// ),
/// BlockPos::new(1, 20, 30),
/// );
/// ```
pub fn min(&self, other: &Self) -> Self {
Self {
x: self.x.min(other.x),
y: self.y.min(other.y),
z: self.z.min(other.z),
}
}

/// Make a new BlockPos with the higher coordinates for each axis.
///
/// ```
/// # use azalea_core::position::BlockPos;
/// assert_eq!(
/// BlockPos::max(
/// &BlockPos::new(1, 20, 300),
/// &BlockPos::new(50, 40, 30),
/// ),
/// BlockPos::new(50, 40, 300),
/// );
/// ```
pub fn max(&self, other: &Self) -> Self {
Self {
x: self.x.max(other.x),
y: self.y.max(other.y),
z: self.z.max(other.z),
}
}
}

/// Chunk coordinates are used to represent where a chunk is in the world. You
Expand Down
72 changes: 51 additions & 21 deletions azalea-entity/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use derive_more::{Deref, DerefMut};
pub use dimensions::EntityDimensions;
use plugin::indexing::EntityChunkPos;
use std::{
f64::consts::PI,
fmt::Debug,
hash::{Hash, Hasher},
};
Expand Down Expand Up @@ -426,24 +427,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);
}
}
Loading
Loading