Alexander Medvedev 2026-01-15 17:47:30 +01:00
parent 2faf24bb42
commit 0ef17af5d0
7 changed files with 62 additions and 26 deletions

View File

@ -61,6 +61,14 @@ impl BoundingBox {
} }
} }
pub fn expand_all(&self, value: f64) -> Self {
self.expand(value, value, value)
}
pub fn contract_all(&self, value: f64) -> Self {
self.expand_all(-value)
}
pub fn offset(&self, other: Self) -> Self { pub fn offset(&self, other: Self) -> Self {
Self { Self {
min: self.min.add(&other.min), min: self.min.add(&other.min),
@ -207,4 +215,15 @@ impl BoundingBox {
pub struct EntityDimensions { pub struct EntityDimensions {
pub width: f32, pub width: f32,
pub height: f32, pub height: f32,
pub eye_height: f32,
}
impl EntityDimensions {
pub fn new(width: f32, height: f32, eye_height: f32) -> Self {
Self {
width,
height,
eye_height,
}
}
} }

View File

@ -113,6 +113,7 @@ impl BlockEntity for MobSpawnerBlockEntity {
&EntityDimensions { &EntityDimensions {
width: entity_type.dimension[0], width: entity_type.dimension[0],
height: entity_type.dimension[1], height: entity_type.dimension[1],
eye_height: entity_type.eye_height,
}, },
)) ))
.await .await

View File

@ -638,7 +638,7 @@ impl LivingEntity {
} }
pub fn get_swim_height(&self) -> f64 { pub fn get_swim_height(&self) -> f64 {
let eye_height = self.entity.standing_eye_height; let eye_height = self.entity.entity_dimension.load().eye_height;
if self.entity.entity_type == &EntityType::BREEZE { if self.entity.entity_type == &EntityType::BREEZE {
f64::from(eye_height) f64::from(eye_height)

View File

@ -321,14 +321,12 @@ pub struct Entity {
pub body_yaw: AtomicCell<f32>, pub body_yaw: AtomicCell<f32>,
/// The entity's pitch rotation (vertical rotation) ↑ ↓ /// The entity's pitch rotation (vertical rotation) ↑ ↓
pub pitch: AtomicCell<f32>, pub pitch: AtomicCell<f32>,
/// The height of the entity's eyes from the ground.
pub standing_eye_height: f32,
/// The entity's current pose (e.g., standing, sitting, swimming). /// The entity's current pose (e.g., standing, sitting, swimming).
pub pose: AtomicCell<EntityPose>, pub pose: AtomicCell<EntityPose>,
/// The bounding box of an entity (hitbox) /// The bounding box of an entity (hitbox)
pub bounding_box: AtomicCell<BoundingBox>, pub bounding_box: AtomicCell<BoundingBox>,
///The size (width and height) of the bounding box ///The size (width and height) of the bounding box
pub bounding_box_size: AtomicCell<EntityDimensions>, pub entity_dimension: AtomicCell<EntityDimensions>,
/// Whether this entity is invulnerable to all damage /// Whether this entity is invulnerable to all damage
pub invulnerable: AtomicBool, pub invulnerable: AtomicBool,
/// List of damage types this entity is immune to /// List of damage types this entity is immune to
@ -378,6 +376,7 @@ impl Entity {
let bounding_box_size = EntityDimensions { let bounding_box_size = EntityDimensions {
width: entity_type.dimension[0], width: entity_type.dimension[0],
height: entity_type.dimension[1], height: entity_type.dimension[1],
eye_height: entity_type.eye_height,
}; };
Self { Self {
@ -408,7 +407,6 @@ impl Entity {
body_yaw: AtomicCell::new(0.0), body_yaw: AtomicCell::new(0.0),
pitch: AtomicCell::new(0.0), pitch: AtomicCell::new(0.0),
velocity: AtomicCell::new(Vector3::new(0.0, 0.0, 0.0)), velocity: AtomicCell::new(Vector3::new(0.0, 0.0, 0.0)),
standing_eye_height: entity_type.eye_height,
pose: AtomicCell::new(EntityPose::Standing), pose: AtomicCell::new(EntityPose::Standing),
first_loaded_chunk_position: AtomicCell::new(None), first_loaded_chunk_position: AtomicCell::new(None),
bounding_box: AtomicCell::new(BoundingBox::new_from_pos( bounding_box: AtomicCell::new(BoundingBox::new_from_pos(
@ -417,7 +415,7 @@ impl Entity {
position.z, position.z,
&bounding_box_size, &bounding_box_size,
)), )),
bounding_box_size: AtomicCell::new(bounding_box_size), entity_dimension: AtomicCell::new(bounding_box_size),
invulnerable: AtomicBool::new(invulnerable), invulnerable: AtomicBool::new(invulnerable),
damage_immunities: Vec::new(), damage_immunities: Vec::new(),
data: AtomicI32::new(0), data: AtomicI32::new(0),
@ -460,6 +458,19 @@ impl Entity {
.await; .await;
} }
#[must_use]
pub fn get_entity_dimensions(pose: EntityPose) -> EntityDimensions {
match pose {
EntityPose::Sleeping => EntityDimensions::new(0.2, 0.2, 0.2),
EntityPose::FallFlying | EntityPose::Swimming | EntityPose::SpinAttack => {
EntityDimensions::new(0.6, 0.6, 0.4)
}
EntityPose::Crouching => EntityDimensions::new(0.6, 1.5, 1.27),
EntityPose::Dying => EntityDimensions::new(0.2, 0.2, 1.62),
_ => EntityDimensions::new(0.6, 1.8, 1.62),
}
}
/// Updates the entity's position, block position, and chunk position. /// Updates the entity's position, block position, and chunk position.
/// ///
/// This function calculates the new position, block position, and chunk position based on the provided coordinates. If any of these values change, the corresponding fields are updated. /// This function calculates the new position, block position, and chunk position based on the provided coordinates. If any of these values change, the corresponding fields are updated.
@ -471,7 +482,7 @@ impl Entity {
new_position.x, new_position.x,
new_position.y, new_position.y,
new_position.z, new_position.z,
&self.bounding_box_size.load(), &self.entity_dimension.load(),
)); ));
let floor_x = new_position.x.floor() as i32; let floor_x = new_position.x.floor() as i32;
@ -806,7 +817,7 @@ impl Entity {
let mut eye_level_box = aabb; let mut eye_level_box = aabb;
let eye_height = f64::from(self.standing_eye_height); let eye_height = f64::from(self.entity_dimension.load().eye_height);
eye_level_box.min.y += eye_height; eye_level_box.min.y += eye_height;
@ -1400,11 +1411,11 @@ impl Entity {
) )
} }
pub fn width(&self) -> f32 { pub fn width(&self) -> f32 {
self.bounding_box_size.load().width self.entity_dimension.load().width
} }
pub fn height(&self) -> f32 { pub fn height(&self) -> f32 {
self.bounding_box_size.load().height self.entity_dimension.load().height
} }
/// Applies knockback to the entity, following vanilla Minecraft's mechanics. /// Applies knockback to the entity, following vanilla Minecraft's mechanics.
@ -1634,7 +1645,14 @@ impl Entity {
} }
pub async fn set_pose(&self, pose: EntityPose) { pub async fn set_pose(&self, pose: EntityPose) {
let dimension = Self::get_entity_dimensions(pose);
let position = self.pos.load();
let aabb = BoundingBox::new_from_pos(position.x, position.y, position.z, &dimension);
if self.world.is_space_empty(aabb.contract_all(1.0E-7)).await {
self.pose.store(pose); self.pose.store(pose);
let dimension = Self::get_entity_dimensions(pose);
self.bounding_box.store(aabb);
self.entity_dimension.store(dimension);
let pose = pose as i32; let pose = pose as i32;
self.send_meta_data(&[Metadata::new( self.send_meta_data(&[Metadata::new(
TrackedData::DATA_POSE, TrackedData::DATA_POSE,
@ -1643,6 +1661,7 @@ impl Entity {
)]) )])
.await; .await;
} }
}
pub fn is_invulnerable_to(&self, damage_type: &DamageType) -> bool { pub fn is_invulnerable_to(&self, damage_type: &DamageType) -> bool {
*damage_type != DamageType::GENERIC_KILL *damage_type != DamageType::GENERIC_KILL
@ -1735,7 +1754,7 @@ impl Entity {
} }
pub fn get_eye_y(&self) -> f64 { pub fn get_eye_y(&self) -> f64 {
self.pos.load().y + f64::from(self.standing_eye_height) self.pos.load().y + f64::from(self.entity_dimension.load().eye_height)
} }
pub fn is_removed(&self) -> bool { pub fn is_removed(&self) -> bool {

View File

@ -1081,11 +1081,7 @@ impl Player {
} }
pub fn eye_position(&self) -> Vector3<f64> { pub fn eye_position(&self) -> Vector3<f64> {
let eye_height = if self.living_entity.entity.pose.load() == EntityPose::Crouching { let eye_height = f64::from(self.living_entity.entity.entity_dimension.load().eye_height);
1.27
} else {
f64::from(self.living_entity.entity.standing_eye_height)
};
Vector3::new( Vector3::new(
self.living_entity.entity.pos.load().x, self.living_entity.entity.pos.load().x,
self.living_entity.entity.pos.load().y + eye_height, self.living_entity.entity.pos.load().y + eye_height,
@ -1388,7 +1384,7 @@ impl Player {
let d = self.block_interaction_range() + additional_range; let d = self.block_interaction_range() + additional_range;
let box_pos = BoundingBox::from_block(position); let box_pos = BoundingBox::from_block(position);
let entity_pos = self.living_entity.entity.pos.load(); let entity_pos = self.living_entity.entity.pos.load();
let standing_eye_height = self.living_entity.entity.standing_eye_height; let standing_eye_height = self.living_entity.entity.entity_dimension.load().eye_height;
box_pos.squared_magnitude(Vector3 { box_pos.squared_magnitude(Vector3 {
x: entity_pos.x, x: entity_pos.x,
y: entity_pos.y + f64::from(standing_eye_height), y: entity_pos.y + f64::from(standing_eye_height),

View File

@ -16,7 +16,7 @@ pub struct ThrownItemEntity {
impl ThrownItemEntity { impl ThrownItemEntity {
pub fn new(entity: Entity, owner: &Entity) -> Self { pub fn new(entity: Entity, owner: &Entity) -> Self {
let mut owner_pos = owner.pos.load(); let mut owner_pos = owner.pos.load();
owner_pos.y = (owner_pos.y + f64::from(owner.standing_eye_height)) - 0.1; owner_pos.y = (owner_pos.y + f64::from(owner.entity_dimension.load().eye_height)) - 0.1;
entity.pos.store(owner_pos); entity.pos.store(owner_pos);
Self { entity } Self { entity }
} }

View File

@ -567,6 +567,7 @@ pub async fn is_valid_spawn_position_for_type(
&EntityDimensions { &EntityDimensions {
width: entity_type.dimension[0], width: entity_type.dimension[0],
height: entity_type.dimension[1], height: entity_type.dimension[1],
eye_height: entity_type.eye_height,
}, },
)) ))
.await .await