use std::sync::Arc; use std::sync::Mutex; use pumpkin_data::translation; use pumpkin_data::{ Block, BlockDirection, BlockStateId, HorizontalFacingExt, block_properties::{AttachFace, GrindstoneLikeProperties}, }; use pumpkin_inventory::grindstone_screen_handler::GrindstoneScreenHandler; use pumpkin_inventory::player::player_inventory::PlayerInventory; use pumpkin_inventory::screen_handler::{ InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler, }; use pumpkin_macros::pumpkin_block; use pumpkin_util::math::position::BlockPos; use pumpkin_util::text::TextComponent; use pumpkin_world::inventory::SimpleInventory; use pumpkin_world::world::BlockAccessor; use crate::block::registry::BlockActionResult; use crate::block::{ BlockBehaviour, CanPlaceAtArgs, GetScreenHandlerFactoryArgs, GetStateForNeighborUpdateArgs, NormalUseArgs, OnPlaceArgs, PathComputationType, }; use pumpkin_data::BlockState; use super::abstract_wall_mounting::WallMountedBlock; #[pumpkin_block("minecraft:grindstone")] pub struct GrindstoneBlock; impl BlockBehaviour for GrindstoneBlock { fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult { if let Some(factory) = self.get_screen_handler_factory(GetScreenHandlerFactoryArgs { server: args.server, world: args.world, block: args.block, position: args.position, player: args.player, }) { args.player.increment_stat( pumpkin_data::statistic::StatisticCategory::Custom, pumpkin_data::statistic::CustomStatistic::InteractWithGrindstone as i32, 1, ); args.player .open_handled_screen(factory.as_ref(), Some(*args.position)); } BlockActionResult::Success } fn get_screen_handler_factory( &self, _args: GetScreenHandlerFactoryArgs<'_>, ) -> Option> { Some(Box::new(GrindstoneScreenFactory)) } fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId { let mut props = GrindstoneLikeProperties::from_state_id(args.block.default_state.id); (props.face, props.facing) = WallMountedBlock::get_placement_face(self, args.player, args.direction); props.to_state_id(args.block) } fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool { // Use the provided direction, or fallback to the current state's direction if missing let direction = args .direction .unwrap_or_else(|| self.get_direction(args.state.id, args.block)); WallMountedBlock::can_place_at(self, args.block_accessor, args.position, direction) } fn get_state_for_neighbor_update( &self, args: GetStateForNeighborUpdateArgs<'_>, ) -> BlockStateId { WallMountedBlock::get_state_for_neighbor_update(self, args) } fn is_pathfindable(&self, _state: &BlockState, _computation_type: PathComputationType) -> bool { false } } impl WallMountedBlock for GrindstoneBlock { fn can_place_at( &self, _world: &dyn BlockAccessor, _pos: &BlockPos, _direction: BlockDirection, ) -> bool { true } fn get_direction(&self, state_id: BlockStateId, _block: &Block) -> BlockDirection { let props = GrindstoneLikeProperties::from_state_id(state_id); match props.face { AttachFace::Floor => BlockDirection::Up, AttachFace::Ceiling => BlockDirection::Down, AttachFace::Wall => props.facing.to_block_direction(), } } } struct GrindstoneScreenFactory; impl ScreenHandlerFactory for GrindstoneScreenFactory { fn create_screen_handler( &self, sync_id: u8, player_inventory: &Arc, _player: &dyn InventoryPlayer, ) -> Option { let inventory = Arc::new(SimpleInventory::new(3)); let handler = GrindstoneScreenHandler::new(sync_id, player_inventory, inventory); let concrete_arc = Arc::new(Mutex::new(handler)); Some(concrete_arc as SharedScreenHandler) } fn get_display_name(&self) -> TextComponent { pumpkin_macros::translate_cross!( translation::java::CONTAINER_GRINDSTONE_TITLE, translation::bedrock::TILE_GRINDSTONE_NAME ) } }