steel_core/behavior/blocks/building/
amethyst_cluster.rs1use crate::{
2 behavior::{BlockBehavior, BlockPlaceContext, blocks::AmethystBlock},
3 entity::projectile::Projectile,
4 world::{ClipHitResult, LevelReader, ScheduledTickAccess, World},
5};
6use std::sync::Arc;
7use steel_macros::block_behavior;
8use steel_registry::{
9 blocks::{
10 BlockRef,
11 block_state_ext::BlockStateExt,
12 properties::{BlockStateProperties, BoolProperty, EnumProperty},
13 },
14 vanilla_blocks, vanilla_fluids,
15};
16use steel_utils::{BlockPos, BlockStateId, Direction};
17
18#[block_behavior]
20pub struct AmethystClusterBlock {
21 block: BlockRef,
22}
23
24const FACING: &EnumProperty<Direction> = &BlockStateProperties::FACING;
25const WATERLOGGED: &BoolProperty = &BlockStateProperties::WATERLOGGED;
26
27impl AmethystClusterBlock {
28 #[must_use]
30 pub const fn new(block: BlockRef) -> Self {
31 Self { block }
32 }
33}
34
35impl BlockBehavior for AmethystClusterBlock {
36 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
37 let state = self
38 .block
39 .default_state()
40 .set_value(WATERLOGGED, context.is_water_source())
41 .set_value(FACING, context.clicked_face());
42 self.can_survive(state, context.world, context.place_pos())
43 .then_some(state)
44 }
45
46 fn update_shape(
47 &self,
48 state: BlockStateId,
49 world: &dyn ScheduledTickAccess,
50 pos: BlockPos,
51 direction: Direction,
52 _neighbor_pos: BlockPos,
53 _neighbor_state: BlockStateId,
54 ) -> BlockStateId {
55 if state.get_value(WATERLOGGED) {
56 let delay = world.fluid_tick_delay(&vanilla_fluids::WATER);
57 let _ = world.schedule_fluid_tick_default(pos, &vanilla_fluids::WATER, delay);
58 }
59
60 if direction == state.get_value(FACING).opposite() && !self.can_survive(state, world, pos) {
61 vanilla_blocks::AIR.default_state()
62 } else {
63 state
64 }
65 }
66
67 fn can_survive(&self, state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
68 let direction = state.get_value(FACING);
69 let adjacent = pos.relative(direction.opposite());
70 world.is_face_sturdy(world.get_block_state(adjacent), adjacent, direction)
71 }
72
73 fn on_projectile_hit(
74 &self,
75 _state: BlockStateId,
76 world: &Arc<World>,
77 hit: &ClipHitResult,
78 _projectile: &dyn Projectile,
79 ) {
80 AmethystBlock::play_projectile_hit_sound(world, hit.block_pos);
81 }
82
83 }