use pumpkin_data::sound::{Sound, SoundCategory}; use pumpkin_nbt::compound::NbtCompound; use pumpkin_util::math::position::BlockPos; use pumpkin_util::random::xoroshiro128::Xoroshiro; use pumpkin_util::random::{RandomImpl, get_seed}; use std::any::Any; use std::pin::Pin; use std::sync::Arc; use crate::block::viewer::{ViewerCountListener, ViewerCountTracker, ViewerFuture}; use crate::world::SimpleWorld; use super::BlockEntity; pub struct EnderChestBlockEntity { pub position: BlockPos, // Viewer viewers: Arc, } impl BlockEntity for EnderChestBlockEntity { fn resource_location(&self) -> &'static str { Self::ID } fn get_position(&self) -> BlockPos { self.position } fn from_nbt(_nbt: &NbtCompound, position: BlockPos) -> Self where Self: Sized, { Self { position, viewers: Arc::new(ViewerCountTracker::new()), } } fn write_nbt<'a>( &'a self, _nbt: &'a mut NbtCompound, ) -> Pin + Send + 'a>> { Box::pin(async {}) } fn tick<'a>( &'a self, world: &'a Arc, ) -> Pin + Send + 'a>> { Box::pin(async move { self.viewers .update_viewer_count::(self, world, &self.position) .await; }) } fn as_any(&self) -> &dyn Any { self } } impl ViewerCountListener for EnderChestBlockEntity { fn on_container_open<'a>( &'a self, world: &'a Arc, _position: &'a BlockPos, ) -> ViewerFuture<'a, ()> { Box::pin(async move { self.play_sound(world, Sound::BlockEnderChestOpen).await; }) } fn on_container_close<'a>( &'a self, world: &'a Arc, _position: &'a BlockPos, ) -> ViewerFuture<'a, ()> { Box::pin(async move { self.play_sound(world, Sound::BlockEnderChestClose).await; }) } fn on_viewer_count_update<'a>( &'a self, world: &'a Arc, position: &'a BlockPos, _old: u16, new: u16, ) -> ViewerFuture<'a, ()> { Box::pin(async move { world .add_synced_block_event(*position, Self::LID_ANIMATION_EVENT_TYPE, new as u8) .await; }) } } impl EnderChestBlockEntity { pub const LID_ANIMATION_EVENT_TYPE: u8 = 1; pub const ID: &'static str = "minecraft:ender_chest"; #[must_use] pub fn new(position: BlockPos) -> Self { Self { position, viewers: Arc::new(ViewerCountTracker::new()), } } #[must_use] pub fn get_tracker(&self) -> Arc { self.viewers.clone() } async fn play_sound(&self, world: &Arc, sound: Sound) { let mut rng = Xoroshiro::from_seed(get_seed()); world .play_sound_fine( sound, SoundCategory::Blocks, &self.position.to_centered_f64(), 0.5, rng.next_f32() * 0.1 + 0.9, ) .await; } }