Skip to main content

steel_core/behavior/blocks/vegetation/
nether_wart.rs

1use std::sync::Arc;
2
3use steel_macros::block_behavior;
4use steel_registry::{
5    blocks::{
6        BlockRef,
7        block_state_ext::BlockStateExt,
8        properties::{BlockStateProperties, IntProperty},
9    },
10    item_stack::ItemStack,
11    vanilla_block_tags::BlockTag,
12    vanilla_items,
13};
14use steel_utils::{BlockPos, BlockStateId, types::UpdateFlags};
15
16use crate::{
17    behavior::{
18        BlockBehavior, BlockPlaceContext,
19        blocks::vegetation::{
20            Vegetation,
21            vegetation_block::{survival_update_shape, vegetation_can_survive},
22        },
23    },
24    world::{LevelReader, ScheduledTickAccess, World},
25};
26
27const AGE_PROPERTY: IntProperty = BlockStateProperties::AGE_3;
28
29/// Behavior for Nether Warts
30#[block_behavior]
31pub struct NetherWartBlock {
32    block: BlockRef,
33}
34
35impl NetherWartBlock {
36    /// Creates a new Nether Wart Block Behavior
37    #[must_use]
38    pub const fn new(block: BlockRef) -> Self {
39        Self { block }
40    }
41}
42
43impl BlockBehavior for NetherWartBlock {
44    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
45        if self.may_place_on(
46            context.world.get_block_state(context.place_pos().below()),
47            context.world,
48            context.place_pos().below(),
49        ) {
50            Some(self.block.default_state())
51        } else {
52            None
53        }
54    }
55
56    fn update_shape(
57        &self,
58        state: BlockStateId,
59        world: &dyn ScheduledTickAccess,
60        pos: BlockPos,
61        _direction: steel_utils::Direction,
62        _neighbor_pos: BlockPos,
63        _neighbor_state: BlockStateId,
64    ) -> BlockStateId {
65        survival_update_shape(self, state, world, pos)
66    }
67
68    fn can_survive(&self, state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
69        vegetation_can_survive(self, state, world, pos)
70    }
71
72    fn random_tick(&self, state: BlockStateId, world: &Arc<World>, pos: BlockPos) {
73        let age = state.get_value(&AGE_PROPERTY);
74        if age > 2 || rand::random_range(0..10) != 0 {
75            return;
76        }
77
78        world.set_block(
79            pos,
80            state.set_value(&AGE_PROPERTY, age + 1),
81            UpdateFlags::UPDATE_CLIENTS,
82        );
83    }
84
85    fn get_clone_item_stack(
86        &self,
87        _block: BlockRef,
88        _state: BlockStateId,
89        _include_data: bool,
90    ) -> Option<ItemStack> {
91        Some(ItemStack::new(&vanilla_items::NETHER_WART))
92    }
93}
94
95impl Vegetation for NetherWartBlock {
96    fn may_place_on(&self, state: BlockStateId, _world: &dyn LevelReader, _pos: BlockPos) -> bool {
97        state.get_block().has_tag(&BlockTag::SUPPORTS_NETHER_WART)
98    }
99}