Improve fall damage calculation

This commit is contained in:
Alexander Medvedev
2025-01-27 23:51:38 +01:00
parent deda78231a
commit dbbf745da2
3 changed files with 41 additions and 40 deletions

View File

@@ -24,7 +24,7 @@ pub struct LivingEntity {
/// The current health level of the entity.
pub health: AtomicCell<f32>,
/// The distance the entity has been falling
pub fall_distance: AtomicCell<f64>,
pub fall_distance: AtomicCell<f32>,
}
impl LivingEntity {
pub const fn new(entity: Entity) -> Self {
@@ -113,25 +113,21 @@ impl LivingEntity {
amount > 0.0
}
pub async fn update_fall_distance(&self, dont_damage: bool) {
let y = self.entity.pos.load().y;
let last_y = self.last_pos.load().y;
let grounded = self
.entity
.on_ground
.load(std::sync::atomic::Ordering::Relaxed);
// + => falling, - => up
let y_diff = last_y - y;
if grounded {
pub async fn update_fall_distance(
&self,
height_difference: f64,
ground: bool,
dont_damage: bool,
) {
if ground {
let fall_distance = self.fall_distance.swap(0.0);
if dont_damage {
if fall_distance <= 0.0 || dont_damage {
return;
}
let mut damage = (fall_distance - 3.0).max(0.0) as f32;
damage = (damage * 2.0).round() / 2.0;
let safe_fall_distance = 3.0;
let mut damage = fall_distance - safe_fall_distance;
damage = (damage).round();
if !self.check_damage(damage) {
return;
}
@@ -141,11 +137,10 @@ impl LivingEntity {
.await;
// TODO: Play block fall sound
self.damage(damage, 10).await; // Fall
} else if y_diff < 0.0 {
self.fall_distance.store(0.0);
} else {
let fall_distance = self.fall_distance.load();
self.fall_distance.store(fall_distance + y_diff);
} else if height_difference < 0.0 {
let distance = self.fall_distance.load();
self.fall_distance
.store(distance - (height_difference as f32));
}
}

View File

@@ -148,17 +148,15 @@ impl Player {
Self::clamp_horizontal(position.z),
);
let entity = &self.living_entity.entity;
let last_pos = entity.pos.load();
self.living_entity.set_pos(position);
let pos = entity.pos.load();
let last_pos = self.living_entity.last_pos.load();
entity
.on_ground
.store(packet.ground, std::sync::atomic::Ordering::Relaxed);
let entity_id = entity.entity_id;
let Vector3 { x, y, z } = pos;
let Vector3 { x, y, z } = position;
let world = &entity.world;
// let delta = Vector3::new(x - lastx, y - lasty, z - lastz);
@@ -188,6 +186,16 @@ impl Player {
),
)
.await;
if !self.abilities.lock().await.flying {
let height_difference = position.y - last_pos.y;
self.living_entity
.update_fall_distance(
height_difference,
packet.ground,
self.gamemode.load() == GameMode::Creative,
)
.await;
}
player_chunker::update_position(self).await;
}
@@ -217,11 +225,9 @@ impl Player {
Self::clamp_horizontal(position.z),
);
let entity = &self.living_entity.entity;
let last_pos = entity.pos.load();
self.living_entity.set_pos(position);
let pos = entity.pos.load();
let last_pos = self.living_entity.last_pos.load();
entity
.on_ground
.store(packet.ground, std::sync::atomic::Ordering::Relaxed);
@@ -232,7 +238,7 @@ impl Player {
);
let entity_id = entity.entity_id;
let Vector3 { x, y, z } = pos;
let Vector3 { x, y, z } = position;
let yaw = (entity.yaw.load() * 256.0 / 360.0).rem_euclid(256.0);
let pitch = (entity.pitch.load() * 256.0 / 360.0).rem_euclid(256.0);
@@ -275,6 +281,16 @@ impl Player {
&CHeadRot::new(entity_id.into(), yaw as u8),
)
.await;
if !self.abilities.lock().await.flying {
let height_difference = position.y - last_pos.y;
self.living_entity
.update_fall_distance(
height_difference,
packet.ground,
self.gamemode.load() == GameMode::Creative,
)
.await;
}
player_chunker::update_position(self).await;
}

View File

@@ -2,10 +2,7 @@ use std::{num::NonZeroU8, sync::Arc};
use pumpkin_config::BASIC_CONFIG;
use pumpkin_protocol::client::play::{CCenterChunk, CUnloadChunk};
use pumpkin_util::{
math::{get_section_cord, position::BlockPos, vector3::Vector3},
GameMode,
};
use pumpkin_util::math::{get_section_cord, position::BlockPos, vector3::Vector3};
use pumpkin_world::cylindrical_chunk_iterator::Cylindrical;
use crate::entity::player::Player;
@@ -40,13 +37,6 @@ pub async fn player_join(player: &Arc<Player>) {
}
pub async fn update_position(player: &Arc<Player>) {
if !player.abilities.lock().await.flying {
player
.living_entity
.update_fall_distance(player.gamemode.load() == GameMode::Creative)
.await;
}
let entity = &player.living_entity.entity;
let view_distance = get_view_distance(player).await;