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    block_entity::SharedBlockEntity,
25    world::{LevelReader, ScheduledTickAccess, World},
26};
27
28const AGE: &IntProperty = &BlockStateProperties::AGE_3;
29
30/// Behavior for Nether Warts
31#[block_behavior]
32pub struct NetherWartBlock {
33    block: BlockRef,
34}
35
36impl NetherWartBlock {
37    /// Creates a new Nether Wart Block Behavior
38    #[must_use]
39    pub const fn new(block: BlockRef) -> Self {
40        Self { block }
41    }
42}
43
44impl BlockBehavior for NetherWartBlock {
45    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
46        if self.may_place_on(
47            context.world.get_block_state(context.place_pos().below()),
48            context.world,
49            context.place_pos().below(),
50        ) {
51            Some(self.block.default_state())
52        } else {
53            None
54        }
55    }
56
57    fn update_shape(
58        &self,
59        state: BlockStateId,
60        world: &dyn ScheduledTickAccess,
61        pos: BlockPos,
62        _direction: steel_utils::Direction,
63        _neighbor_pos: BlockPos,
64        _neighbor_state: BlockStateId,
65    ) -> BlockStateId {
66        survival_update_shape(self, state, world, pos)
67    }
68
69    fn can_survive(&self, state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
70        vegetation_can_survive(self, state, world, pos)
71    }
72
73    fn random_tick(&self, state: BlockStateId, world: &Arc<World>, pos: BlockPos) {
74        let age = state.get_value(AGE);
75        if age >= AGE.max || rand::random_range(0..10) != 0 {
76            return;
77        }
78
79        world.set_block(
80            pos,
81            state.set_value(AGE, age + 1),
82            UpdateFlags::UPDATE_CLIENTS,
83        );
84    }
85
86    fn get_clone_item_stack(
87        &self,
88        _block: BlockRef,
89        _state: BlockStateId,
90        _block_entity: Option<SharedBlockEntity>,
91        _include_data: bool,
92    ) -> Option<ItemStack> {
93        Some(ItemStack::new(&vanilla_items::NETHER_WART))
94    }
95}
96
97impl Vegetation for NetherWartBlock {
98    fn may_place_on(&self, state: BlockStateId, _world: &dyn LevelReader, _pos: BlockPos) -> bool {
99        state.get_block().has_tag(&BlockTag::SUPPORTS_NETHER_WART)
100    }
101}