steel_core/behavior/blocks/vegetation/
nether_wart.rs1use 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#[block_behavior]
32pub struct NetherWartBlock {
33 block: BlockRef,
34}
35
36impl NetherWartBlock {
37 #[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}