fix: sweet berry bush collision (#1547)

* fix berry bush collision

* fix format

* fix fall distance

* rename function
This commit is contained in:
Mikhail Reznichenko
2026-02-13 13:57:51 +03:00
committed by GitHub
parent 528d5b3945
commit 0acb913775
3 changed files with 73 additions and 23 deletions

View File

@@ -1,22 +1,5 @@
use std::sync::Arc;
use pumpkin_data::{
Block,
block_properties::{BlockProperties, EnumVariants, Integer0To3, NetherWartLikeProperties},
damage::DamageType,
entity::EntityType,
item::Item,
tag::{self, Taggable},
};
use pumpkin_macros::pumpkin_block;
use pumpkin_util::math::position::BlockPos;
use pumpkin_world::{
BlockStateId,
item::ItemStack,
world::{BlockAccessor, BlockFlags},
};
use rand::RngExt;
use crate::{
block::{
BlockBehaviour, BlockFuture, CanPlaceAtArgs, GetStateForNeighborUpdateArgs, NormalUseArgs,
@@ -26,6 +9,23 @@ use crate::{
},
world::World,
};
use pumpkin_data::{
Block,
block_properties::{BlockProperties, EnumVariants, Integer0To3, NetherWartLikeProperties},
damage::DamageType,
entity::EntityType,
item::Item,
tag::{self, Taggable},
};
use pumpkin_macros::pumpkin_block;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_world::{
BlockStateId,
item::ItemStack,
world::{BlockAccessor, BlockFlags},
};
use rand::RngExt;
#[pumpkin_block("minecraft:sweet_berry_bush")]
pub struct SweetBerryBushBlock;
@@ -104,20 +104,32 @@ impl BlockBehaviour for SweetBerryBushBlock {
Box::pin(async move {
let entity = args.entity.get_entity();
if entity.entity_type == &EntityType::FOX || entity.entity_type == &EntityType::BEE {
let living_entity_opt = args.entity.get_living_entity();
if living_entity_opt.is_none()
|| entity.entity_type == &EntityType::FOX
|| entity.entity_type == &EntityType::BEE
{
return;
}
let living_entity = living_entity_opt.expect("Living entity should exist");
entity
.slow_movement(args.state, Vector3::new(0.8, 0.75, 0.8))
.await;
let mov = if living_entity.is_player() {
living_entity.get_movement()
} else {
entity.last_pos.load() - entity.pos.load()
};
let state_id = args.world.get_block_state_id(args.position).await;
let props = NetherWartLikeProperties::from_state_id(state_id, args.block);
if props.age == Integer0To3::L0 {
return;
}
let velocity = entity.velocity.load(); // FIXME: velocity != momentum/movement
if velocity.horizontal_length_squared() <= 0.0
|| (velocity.x.abs() < 0.003 && velocity.z.abs() < 0.003)
if mov.horizontal_length_squared() <= 0.0
|| (mov.x.abs() < 0.003 && mov.z.abs() < 0.003)
{
return;
}

View File

@@ -1142,6 +1142,15 @@ impl LivingEntity {
self.dead.store(false, Relaxed);
}
pub fn is_player(&self) -> bool {
let world = self.entity.world.load();
world.get_player_by_id(self.entity.entity_id).is_some()
}
pub fn get_movement(&self) -> Vector3<f64> {
self.entity.movement.load()
}
}
impl NBTStorage for LivingEntity {

View File

@@ -326,6 +326,8 @@ pub struct Entity {
pub pos: AtomicCell<Vector3<f64>>,
/// The last known position of the entity.
pub last_pos: AtomicCell<Vector3<f64>>,
/// The last movement vector
pub movement: AtomicCell<Vector3<f64>>,
/// The entity's position rounded to the nearest block coordinates
pub block_pos: AtomicCell<BlockPos>,
/// The block supporting the entity
@@ -443,6 +445,7 @@ impl Entity {
horizontal_collision: AtomicBool::new(false),
pos: AtomicCell::new(position),
last_pos: AtomicCell::new(position),
movement: AtomicCell::new(Vector3::default()),
block_pos: AtomicCell::new(BlockPos(Vector3::new(floor_x, floor_y, floor_z))),
supporting_block_pos: AtomicCell::new(None),
chunk_pos: AtomicCell::new(Vector2::new(
@@ -968,7 +971,7 @@ impl Entity {
pub fn update_last_pos(&self) -> Vector3<f64> {
let pos = self.pos.load();
let old = self.last_pos.load();
self.movement.store(pos - old);
self.last_pos.store(pos);
old
}
@@ -2074,6 +2077,31 @@ impl Entity {
self.extinguish();
self.set_on_fire(false).await;
}
pub async fn slow_movement(&self, state: &BlockState, multiplier: Vector3<f64>) {
match self.entity_type.id {
v if v == EntityType::PLAYER.id => {
if let Some(player_entity) = self.get_player()
&& player_entity.is_flying().await
{
return;
}
}
v if v == EntityType::SPIDER.id || v == EntityType::CAVE_SPIDER.id => {
if Block::from_state_id(state.id).id == Block::COBWEB.id {
return;
}
}
v if v == EntityType::WITHER.id => {
return;
}
_ => {}
}
if let Some(living) = self.get_living_entity() {
living.fall_distance.store(0f32);
}
self.movement_multiplier.store(multiplier);
}
}
impl NBTStorage for Entity {
@@ -2168,6 +2196,7 @@ impl EntityBase for Entity {
_server: &'a Server,
) -> EntityBaseFuture<'a, ()> {
Box::pin(async move {
self.update_last_pos();
self.tick_portal(&caller).await;
self.update_fluid_state(&caller).await;
self.check_out_of_world(&*caller).await;