#![allow(clippy::derived_hash_with_manual_eq)]
pub mod attributes;
mod data;
mod dimensions;
mod effects;
mod enchantments;
pub mod metadata;
pub mod mining;
pub mod particle;
mod plugin;
use std::{
fmt::Debug,
hash::{Hash, Hasher},
};
pub use attributes::Attributes;
use azalea_block::BlockState;
use azalea_core::{
aabb::AABB,
math,
position::{BlockPos, ChunkPos, Vec3},
resource_location::ResourceLocation,
};
use azalea_world::{ChunkStorage, InstanceName};
use bevy_ecs::{bundle::Bundle, component::Component};
pub use data::*;
use derive_more::{Deref, DerefMut};
pub use dimensions::EntityDimensions;
use plugin::indexing::EntityChunkPos;
use uuid::Uuid;
use self::attributes::AttributeInstance;
pub use crate::plugin::*;
pub fn move_relative(
physics: &mut Physics,
direction: &LookDirection,
speed: f32,
acceleration: &Vec3,
) {
let input_vector = input_vector(direction, speed, acceleration);
physics.velocity += input_vector;
}
pub fn input_vector(direction: &LookDirection, speed: f32, acceleration: &Vec3) -> Vec3 {
let distance = acceleration.length_squared();
if distance < 1.0E-7 {
return Vec3::default();
}
let acceleration = if distance > 1.0 {
acceleration.normalize()
} else {
*acceleration
}
.scale(speed as f64);
let y_rot = math::sin(direction.y_rot * 0.017453292f32);
let x_rot = math::cos(direction.y_rot * 0.017453292f32);
Vec3 {
x: acceleration.x * (x_rot as f64) - acceleration.z * (y_rot as f64),
y: acceleration.y,
z: acceleration.z * (x_rot as f64) + acceleration.x * (y_rot as f64),
}
}
pub fn view_vector(look_direction: &LookDirection) -> Vec3 {
let x_rot = look_direction.x_rot * 0.017453292;
let y_rot = -look_direction.y_rot * 0.017453292;
let y_rot_cos = math::cos(y_rot);
let y_rot_sin = math::sin(y_rot);
let x_rot_cos = math::cos(x_rot);
let x_rot_sin = math::sin(x_rot);
Vec3 {
x: (y_rot_sin * x_rot_cos) as f64,
y: (-x_rot_sin) as f64,
z: (y_rot_cos * x_rot_cos) as f64,
}
}
pub fn on_pos_legacy(chunk_storage: &ChunkStorage, position: &Position) -> BlockPos {
on_pos(0.2, chunk_storage, position)
}
pub fn on_pos(offset: f32, chunk_storage: &ChunkStorage, pos: &Position) -> BlockPos {
let x = pos.x.floor() as i32;
let y = (pos.y - offset as f64).floor() as i32;
let z = pos.z.floor() as i32;
let pos = BlockPos { x, y, z };
let block_pos = pos.down(1);
let block_state = chunk_storage.get_block_state(&block_pos);
if block_state == Some(BlockState::AIR) {
let block_pos_below = block_pos.down(1);
let block_state_below = chunk_storage.get_block_state(&block_pos_below);
if let Some(_block_state_below) = block_state_below {
}
}
pos
}
#[derive(Component, Deref, DerefMut, Clone, Copy, Default)]
pub struct EntityUuid(Uuid);
impl EntityUuid {
pub fn new(uuid: Uuid) -> Self {
Self(uuid)
}
}
impl Debug for EntityUuid {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self.0).fmt(f)
}
}
#[derive(Component, Clone, Copy, Debug, Default, PartialEq, Deref, DerefMut)]
pub struct Position(Vec3);
impl Position {
pub fn new(pos: Vec3) -> Self {
Self(pos)
}
}
impl From<&Position> for Vec3 {
fn from(value: &Position) -> Self {
value.0
}
}
impl From<Position> for ChunkPos {
fn from(value: Position) -> Self {
ChunkPos::from(&value.0)
}
}
impl From<Position> for BlockPos {
fn from(value: Position) -> Self {
BlockPos::from(&value.0)
}
}
impl From<&Position> for ChunkPos {
fn from(value: &Position) -> Self {
ChunkPos::from(value.0)
}
}
impl From<&Position> for BlockPos {
fn from(value: &Position) -> Self {
BlockPos::from(value.0)
}
}
#[derive(Component, Clone, Copy, Debug, Default, PartialEq, Deref, DerefMut)]
pub struct LastSentPosition(Vec3);
impl From<&LastSentPosition> for Vec3 {
fn from(value: &LastSentPosition) -> Self {
value.0
}
}
impl From<LastSentPosition> for ChunkPos {
fn from(value: LastSentPosition) -> Self {
ChunkPos::from(&value.0)
}
}
impl From<LastSentPosition> for BlockPos {
fn from(value: LastSentPosition) -> Self {
BlockPos::from(&value.0)
}
}
impl From<&LastSentPosition> for ChunkPos {
fn from(value: &LastSentPosition) -> Self {
ChunkPos::from(value.0)
}
}
impl From<&LastSentPosition> for BlockPos {
fn from(value: &LastSentPosition) -> Self {
BlockPos::from(value.0)
}
}
#[derive(Debug, Component, Copy, Clone, Deref, DerefMut, Default)]
pub struct Jumping(bool);
#[derive(Debug, Component, Copy, Clone, Default, PartialEq)]
pub struct LookDirection {
pub y_rot: f32,
pub x_rot: f32,
}
impl LookDirection {
pub fn new(y_rot: f32, x_rot: f32) -> Self {
Self { y_rot, x_rot }
}
}
impl From<LookDirection> for (f32, f32) {
fn from(value: LookDirection) -> Self {
(value.y_rot, value.x_rot)
}
}
impl From<(f32, f32)> for LookDirection {
fn from((y_rot, x_rot): (f32, f32)) -> Self {
Self { y_rot, x_rot }
}
}
impl Hash for LookDirection {
fn hash<H: Hasher>(&self, state: &mut H) {
self.y_rot.to_bits().hash(state);
self.x_rot.to_bits().hash(state);
}
}
impl Eq for LookDirection {}
#[derive(Debug, Component, Clone)]
pub struct Physics {
pub velocity: Vec3,
pub xxa: f32,
pub yya: f32,
pub zza: f32,
pub on_ground: bool,
pub last_on_ground: bool,
pub dimensions: EntityDimensions,
pub bounding_box: AABB,
pub has_impulse: bool,
pub horizontal_collision: bool,
pub vertical_collision: bool,
}
impl Physics {
pub fn new(dimensions: EntityDimensions, pos: &Vec3) -> Self {
Self {
velocity: Vec3::default(),
xxa: 0.,
yya: 0.,
zza: 0.,
on_ground: false,
last_on_ground: false,
bounding_box: dimensions.make_bounding_box(pos),
dimensions,
has_impulse: false,
horizontal_collision: false,
vertical_collision: false,
}
}
}
#[derive(Component, Copy, Clone, Default)]
pub struct Dead;
#[derive(Component, Clone, Copy, Debug, PartialEq, Deref, DerefMut)]
pub struct EyeHeight(f32);
impl EyeHeight {
pub fn new(height: f32) -> Self {
Self(height)
}
}
impl From<EyeHeight> for f32 {
fn from(value: EyeHeight) -> Self {
value.0
}
}
impl From<EyeHeight> for f64 {
fn from(value: EyeHeight) -> Self {
value.0 as f64
}
}
impl From<&EyeHeight> for f32 {
fn from(value: &EyeHeight) -> Self {
value.0
}
}
impl From<&EyeHeight> for f64 {
fn from(value: &EyeHeight) -> Self {
value.0 as f64
}
}
#[derive(Component, Clone, Copy, Debug, PartialEq, Deref)]
pub struct EntityKind(pub azalea_registry::EntityKind);
#[derive(Bundle)]
pub struct EntityBundle {
pub kind: EntityKind,
pub uuid: EntityUuid,
pub world_name: InstanceName,
pub position: Position,
pub last_sent_position: LastSentPosition,
pub chunk_pos: EntityChunkPos,
pub physics: Physics,
pub direction: LookDirection,
pub eye_height: EyeHeight,
pub attributes: Attributes,
pub jumping: Jumping,
pub fluid_on_eyes: FluidOnEyes,
pub on_climbable: OnClimbable,
}
impl EntityBundle {
pub fn new(
uuid: Uuid,
pos: Vec3,
kind: azalea_registry::EntityKind,
world_name: ResourceLocation,
) -> Self {
let dimensions = EntityDimensions {
width: 0.6,
height: 1.8,
};
let eye_height = dimensions.height * 0.85;
Self {
kind: EntityKind(kind),
uuid: EntityUuid(uuid),
world_name: InstanceName(world_name),
position: Position(pos),
chunk_pos: EntityChunkPos(ChunkPos::from(&pos)),
last_sent_position: LastSentPosition(pos),
physics: Physics::new(dimensions, &pos),
eye_height: EyeHeight(eye_height),
direction: LookDirection::default(),
attributes: Attributes {
speed: AttributeInstance::new(0.1),
attack_speed: AttributeInstance::new(4.0),
},
jumping: Jumping(false),
fluid_on_eyes: FluidOnEyes(azalea_registry::Fluid::Empty),
on_climbable: OnClimbable(false),
}
}
}
#[derive(Bundle)]
pub struct PlayerBundle {
pub entity: EntityBundle,
pub metadata: metadata::PlayerMetadataBundle,
}
#[derive(Component, Clone)]
pub struct LocalEntity;
#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)]
pub struct FluidOnEyes(azalea_registry::Fluid);
impl FluidOnEyes {
pub fn new(fluid: azalea_registry::Fluid) -> Self {
Self(fluid)
}
}
#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)]
pub struct OnClimbable(bool);