178 lines
6.4 KiB
Rust
178 lines
6.4 KiB
Rust
use std::sync::Arc;
|
|
use std::sync::Mutex;
|
|
|
|
use crate::block::blocks::redstone::block_receives_redstone_power;
|
|
use crate::block::entities::crafter::CrafterBlockEntity;
|
|
use crate::block::registry::BlockActionResult;
|
|
use crate::block::{
|
|
BlockBehaviour, GetComparatorOutputArgs, NormalUseArgs, OnNeighborUpdateArgs, OnPlaceArgs,
|
|
OnScheduledTickArgs, PlacedArgs,
|
|
};
|
|
use pumpkin_data::block_properties::{
|
|
BlockProperties, CrafterLikeProperties, HorizontalFacing, Orientation,
|
|
};
|
|
use pumpkin_data::translation;
|
|
use pumpkin_data::world::WorldEvent;
|
|
use pumpkin_data::{BlockDirection, BlockStateId};
|
|
use pumpkin_inventory::generic_container_screen_handler::create_crafter_3x3;
|
|
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
|
use pumpkin_inventory::screen_handler::{
|
|
InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
|
|
};
|
|
use pumpkin_macros::pumpkin_block;
|
|
use pumpkin_util::text::TextComponent;
|
|
use pumpkin_world::inventory::Inventory;
|
|
use pumpkin_world::tick::TickPriority;
|
|
use pumpkin_world::world::BlockFlags;
|
|
|
|
struct CrafterScreenFactory(Arc<dyn Inventory>);
|
|
|
|
impl ScreenHandlerFactory for CrafterScreenFactory {
|
|
fn create_screen_handler(
|
|
&self,
|
|
sync_id: u8,
|
|
player_inventory: &Arc<PlayerInventory>,
|
|
_player: &dyn InventoryPlayer,
|
|
) -> Option<SharedScreenHandler> {
|
|
let handler = create_crafter_3x3(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_CRAFTER,
|
|
translation::bedrock::CONTAINER_CRAFTER
|
|
)
|
|
}
|
|
}
|
|
|
|
#[pumpkin_block("minecraft:crafter")]
|
|
pub struct CrafterBlock;
|
|
|
|
impl BlockBehaviour for CrafterBlock {
|
|
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
|
|
.open_handled_screen(&CrafterScreenFactory(inventory), Some(*args.position));
|
|
}
|
|
BlockActionResult::Success
|
|
}
|
|
|
|
fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
|
|
let mut props = CrafterLikeProperties::default(args.block);
|
|
let facing = args.direction;
|
|
let horizontal = args.player.living_entity.entity.get_horizontal_facing();
|
|
props.orientation = match facing {
|
|
BlockDirection::Down => match horizontal {
|
|
HorizontalFacing::North => Orientation::DownNorth,
|
|
HorizontalFacing::South => Orientation::DownSouth,
|
|
HorizontalFacing::East => Orientation::DownEast,
|
|
HorizontalFacing::West => Orientation::DownWest,
|
|
},
|
|
BlockDirection::Up => match horizontal {
|
|
HorizontalFacing::North => Orientation::UpNorth,
|
|
HorizontalFacing::South => Orientation::UpSouth,
|
|
HorizontalFacing::East => Orientation::UpEast,
|
|
HorizontalFacing::West => Orientation::UpWest,
|
|
},
|
|
BlockDirection::North => Orientation::NorthUp,
|
|
BlockDirection::South => Orientation::SouthUp,
|
|
BlockDirection::East => Orientation::EastUp,
|
|
BlockDirection::West => Orientation::WestUp,
|
|
};
|
|
props.to_state_id(args.block)
|
|
}
|
|
|
|
fn placed(&self, args: PlacedArgs<'_>) {
|
|
let crafter_block_entity = CrafterBlockEntity::new(*args.position);
|
|
args.world.add_block_entity(Arc::new(crafter_block_entity));
|
|
}
|
|
|
|
fn on_neighbor_update(&self, args: OnNeighborUpdateArgs<'_>) {
|
|
let powered = block_receives_redstone_power(args.world, args.position);
|
|
let mut props = CrafterLikeProperties::from_state_id(
|
|
args.world.get_block_state(args.position).id,
|
|
args.block,
|
|
);
|
|
|
|
if powered && !props.triggered {
|
|
props.triggered = true;
|
|
args.world
|
|
.schedule_block_tick(args.block, *args.position, 4, TickPriority::Normal);
|
|
args.world.set_block_state(
|
|
args.position,
|
|
props.to_state_id(args.block),
|
|
BlockFlags::NOTIFY_LISTENERS,
|
|
);
|
|
} else if !powered && props.triggered {
|
|
props.triggered = false;
|
|
args.world.set_block_state(
|
|
args.position,
|
|
props.to_state_id(args.block),
|
|
BlockFlags::NOTIFY_LISTENERS,
|
|
);
|
|
}
|
|
}
|
|
|
|
fn on_scheduled_tick(&self, args: OnScheduledTickArgs<'_>) {
|
|
let mut props = CrafterLikeProperties::from_state_id(
|
|
args.world.get_block_state(args.position).id,
|
|
args.block,
|
|
);
|
|
|
|
// Set to crafting state
|
|
props.crafting = true;
|
|
args.world.set_block_state(
|
|
args.position,
|
|
props.to_state_id(args.block),
|
|
BlockFlags::NOTIFY_LISTENERS,
|
|
);
|
|
|
|
// Spawn fail smoke particles
|
|
args.world.sync_world_event(
|
|
WorldEvent::ParticlesShootSmoke,
|
|
*args.position,
|
|
match props.orientation {
|
|
Orientation::DownEast
|
|
| Orientation::DownNorth
|
|
| Orientation::DownSouth
|
|
| Orientation::DownWest => 0,
|
|
Orientation::UpEast
|
|
| Orientation::UpNorth
|
|
| Orientation::UpSouth
|
|
| Orientation::UpWest => 1,
|
|
Orientation::NorthUp => 2,
|
|
Orientation::SouthUp => 3,
|
|
Orientation::WestUp => 4,
|
|
Orientation::EastUp => 5,
|
|
},
|
|
);
|
|
|
|
props.crafting = false;
|
|
args.world.set_block_state(
|
|
args.position,
|
|
props.to_state_id(args.block),
|
|
BlockFlags::NOTIFY_LISTENERS,
|
|
);
|
|
}
|
|
|
|
fn get_comparator_output(&self, args: GetComparatorOutputArgs<'_>) -> Option<u8> {
|
|
if let Some(block_entity) = args.world.get_block_entity(args.position) {
|
|
let crafter = block_entity.as_any().downcast_ref::<CrafterBlockEntity>()?;
|
|
|
|
let items = crafter
|
|
.items
|
|
.read()
|
|
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
|
let occupied = items.iter().filter(|s| !s.is_empty()).count() as u8;
|
|
Some(occupied)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|