steel_core/behavior/blocks/building/
amethyst_block.rs1use std::sync::Arc;
2
3use steel_macros::block_behavior;
4use steel_registry::{blocks::BlockRef, sound_events::BLOCK_AMETHYST_BLOCK_CHIME};
5use steel_utils::{BlockPos, BlockStateId};
6
7use crate::{
8 behavior::{BlockBehavior, BlockPlaceContext},
9 entity::projectile::Projectile,
10 world::{ClipHitResult, World},
11};
12
13#[block_behavior]
15pub struct AmethystBlock {
16 block: BlockRef,
17}
18
19impl AmethystBlock {
20 #[must_use]
22 pub const fn new(block: BlockRef) -> Self {
23 Self { block }
24 }
25
26 fn projectile_hit_pitch(random_fraction: f32) -> f32 {
27 0.5 + random_fraction * 1.2
28 }
29
30 pub(super) fn play_projectile_hit_sound(world: &World, pos: BlockPos) {
31 let pitch = Self::projectile_hit_pitch(rand::random());
32 world.play_block_sound(&BLOCK_AMETHYST_BLOCK_CHIME, pos, 1.0, pitch, None);
33 }
34}
35
36impl BlockBehavior for AmethystBlock {
37 fn get_state_for_placement(&self, _context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
38 Some(self.block.default_state())
39 }
40
41 fn on_projectile_hit(
42 &self,
43 _state: BlockStateId,
44 world: &Arc<World>,
45 hit: &ClipHitResult,
46 _projectile: &dyn Projectile,
47 ) {
48 Self::play_projectile_hit_sound(world, hit.block_pos);
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::AmethystBlock;
55
56 #[test]
57 fn projectile_chime_pitch_matches_vanilla_range() {
58 assert!((AmethystBlock::projectile_hit_pitch(0.0) - 0.5).abs() < f32::EPSILON);
59 assert!(AmethystBlock::projectile_hit_pitch(0.999_999) < 1.7);
60 }
61}