steel_core/behavior/blocks/vegetation/
flower_bed_block.rs1use crate::behavior::BlockPlaceContext;
2use crate::behavior::blocks::vegetation::segmentable_block::{
3 segmentable_can_be_replaced, segmentable_get_state_for_placement,
4};
5use crate::world::{ScheduledTickAccess, World};
6use rand::prelude::Rng;
7use std::sync::Arc;
8use steel_macros::block_behavior;
9use steel_registry::REGISTRY;
10use steel_registry::blocks::{
11 block_state_ext::BlockStateExt,
12 properties::{BlockStateProperties, IntProperty},
13};
14use steel_registry::item_stack::ItemStack;
15use steel_registry::vanilla_block_tags::BlockTag;
16use steel_utils::{BlockPos, BlockStateId, Direction, types::UpdateFlags};
17
18use crate::behavior::block::BlockBehavior;
19use crate::behavior::blocks::vegetation::bonemealable::Bonemealable;
20use crate::world::LevelReader;
21
22use super::{BlockRef, survives_on_tag, vegetation_block::survival_update_shape};
23
24const SEGMENT_PROPERTY: IntProperty = BlockStateProperties::FLOWER_AMOUNT;
25
26#[block_behavior]
28pub struct FlowerBedBlock {
29 block: BlockRef,
30}
31
32impl FlowerBedBlock {
33 #[must_use]
35 pub const fn new(block: BlockRef) -> Self {
36 Self { block }
37 }
38}
39
40impl BlockBehavior for FlowerBedBlock {
41 fn can_survive(&self, _state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
42 survives_on_tag(world, pos, &BlockTag::SUPPORTS_VEGETATION)
43 }
44
45 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
46 Some(segmentable_get_state_for_placement(
47 self.block,
48 &SEGMENT_PROPERTY,
49 context,
50 ))
51 }
52
53 fn can_be_replaced(&self, state: BlockStateId, context: &BlockPlaceContext<'_>) -> bool {
54 segmentable_can_be_replaced(&SEGMENT_PROPERTY, state, context)
55 }
56
57 fn update_shape(
58 &self,
59 state: BlockStateId,
60 world: &dyn ScheduledTickAccess,
61 pos: BlockPos,
62 _direction: Direction,
63 _neighbor_pos: BlockPos,
64 _neighbor_state: BlockStateId,
65 ) -> BlockStateId {
66 survival_update_shape(self, state, world, pos)
67 }
68
69 fn as_bonemealable(&self) -> Option<&dyn Bonemealable> {
70 Some(self)
71 }
72}
73
74impl Bonemealable for FlowerBedBlock {
75 fn is_valid_bonemeal_target(
76 &self,
77 _state: BlockStateId,
78 _world: &dyn LevelReader,
79 _pos: BlockPos,
80 ) -> bool {
81 true
82 }
83
84 fn perform_bonemeal(
85 &self,
86 state: BlockStateId,
87 world: &Arc<World>,
88 _rng: &mut dyn Rng,
89 pos: BlockPos,
90 ) {
91 let amount = state.get_value(&SEGMENT_PROPERTY);
92 if amount < 4 {
93 world.set_block(
94 pos,
95 state.set_value(&SEGMENT_PROPERTY, amount + 1),
96 UpdateFlags::UPDATE_CLIENTS,
97 );
98 } else {
99 world.pop_resource(pos, ItemStack::new(REGISTRY.items.by_block(self.block)));
100 }
101 }
102}