fix: make item drops fall smooth

This commit is contained in:
Alexander Medvedev 2026-01-15 20:29:30 +01:00
parent 0ef17af5d0
commit db486d5572
19 changed files with 43 additions and 40 deletions

View File

@ -7,7 +7,7 @@ pub(crate) fn build() -> TokenStream {
println!("cargo:rerun-if-changed=../assets/tracked_data.json");
let mut handlers: Vec<(String, u8)> =
serde_json::from_str::<std::collections::HashMap<String, u8>>(
serde_json::from_str::<std::collections::BTreeMap<String, u8>>(
&fs::read_to_string("../assets/tracked_data.json").unwrap(),
)
.expect("Failed to parse tracked_data.json")

View File

@ -22,7 +22,7 @@ fn abs_max(a: f64, b: f64) -> f64 {
}
fn to_long(value: f64) -> i64 {
((value * 0.5 + 0.5) * MAX_15_BIT_VALUE).round() as i64
(((value * 0.5 + 0.5) * MAX_15_BIT_VALUE).round() as i64).clamp(0, 32766)
}
impl Serialize for Velocity {

View File

@ -1624,7 +1624,7 @@ impl GenerationSchedule {
level: Arc<Level>,
lock: IOLock,
) {
log::info!("io read thread start");
log::debug!("io read thread start");
use crate::biome::hash_seed;
let biome_mixer_seed = hash_seed(level.world_gen.random_config.seed);
let dimension = &level.world_gen.dimension;
@ -1687,7 +1687,7 @@ impl GenerationSchedule {
break;
}
}
log::info!("io read thread stop");
log::debug!("io read thread stop");
}
async fn io_write_work(recv: AsyncRx<Vec<(ChunkPos, Chunk)>>, level: Arc<Level>, lock: IOLock) {

View File

@ -309,7 +309,7 @@ impl Level {
};
for handle in handles {
log::info!(
log::debug!(
"Waiting for thread {:?} ({}) to stop",
handle.thread().id(),
handle.thread().name().unwrap_or("unknown")

View File

@ -1,6 +1,6 @@
use super::{Controls, Goal, to_goal_ticks};
use crate::entity::ai::goal::GoalFuture;
use crate::entity::ai::goal::track_target_goal::TrackTargetGoal;
use crate::entity::ai::goal::track_target::TrackTargetGoal;
use crate::entity::ai::target_predicate::TargetPredicate;
use crate::entity::living::LivingEntity;
use crate::entity::mob::Mob;

View File

@ -1,16 +1,16 @@
use crate::entity::mob::Mob;
use std::{any::TypeId, ops::BitOr, pin::Pin, ptr};
pub mod active_target_goal;
pub mod ambient_stand_goal;
pub mod active_target;
pub mod ambient_stand;
pub mod goal_selector;
pub mod look_around_goal;
pub mod look_around;
pub mod look_at_entity;
mod melee_attack_goal;
pub mod move_to_target_pos_goal;
pub mod step_and_destroy_block_goal;
mod track_target_goal;
pub mod zombie_attack_goal;
mod melee_attack;
pub mod move_to_target_pos;
pub mod step_and_destroy_block;
mod track_target;
pub mod zombie_attack;
#[must_use]
pub fn to_goal_ticks(server_ticks: i32) -> i32 {

View File

@ -1,5 +1,5 @@
use super::{Controls, Goal, to_goal_ticks};
use crate::entity::ai::goal::move_to_target_pos_goal::{MoveToTargetPos, MoveToTargetPosGoal};
use crate::entity::ai::goal::move_to_target_pos::{MoveToTargetPos, MoveToTargetPosGoal};
use crate::entity::ai::goal::{GoalFuture, ParentHandle};
use crate::entity::mob::Mob;
use crate::world::World;

View File

@ -45,7 +45,7 @@ impl TrackTargetGoal {
// TODO: get from entity attribute
pub fn get_follow_range(_mob: &MobEntity) -> f32 {
1.0
32.0
}
fn can_navigate_to_entity(&mut self, mob: &dyn Mob, _target: &LivingEntity) -> bool {

View File

@ -1,6 +1,6 @@
use super::{Controls, Goal};
use crate::entity::ai::goal::GoalFuture;
use crate::entity::ai::goal::melee_attack_goal::MeleeAttackGoal;
use crate::entity::ai::goal::melee_attack::MeleeAttackGoal;
use crate::entity::mob::Mob;
pub struct ZombieAttackGoal {

View File

@ -324,18 +324,9 @@ impl EntityBase for ItemEntity {
entity.update_fluid_state(&caller).await;
let velocity_dirty = entity.velocity_dirty.swap(false, Ordering::SeqCst)
|| entity.touching_water.load(Ordering::SeqCst)
|| entity.touching_lava.load(Ordering::SeqCst)
//|| entity.velocity.load().sub(&original_velo).length_squared() > 0.01;
|| entity.velocity.load() != original_velo;
|| entity.velocity.load().sub(&original_velo).length_squared() > 0.01;
if velocity_dirty {
entity.send_pos_rot().await;

View File

@ -1077,6 +1077,14 @@ impl EntityBase for LivingEntity {
})
}
fn tick_in_void<'a>(&'a self, dyn_self: &'a dyn EntityBase) -> EntityBaseFuture<'a, ()> {
Box::pin(async move {
dyn_self
.damage(dyn_self, 4.0, DamageType::OUT_OF_WORLD)
.await;
})
}
fn get_gravity(&self) -> f64 {
const GRAVITY: f64 = 0.08;
GRAVITY

View File

@ -5,7 +5,7 @@ use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target_goal::ActiveTargetGoal, look_around_goal::LookAroundGoal,
active_target::ActiveTargetGoal, look_around::LookAroundGoal,
look_at_entity::LookAtEntityGoal,
},
mob::{Mob, MobEntity},

View File

@ -1,14 +1,14 @@
use super::{Mob, MobEntity};
use crate::entity::ai::goal::look_around_goal::LookAroundGoal;
use crate::entity::ai::goal::move_to_target_pos_goal::MoveToTargetPos;
use crate::entity::ai::goal::step_and_destroy_block_goal::{
use crate::entity::ai::goal::look_around::LookAroundGoal;
use crate::entity::ai::goal::move_to_target_pos::MoveToTargetPos;
use crate::entity::ai::goal::step_and_destroy_block::{
StepAndDestroyBlockGoal, Stepping, SteppingFuture,
};
use crate::entity::ai::goal::zombie_attack_goal::ZombieAttackGoal;
use crate::entity::ai::goal::zombie_attack::ZombieAttackGoal;
use crate::entity::ai::goal::{Controls, Goal, GoalFuture, ParentHandle};
use crate::entity::{
Entity, NBTStorage,
ai::goal::{active_target_goal::ActiveTargetGoal, look_at_entity::LookAtEntityGoal},
ai::goal::{active_target::ActiveTargetGoal, look_at_entity::LookAtEntityGoal},
};
use crate::world::World;
use pumpkin_data::Block;

View File

@ -126,6 +126,10 @@ pub trait EntityBase: Send + Sync + NBTStorage {
0.0
}
fn tick_in_void<'a>(&'a self, _dyn_self: &'a dyn EntityBase) -> EntityBaseFuture<'a, ()> {
Box::pin(async move { self.get_entity().remove().await })
}
/// Returns if damage was successful or not
fn damage<'a>(
&'a self,
@ -1776,10 +1780,7 @@ impl Entity {
pub async fn check_out_of_world(&self, dyn_self: &dyn EntityBase) {
if self.pos.load().y < f64::from(self.world.dimension.min_y) - 64.0 {
// Tick out of world damage
dyn_self
.damage(dyn_self, 4.0, DamageType::OUT_OF_WORLD)
.await;
dyn_self.tick_in_void(dyn_self).await;
}
}

View File

@ -7,7 +7,9 @@ use uuid::Uuid;
use crate::{
entity::{
Entity, EntityBase,
decoration::{end_crystal::EndCrystalEntity, painting::PaintingEntity},
decoration::{
armor_stand::ArmorStandEntity, end_crystal::EndCrystalEntity, painting::PaintingEntity,
},
living::LivingEntity,
mob::{drowned::DrownedEntity, zombie::ZombieEntity},
},
@ -25,6 +27,7 @@ pub async fn from_type(
let mob: Arc<dyn EntityBase> = match entity_type.id {
id if id == EntityType::ZOMBIE.id => ZombieEntity::make(entity).await,
id if id == EntityType::DROWNED.id => DrownedEntity::make(entity).await,
id if id == EntityType::ARMOR_STAND.id => Arc::new(ArmorStandEntity::new(entity)),
id if id == EntityType::PAINTING.id => Arc::new(PaintingEntity::new(entity)),
id if id == EntityType::END_CRYSTAL.id => Arc::new(EndCrystalEntity::new(entity)),
// Fallback Entity