103 lines
3.5 KiB
Rust
103 lines
3.5 KiB
Rust
use std::sync::Arc;
|
|
use std::sync::Mutex;
|
|
|
|
use crate::block::{GetComparatorOutputArgs, OnPlaceArgs, OnSyncedBlockEventArgs, PlacedArgs};
|
|
use crate::block::{
|
|
registry::BlockActionResult,
|
|
{BlockBehaviour, NormalUseArgs},
|
|
};
|
|
|
|
use crate::block::entities::shulker_box::ShulkerBoxBlockEntity;
|
|
use pumpkin_data::BlockStateId;
|
|
use pumpkin_data::block_properties::BlockProperties;
|
|
use pumpkin_data::translation;
|
|
use pumpkin_inventory::generic_container_screen_handler::create_generic_9x3;
|
|
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
|
use pumpkin_inventory::screen_handler::{
|
|
InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
|
|
};
|
|
use pumpkin_macros::pumpkin_block_from_tag;
|
|
use pumpkin_util::text::TextComponent;
|
|
use pumpkin_world::inventory::Inventory;
|
|
|
|
struct ShulkerBoxScreenFactory(Arc<dyn Inventory>);
|
|
|
|
impl ScreenHandlerFactory for ShulkerBoxScreenFactory {
|
|
fn create_screen_handler(
|
|
&self,
|
|
sync_id: u8,
|
|
player_inventory: &Arc<PlayerInventory>,
|
|
_player: &dyn InventoryPlayer,
|
|
) -> Option<SharedScreenHandler> {
|
|
let handler = create_generic_9x3(sync_id, player_inventory, self.0.clone());
|
|
let screen_handler_arc = Arc::new(Mutex::new(handler));
|
|
|
|
Some(screen_handler_arc as SharedScreenHandler)
|
|
}
|
|
|
|
fn get_display_name(&self) -> TextComponent {
|
|
pumpkin_macros::translate_cross!(
|
|
translation::java::CONTAINER_SHULKERBOX,
|
|
translation::bedrock::CONTAINER_SHULKERBOX
|
|
)
|
|
}
|
|
}
|
|
|
|
#[pumpkin_block_from_tag("minecraft:shulker_boxes")]
|
|
pub struct ShulkerBoxBlock;
|
|
|
|
type EndRodLikeProperties = pumpkin_data::block_properties::EndRodLikeProperties;
|
|
|
|
impl BlockBehaviour for ShulkerBoxBlock {
|
|
fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
|
|
let mut props = EndRodLikeProperties::default(args.block);
|
|
props.facing = args.direction.to_facing().opposite();
|
|
props.to_state_id(args.block)
|
|
}
|
|
|
|
fn on_synced_block_event(&self, args: OnSyncedBlockEventArgs<'_>) -> bool {
|
|
// On the server, we don't need the Animation steps for now, because the client is responsible for that.
|
|
// TODO: Do not open the shulker box when it is currently closing
|
|
args.r#type == Self::OPEN_ANIMATION_EVENT_TYPE
|
|
}
|
|
|
|
fn placed(&self, args: PlacedArgs<'_>) {
|
|
{
|
|
let barrel_block_entity = ShulkerBoxBlockEntity::new(*args.position);
|
|
args.world.add_block_entity(Arc::new(barrel_block_entity));
|
|
}
|
|
}
|
|
|
|
fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
|
|
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
|
&& let Some(inventory) = block_entity.get_inventory()
|
|
{
|
|
args.player.increment_stat(
|
|
pumpkin_data::statistic::StatisticCategory::Custom,
|
|
pumpkin_data::statistic::CustomStatistic::OpenShulkerBox as i32,
|
|
1,
|
|
);
|
|
args.player
|
|
.open_handled_screen(&ShulkerBoxScreenFactory(inventory), Some(*args.position));
|
|
}
|
|
|
|
BlockActionResult::Success
|
|
}
|
|
|
|
fn get_comparator_output(&self, args: GetComparatorOutputArgs<'_>) -> Option<u8> {
|
|
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
|
&& let Some(inventory) = block_entity.get_inventory()
|
|
{
|
|
Some(crate::block::calculate_comparator_output(
|
|
inventory.as_ref(),
|
|
))
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ShulkerBoxBlock {
|
|
pub const OPEN_ANIMATION_EVENT_TYPE: u8 = 1;
|
|
}
|