Skip to main content

steel_core/behavior/blocks/building/
hay_block.rs

1use std::sync::Arc;
2
3use steel_macros::block_behavior;
4use steel_registry::blocks::BlockRef;
5use steel_registry::vanilla_damage_types;
6use steel_utils::{BlockPos, BlockStateId};
7
8use crate::{
9    behavior::{
10        BlockBehavior, BlockPlaceContext, EntityFallDamage, EntityFallOnContext,
11        blocks::RotatedPillarBlock,
12    },
13    world::World,
14};
15
16use crate::entity::damage::DamageSource;
17
18/// Behavior for hay blocks.
19#[block_behavior]
20pub struct HayBlock {
21    block: BlockRef,
22}
23
24impl HayBlock {
25    /// Creates a hay block behavior.
26    #[must_use]
27    pub const fn new(block: BlockRef) -> Self {
28        Self { block }
29    }
30
31    #[must_use]
32    fn fall_damage(fall_distance: f64) -> EntityFallDamage {
33        EntityFallDamage::new(
34            fall_distance,
35            0.2,
36            DamageSource::environment(&vanilla_damage_types::FALL),
37        )
38    }
39}
40
41impl BlockBehavior for HayBlock {
42    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
43        Some(RotatedPillarBlock::placement_state(self.block, context))
44    }
45
46    fn fall_on(
47        &self,
48        _state: BlockStateId,
49        _world: &Arc<World>,
50        _pos: BlockPos,
51        context: EntityFallOnContext<'_>,
52    ) -> Option<EntityFallDamage> {
53        Some(Self::fall_damage(context.fall_distance))
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn hay_reduces_fall_damage_like_vanilla() {
63        let fall_damage = HayBlock::fall_damage(12.0);
64
65        assert!((fall_damage.fall_distance - 12.0).abs() < f64::EPSILON);
66        assert!((fall_damage.damage_modifier - 0.2).abs() < f32::EPSILON);
67    }
68}