steel_core/behavior/blocks/vegetation/
lily_pad_block.rs1use std::sync::Arc;
2
3use steel_macros::block_behavior;
4use steel_registry::blocks::block_state_ext::BlockStateExt;
5use steel_registry::vanilla_block_tags::BlockTag;
6use steel_registry::vanilla_fluid_tags::FluidTag;
7use steel_utils::{BlockPos, BlockStateId, Direction};
8
9use crate::behavior::block::BlockBehavior;
10use crate::behavior::blocks::vegetation::vegetation_block::survival_update_shape;
11use crate::behavior::context::BlockPlaceContext;
12use crate::entity::{Entity, InsideBlockEffectCollector};
13use crate::fluid::get_fluid_state_from_block;
14use crate::world::{LevelReader, ScheduledTickAccess, World};
15
16use super::BlockRef;
17
18#[block_behavior]
20pub struct LilyPadBlock {
21 block: BlockRef,
22}
23
24impl LilyPadBlock {
25 #[must_use]
27 pub const fn new(block: BlockRef) -> Self {
28 Self { block }
29 }
30
31 fn may_place_on(world: &dyn LevelReader, pos: BlockPos) -> bool {
32 let below = world.get_block_state(pos);
33 let below_fluid = get_fluid_state_from_block(below);
34 let above_fluid = get_fluid_state_from_block(world.get_block_state(pos.above()));
35
36 (below_fluid.fluid_id.has_tag(&FluidTag::SUPPORTS_LILY_PAD)
37 || below.get_block().has_tag(&BlockTag::SUPPORTS_LILY_PAD))
38 && above_fluid.is_empty()
39 }
40}
41
42impl BlockBehavior for LilyPadBlock {
43 fn entity_inside(
44 &self,
45 _state: BlockStateId,
46 world: &Arc<World>,
47 pos: BlockPos,
48 entity: &dyn Entity,
49 _effect_collector: &mut InsideBlockEffectCollector,
50 _is_precise: bool,
51 ) {
52 if entity.entity_type().is_abstract_boat {
53 world.destroy_block_by_entity(pos, true, entity);
54 }
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 can_survive(&self, _state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
70 let below = pos.below();
71 Self::may_place_on(world, below)
72 }
73
74 fn get_state_for_placement(&self, _context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
75 Some(self.block.default_state())
76 }
77}