diff options
Diffstat (limited to 'azalea-world/src/entity/mod.rs')
| -rw-r--r-- | azalea-world/src/entity/mod.rs | 108 |
1 files changed, 80 insertions, 28 deletions
diff --git a/azalea-world/src/entity/mod.rs b/azalea-world/src/entity/mod.rs index 84c183ff..d1d29a5a 100644 --- a/azalea-world/src/entity/mod.rs +++ b/azalea-world/src/entity/mod.rs @@ -23,7 +23,8 @@ pub use data::*; use derive_more::{Deref, DerefMut}; pub use dimensions::{update_bounding_box, EntityDimensions}; pub use info::{ - EntityInfos, EntityPlugin, EntityUpdateSet, LoadedBy, PartialEntityInfos, RelativeEntityUpdate, + clamp_look_direction, EntityInfos, EntityPlugin, EntityUpdateSet, LoadedBy, PartialEntityInfos, + RelativeEntityUpdate, }; use std::fmt::Debug; use uuid::Uuid; @@ -38,19 +39,18 @@ impl std::hash::Hash for MinecraftEntityId { } } impl nohash_hasher::IsEnabled for MinecraftEntityId {} -pub fn set_rotation(physics: &mut Physics, y_rot: f32, x_rot: f32) { - physics.y_rot = y_rot % 360.0; - physics.x_rot = x_rot.clamp(-90.0, 90.0) % 360.0; - // TODO: minecraft also sets yRotO and xRotO to xRot and yRot ... but - // idk what they're used for so -} -pub fn move_relative(physics: &mut Physics, speed: f32, acceleration: &Vec3) { - let input_vector = input_vector(physics, speed, acceleration); +pub fn move_relative( + physics: &mut Physics, + direction: &LookDirection, + speed: f32, + acceleration: &Vec3, +) { + let input_vector = input_vector(direction, speed, acceleration); physics.delta += input_vector; } -pub fn input_vector(physics: &mut Physics, speed: f32, acceleration: &Vec3) -> Vec3 { +pub fn input_vector(direction: &LookDirection, speed: f32, acceleration: &Vec3) -> Vec3 { let distance = acceleration.length_squared(); if distance < 1.0E-7 { return Vec3::default(); @@ -61,8 +61,8 @@ pub fn input_vector(physics: &mut Physics, speed: f32, acceleration: &Vec3) -> V *acceleration } .scale(speed as f64); - let y_rot = f32::sin(physics.y_rot * 0.017453292f32); - let x_rot = f32::cos(physics.y_rot * 0.017453292f32); + let y_rot = f32::sin(direction.y_rot * 0.017453292f32); + let x_rot = f32::cos(direction.y_rot * 0.017453292f32); Vec3 { x: acceleration.x * (x_rot as f64) - acceleration.z * (y_rot as f64), y: acceleration.y, @@ -70,6 +70,20 @@ pub fn input_vector(physics: &mut Physics, speed: f32, acceleration: &Vec3) -> V } } +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 = f32::cos(y_rot); + let y_rot_sin = f32::sin(y_rot); + let x_rot_cos = f32::cos(x_rot); + let x_rot_sin = f32::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, + } +} + /// Get the position of the block below the entity, but a little lower. pub fn on_pos_legacy(chunk_storage: &ChunkStorage, position: &Position) -> BlockPos { on_pos(0.2, chunk_storage, position) @@ -128,6 +142,11 @@ impl Debug for EntityUuid { /// automatically. #[derive(Component, Clone, Copy, Debug, Default, PartialEq, Deref, DerefMut)] pub struct Position(Vec3); +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) @@ -149,9 +168,14 @@ impl From<&Position> for BlockPos { } } -/// The last position of the entity that was sent to the network. +/// The last position of the entity that was sent over the network. #[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) @@ -182,9 +206,16 @@ pub struct WorldName(pub ResourceLocation); /// /// If this is true, the entity will try to jump every tick. (It's equivalent to /// the space key being held in vanilla.) -#[derive(Debug, Component, Deref, DerefMut)] +#[derive(Debug, Component, Clone, Deref, DerefMut)] pub struct Jumping(bool); +/// A component that contains the direction an entity is looking. +#[derive(Debug, Component, Clone, Default)] +pub struct LookDirection { + pub x_rot: f32, + pub y_rot: f32, +} + /// The physics data relating to the entity, such as position, velocity, and /// bounding box. #[derive(Debug, Component)] @@ -198,12 +229,6 @@ pub struct Physics { /// Z acceleration. pub zza: f32, - pub x_rot: f32, - pub y_rot: f32, - - pub x_rot_last: f32, - pub y_rot_last: f32, - pub on_ground: bool, pub last_on_ground: bool, @@ -237,10 +262,38 @@ pub fn add_dead(mut commands: Commands, query: Query<(Entity, &Health), Changed< } } +/// A component that contains the offset of the entity's eyes from the entity +/// coordinates. +/// +/// This is used to calculate the camera position for players, when spectating +/// an entity, and when raytracing from the entity. +#[derive(Component, Clone, Copy, Debug, PartialEq, Deref, DerefMut)] +pub struct EyeHeight(f32); +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 + } +} + /// A component NewType for [`azalea_registry::EntityKind`]. /// /// Most of the time, you should be using `azalea_registry::EntityKind` -/// instead. +/// directly instead. #[derive(Component, Clone, Copy, Debug, PartialEq, Deref)] pub struct EntityKind(pub azalea_registry::EntityKind); @@ -254,6 +307,8 @@ pub struct EntityBundle { pub position: Position, pub last_sent_position: LastSentPosition, pub physics: Physics, + pub direction: LookDirection, + pub eye_height: EyeHeight, pub attributes: Attributes, pub jumping: Jumping, } @@ -265,11 +320,12 @@ impl EntityBundle { kind: azalea_registry::EntityKind, world_name: ResourceLocation, ) -> Self { - // TODO: get correct entity dimensions by having them codegened somewhere + // TODO: get correct entity dimensions by having them codegen'd somewhere let dimensions = EntityDimensions { width: 0.6, height: 1.8, }; + let eye_height = dimensions.height * 0.85; Self { kind: EntityKind(kind), @@ -284,12 +340,6 @@ impl EntityBundle { yya: 0., zza: 0., - x_rot: 0., - y_rot: 0., - - y_rot_last: 0., - x_rot_last: 0., - on_ground: false, last_on_ground: false, @@ -299,6 +349,8 @@ impl EntityBundle { has_impulse: false, }, + eye_height: EyeHeight(eye_height), + direction: LookDirection::default(), attributes: Attributes { // TODO: do the correct defaults for everything, some |
