steel_core/behavior/blocks/vegetation/
grass_block.rs1use steel_macros::block_behavior;
2use steel_registry::blocks::BlockRef;
3use steel_registry::vanilla_blocks;
4use steel_utils::{BlockPos, BlockStateId, Direction};
5
6use super::snowy_block::{snowy_placement_state, update_snowy_shape};
7use super::spreading_grass_block::SpreadingGrassBlock;
8use crate::behavior::block::BlockBehavior;
9use crate::behavior::context::BlockPlaceContext;
10use crate::world::{ScheduledTickAccess, World};
11use std::sync::Arc;
12
13#[block_behavior]
16pub struct GrassBlock {
17 block: BlockRef,
18}
19
20impl GrassBlock {
21 #[must_use]
23 pub const fn new(block: BlockRef) -> Self {
24 Self { block }
25 }
26}
27
28impl BlockBehavior for GrassBlock {
29 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
30 Some(snowy_placement_state(self.block, context))
31 }
32
33 fn update_shape(
34 &self,
35 state: BlockStateId,
36 _world: &dyn ScheduledTickAccess,
37 _pos: BlockPos,
38 direction: Direction,
39 _neighbor_pos: BlockPos,
40 neighbor_state: BlockStateId,
41 ) -> BlockStateId {
42 update_snowy_shape(state, direction, neighbor_state)
43 }
44
45 fn random_tick(&self, state: BlockStateId, world: &Arc<World>, pos: BlockPos) {
46 SpreadingGrassBlock::random_tick(
47 &vanilla_blocks::GRASS_BLOCK,
48 &vanilla_blocks::DIRT,
49 state,
50 world,
51 pos,
52 );
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use steel_registry::blocks::block_state_ext::BlockStateExt;
59 use steel_registry::blocks::properties::BlockStateProperties;
60 use steel_registry::{init_vanilla_registry, vanilla_blocks};
61 use steel_utils::{BlockPos, Direction};
62
63 use super::*;
64 use crate::behavior::init_behaviors;
65 use crate::test_support::TestLevel;
66
67 #[test]
68 fn grass_block_updates_snowy_state() {
69 init_vanilla_registry();
70 init_behaviors();
71
72 let level = TestLevel::default();
73 let pos = BlockPos::new(0, 64, 0);
74 let behavior = GrassBlock::new(&vanilla_blocks::GRASS_BLOCK);
75
76 let non_snowy = vanilla_blocks::GRASS_BLOCK.default_state();
77 let snowy = behavior.update_shape(
78 non_snowy,
79 &level,
80 pos,
81 Direction::Up,
82 pos.above(),
83 vanilla_blocks::SNOW.default_state(),
84 );
85 assert!(snowy.get_value(&BlockStateProperties::SNOWY));
86
87 let cleared = behavior.update_shape(
88 snowy,
89 &level,
90 pos,
91 Direction::Up,
92 pos.above(),
93 vanilla_blocks::AIR.default_state(),
94 );
95 assert!(!cleared.get_value(&BlockStateProperties::SNOWY));
96 }
97}