Skip to main content

steel_core/behavior/blocks/vegetation/
wither_rose_block.rs

1use std::sync::Arc;
2use steel_macros::block_behavior;
3use steel_registry::vanilla_block_tags::BlockTag;
4use steel_registry::{vanilla_damage_types, vanilla_mob_effects};
5use steel_utils::types::Difficulty;
6use steel_utils::{BlockPos, BlockStateId, Direction};
7
8use crate::behavior::blocks::vegetation::vegetation_block::survival_update_shape;
9use crate::behavior::context::BlockPlaceContext;
10use crate::entity::damage::DamageSource;
11use crate::entity::{Entity, InsideBlockEffectCollector, MobEffectInstance};
12use crate::world::{LevelReader, ScheduledTickAccess};
13use crate::{behavior::block::BlockBehavior, world::World};
14
15use super::{BlockRef, default_surviving_state, survives_on_tag};
16
17/// Behavior for wither roses.
18#[block_behavior]
19pub struct WitherRoseBlock {
20    block: BlockRef,
21}
22
23impl WitherRoseBlock {
24    /// Creates a new wither rose block behavior.
25    #[must_use]
26    pub const fn new(block: BlockRef) -> Self {
27        Self { block }
28    }
29}
30
31impl BlockBehavior for WitherRoseBlock {
32    fn can_survive(&self, _state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
33        survives_on_tag(world, pos, &BlockTag::SUPPORTS_WITHER_ROSE)
34    }
35    fn update_shape(
36        &self,
37        state: BlockStateId,
38        world: &dyn ScheduledTickAccess,
39        pos: BlockPos,
40        _direction: Direction,
41        _neighbor_pos: BlockPos,
42        _neighbor_state: BlockStateId,
43    ) -> BlockStateId {
44        survival_update_shape(self, state, world, pos)
45    }
46    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
47        default_surviving_state(self.block, self, context)
48    }
49    fn entity_inside(
50        &self,
51        _state: BlockStateId,
52        world: &Arc<World>,
53        _pos: BlockPos,
54        entity: &dyn Entity,
55        _effect_collector: &mut InsideBlockEffectCollector,
56        _is_precise: bool,
57    ) {
58        if world.difficulty() == Difficulty::Peaceful {
59            return;
60        }
61        let Some(living_entity) = entity.as_living_entity() else {
62            return;
63        };
64        if living_entity.is_invulnerable_to(
65            world,
66            &DamageSource::environment(&vanilla_damage_types::WITHER),
67        ) {
68            return;
69        }
70        living_entity.add_mob_effect(MobEffectInstance::with_duration(
71            vanilla_mob_effects::WITHER,
72            40,
73            0,
74        ));
75    }
76}