fix: allow spectatos to inspect containers
This commit is contained in:
parent
015091de12
commit
4e6d380bbc
@ -27,6 +27,7 @@ pub fn create_generic_9x3(
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
inventory: Arc<dyn Inventory>,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> GenericContainerScreenHandler {
|
||||
GenericContainerScreenHandler::new(
|
||||
WindowType::Generic9x3,
|
||||
@ -35,6 +36,7 @@ pub fn create_generic_9x3(
|
||||
inventory,
|
||||
3,
|
||||
9,
|
||||
player.is_spectator(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -45,6 +47,7 @@ pub fn create_generic_9x6(
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
inventory: Arc<dyn Inventory>,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> GenericContainerScreenHandler {
|
||||
GenericContainerScreenHandler::new(
|
||||
WindowType::Generic9x6,
|
||||
@ -53,6 +56,7 @@ pub fn create_generic_9x6(
|
||||
inventory,
|
||||
6,
|
||||
9,
|
||||
player.is_spectator(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -63,6 +67,7 @@ pub fn create_generic_3x3(
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
inventory: Arc<dyn Inventory>,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> GenericContainerScreenHandler {
|
||||
GenericContainerScreenHandler::new(
|
||||
WindowType::Generic3x3,
|
||||
@ -71,6 +76,7 @@ pub fn create_generic_3x3(
|
||||
inventory,
|
||||
3,
|
||||
3,
|
||||
player.is_spectator(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -79,6 +85,7 @@ pub fn create_crafter_3x3(
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
inventory: Arc<dyn Inventory>,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> GenericContainerScreenHandler {
|
||||
GenericContainerScreenHandler::new(
|
||||
WindowType::Crafter3x3,
|
||||
@ -87,6 +94,7 @@ pub fn create_crafter_3x3(
|
||||
inventory,
|
||||
3,
|
||||
3,
|
||||
player.is_spectator(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -97,6 +105,7 @@ pub fn create_hopper(
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
inventory: Arc<dyn Inventory>,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> GenericContainerScreenHandler {
|
||||
GenericContainerScreenHandler::new(
|
||||
WindowType::Hopper,
|
||||
@ -105,6 +114,7 @@ pub fn create_hopper(
|
||||
inventory,
|
||||
1,
|
||||
5,
|
||||
player.is_spectator(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -119,6 +129,8 @@ pub struct GenericContainerScreenHandler {
|
||||
pub rows: u8,
|
||||
/// Number of columns in the container grid.
|
||||
pub columns: u8,
|
||||
/// Whether the opener is in spectator mode.
|
||||
pub is_spectator: bool,
|
||||
/// Core screen handler behavior (slots, sync ID, listeners).
|
||||
behaviour: ScreenHandlerBehaviour,
|
||||
}
|
||||
@ -133,6 +145,7 @@ impl GenericContainerScreenHandler {
|
||||
/// - `inventory` - The container's inventory
|
||||
/// - `rows` - Number of rows in the container
|
||||
/// - `columns` - Number of columns in the container
|
||||
/// - `is_spectator` - Whether the opener is a spectator
|
||||
fn new(
|
||||
screen_type: WindowType,
|
||||
sync_id: u8,
|
||||
@ -140,16 +153,19 @@ impl GenericContainerScreenHandler {
|
||||
inventory: Arc<dyn Inventory>,
|
||||
rows: u8,
|
||||
columns: u8,
|
||||
is_spectator: bool,
|
||||
) -> Self {
|
||||
let mut handler = Self {
|
||||
inventory,
|
||||
rows,
|
||||
columns,
|
||||
is_spectator,
|
||||
behaviour: ScreenHandlerBehaviour::new(sync_id, Some(screen_type)),
|
||||
};
|
||||
|
||||
// TODO: Add player entity as a parameter
|
||||
if !is_spectator {
|
||||
handler.inventory.on_open();
|
||||
}
|
||||
|
||||
handler.add_inventory_slots();
|
||||
let player_inventory: Arc<dyn Inventory> = player_inventory.clone();
|
||||
@ -190,8 +206,10 @@ impl ScreenHandler for GenericContainerScreenHandler {
|
||||
|
||||
fn on_closed(&mut self, player: &dyn InventoryPlayer) {
|
||||
self.default_on_closed(player);
|
||||
if !self.is_spectator && !player.is_spectator() {
|
||||
self.inventory.on_close();
|
||||
}
|
||||
}
|
||||
|
||||
/// Quick move logic for generic containers.
|
||||
///
|
||||
|
||||
@ -135,6 +135,11 @@ pub trait InventoryPlayer: Send + Sync {
|
||||
/// Checks if the player is in creative mode.
|
||||
fn is_creative(&self) -> bool;
|
||||
|
||||
/// Checks if the player is in spectator mode.
|
||||
fn is_spectator(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Gets the player's experience level.
|
||||
fn experience_level(&self) -> i32;
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use crate::block::blocks::falling::FallingBlock;
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{
|
||||
BlockBehaviour, GetStateForNeighborUpdateArgs, NormalUseArgs, OnPlaceArgs, OnScheduledTickArgs,
|
||||
PathComputationType, PlacedArgs,
|
||||
BlockBehaviour, GetScreenHandlerFactoryArgs, GetStateForNeighborUpdateArgs, NormalUseArgs,
|
||||
OnPlaceArgs, OnScheduledTickArgs, PathComputationType, PlacedArgs,
|
||||
};
|
||||
|
||||
use pumpkin_data::block_properties::WallTorchLikeProperties;
|
||||
@ -40,17 +40,32 @@ impl AnvilBlock {
|
||||
|
||||
impl BlockBehaviour for AnvilBlock {
|
||||
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::InteractWithAnvil as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&AnvilScreenFactory, Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
_args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
Some(Box::new(AnvilScreenFactory))
|
||||
}
|
||||
|
||||
fn placed(&self, args: PlacedArgs<'_>) {
|
||||
FallingBlock::placed(&FallingBlock, args);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::block::{GetComparatorOutputArgs, OnPlaceArgs, PlacedArgs};
|
||||
use crate::block::{GetComparatorOutputArgs, GetScreenHandlerFactoryArgs, OnPlaceArgs, PlacedArgs};
|
||||
use crate::block::{
|
||||
registry::BlockActionResult,
|
||||
{BlockBehaviour, NormalUseArgs},
|
||||
@ -28,9 +28,9 @@ impl ScreenHandlerFactory for BarrelScreenFactory {
|
||||
&self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> Option<SharedScreenHandler> {
|
||||
let handler = create_generic_9x3(sync_id, player_inventory, self.0.clone());
|
||||
let handler = create_generic_9x3(sync_id, player_inventory, self.0.clone(), player);
|
||||
let concrete_arc = Arc::new(Mutex::new(handler));
|
||||
|
||||
Some(concrete_arc as SharedScreenHandler)
|
||||
@ -55,21 +55,34 @@ impl BlockBehaviour for BarrelBlock {
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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::OpenBarrel as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&BarrelScreenFactory(inventory), Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.get_inventory()?;
|
||||
Some(Box::new(BarrelScreenFactory(inventory)))
|
||||
}
|
||||
|
||||
fn placed(&self, args: PlacedArgs<'_>) {
|
||||
let barrel_block_entity = BarrelBlockEntity::new(*args.position);
|
||||
args.world.add_block_entity(Arc::new(barrel_block_entity));
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::block::entities::BlockEntity;
|
||||
use pumpkin_data::translation;
|
||||
use pumpkin_inventory::beacon_screen_handler::create_beacon_handler;
|
||||
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
||||
@ -13,7 +12,7 @@ use pumpkin_util::text::TextComponent;
|
||||
use pumpkin_world::inventory::Inventory;
|
||||
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{BlockBehaviour, NormalUseArgs};
|
||||
use crate::block::{BlockBehaviour, GetScreenHandlerFactoryArgs, NormalUseArgs};
|
||||
|
||||
// Create the factory just like ChestScreenFactory
|
||||
struct BeaconScreenFactory(Arc<dyn Inventory>);
|
||||
@ -44,13 +43,14 @@ pub struct BeaconBlock;
|
||||
|
||||
impl BlockBehaviour for BeaconBlock {
|
||||
fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
|
||||
let block_entity = args.world.get_block_entity(args.position);
|
||||
|
||||
// Extract the inventory from the entity
|
||||
let Some(inventory) = block_entity.and_then(BlockEntity::get_inventory) else {
|
||||
return BlockActionResult::Fail;
|
||||
};
|
||||
|
||||
self.get_screen_handler_factory(GetScreenHandlerFactoryArgs {
|
||||
server: args.server,
|
||||
world: args.world,
|
||||
block: args.block,
|
||||
position: args.position,
|
||||
player: args.player,
|
||||
})
|
||||
.map_or(BlockActionResult::Fail, |factory| {
|
||||
args.player.increment_stat(
|
||||
pumpkin_data::statistic::StatisticCategory::Custom,
|
||||
pumpkin_data::statistic::CustomStatistic::InteractWithBeacon as i32,
|
||||
@ -59,8 +59,18 @@ impl BlockBehaviour for BeaconBlock {
|
||||
|
||||
// Open the screen using the factory
|
||||
args.player
|
||||
.open_handled_screen(&BeaconScreenFactory(inventory), Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
|
||||
BlockActionResult::Success
|
||||
})
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.get_inventory()?;
|
||||
Some(Box::new(BeaconScreenFactory(inventory)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,8 +18,8 @@ use pumpkin_world::inventory::Inventory;
|
||||
|
||||
use crate::{
|
||||
block::{
|
||||
BlockBehaviour, BrokenArgs, GetComparatorOutputArgs, NormalUseArgs, OnPlaceArgs,
|
||||
PlacedArgs, registry::BlockActionResult,
|
||||
BlockBehaviour, BrokenArgs, GetComparatorOutputArgs, GetScreenHandlerFactoryArgs,
|
||||
NormalUseArgs, OnPlaceArgs, PlacedArgs, registry::BlockActionResult,
|
||||
},
|
||||
entity::experience_orb::ExperienceOrbEntity,
|
||||
};
|
||||
@ -78,25 +78,37 @@ pub struct BlastFurnaceBlock;
|
||||
|
||||
impl BlockBehaviour for BlastFurnaceBlock {
|
||||
fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(inventory) = block_entity.clone().get_inventory()
|
||||
&& let Some(property_delegate) = block_entity.clone().to_property_delegate()
|
||||
&& let Some(experience_container) = block_entity.to_experience_container()
|
||||
{
|
||||
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::InteractWithBlastFurnace as i32,
|
||||
1,
|
||||
);
|
||||
let blasting_furnace_screen_factory = BlastingFurnaceScreenFactory::new(
|
||||
args.player
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
crate::block::registry::BlockActionResult::Consume
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.clone().get_inventory()?;
|
||||
let property_delegate = block_entity.clone().to_property_delegate()?;
|
||||
let experience_container = block_entity.to_experience_container()?;
|
||||
Some(Box::new(BlastingFurnaceScreenFactory::new(
|
||||
inventory,
|
||||
property_delegate,
|
||||
experience_container,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&blasting_furnace_screen_factory, Some(*args.position));
|
||||
}
|
||||
crate::block::registry::BlockActionResult::Consume
|
||||
)))
|
||||
}
|
||||
|
||||
fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::block::{GetComparatorOutputArgs, PathComputationType, PlacedArgs};
|
||||
use crate::block::{
|
||||
GetComparatorOutputArgs, GetScreenHandlerFactoryArgs, PathComputationType, PlacedArgs,
|
||||
};
|
||||
use crate::block::{
|
||||
registry::BlockActionResult,
|
||||
{BlockBehaviour, NormalUseArgs},
|
||||
@ -48,22 +50,35 @@ pub struct BrewingStandBlock;
|
||||
|
||||
impl BlockBehaviour for BrewingStandBlock {
|
||||
fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(inventory) = block_entity.clone().get_inventory()
|
||||
&& let Some(pd) = block_entity.clone().to_property_delegate()
|
||||
{
|
||||
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::InteractWithBrewingstand as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&BrewingScreenFactory(inventory, pd), Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.clone().get_inventory()?;
|
||||
let pd = block_entity.to_property_delegate()?;
|
||||
Some(Box::new(BrewingScreenFactory(inventory, pd)))
|
||||
}
|
||||
|
||||
fn placed(&self, args: PlacedArgs<'_>) {
|
||||
let be = BrewingStandBlockEntity::new(*args.position);
|
||||
args.world.add_block_entity(Arc::new(be));
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{BlockBehaviour, NormalUseArgs};
|
||||
use crate::block::{BlockBehaviour, GetScreenHandlerFactoryArgs, NormalUseArgs};
|
||||
|
||||
use pumpkin_data::translation;
|
||||
use pumpkin_inventory::cartography_table_screen_handler::CartographyTableScreenHandler;
|
||||
@ -17,16 +17,31 @@ pub struct CartographyTableBlock;
|
||||
|
||||
impl BlockBehaviour for CartographyTableBlock {
|
||||
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::InteractWithCartographyTable as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&CartographyTableScreenFactory, Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
_args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
Some(Box::new(CartographyTableScreenFactory))
|
||||
}
|
||||
}
|
||||
|
||||
struct CartographyTableScreenFactory;
|
||||
|
||||
@ -23,8 +23,9 @@ use std::sync::Mutex;
|
||||
|
||||
use crate::block::{
|
||||
BlockBehaviour, BrokenArgs, EmitsRedstonePowerArgs, GetComparatorOutputArgs,
|
||||
GetRedstonePowerArgs, NormalUseArgs, OnPlaceArgs, OnSyncedBlockEventArgs, PathComputationType,
|
||||
PlacedArgs, PlayerPlacedArgs, RandomTickArgs, registry::BlockActionResult,
|
||||
GetRedstonePowerArgs, GetScreenHandlerFactoryArgs, NormalUseArgs, OnPlaceArgs,
|
||||
OnSyncedBlockEventArgs, PathComputationType, PlacedArgs, PlayerPlacedArgs, RandomTickArgs,
|
||||
registry::BlockActionResult,
|
||||
};
|
||||
use crate::entity::EntityBase;
|
||||
use crate::entity::player::Player;
|
||||
@ -39,12 +40,12 @@ impl ScreenHandlerFactory for ChestScreenFactory {
|
||||
&self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> Option<SharedScreenHandler> {
|
||||
let concrete_handler = if self.0.size() > 27 {
|
||||
create_generic_9x6(sync_id, player_inventory, self.0.clone())
|
||||
create_generic_9x6(sync_id, player_inventory, self.0.clone(), player)
|
||||
} else {
|
||||
create_generic_9x3(sync_id, player_inventory, self.0.clone())
|
||||
create_generic_9x3(sync_id, player_inventory, self.0.clone(), player)
|
||||
};
|
||||
|
||||
let concrete_arc = Arc::new(Mutex::new(concrete_handler));
|
||||
@ -165,32 +166,17 @@ fn get_chest_comparator_output(args: &GetComparatorOutputArgs<'_>) -> Option<u8>
|
||||
}
|
||||
}
|
||||
|
||||
fn normal_use_chest_impl(args: &NormalUseArgs<'_>) -> BlockActionResult {
|
||||
let stat = if args.block.id == Block::TRAPPED_CHEST.id {
|
||||
pumpkin_data::statistic::CustomStatistic::TriggerTrappedChest
|
||||
} else {
|
||||
pumpkin_data::statistic::CustomStatistic::OpenChest
|
||||
};
|
||||
args.player.increment_stat(
|
||||
pumpkin_data::statistic::StatisticCategory::Custom,
|
||||
stat as i32,
|
||||
1,
|
||||
);
|
||||
fn get_chest_screen_handler_factory(
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let state = args.world.get_block_state_id(args.position);
|
||||
let first_chest = args.world.get_block_entity(args.position);
|
||||
|
||||
// Spectators cannot open chests with a pending loot table.
|
||||
// The loot is only generated on first open by a non-spectator.
|
||||
let player_is_spectator = args.player.gamemode.load() == GameMode::Spectator;
|
||||
if player_is_spectator
|
||||
&& let Some(ref entity) = first_chest
|
||||
&& entity.has_loot_table()
|
||||
{
|
||||
return BlockActionResult::Success;
|
||||
}
|
||||
|
||||
// Unpack deferred loot table on first open (non-spectator only).
|
||||
if let Some(ref entity) = first_chest
|
||||
if !player_is_spectator
|
||||
&& let Some(ref entity) = first_chest
|
||||
&& let Some((loot_key, seed)) = entity.take_loot_table()
|
||||
&& let Some(table) = get_loot_table(&loot_key)
|
||||
&& let Some(inv) = entity.clone().get_inventory()
|
||||
@ -199,9 +185,7 @@ fn normal_use_chest_impl(args: &NormalUseArgs<'_>) -> BlockActionResult {
|
||||
inv.mark_dirty();
|
||||
}
|
||||
|
||||
let Some(first_inventory) = first_chest.and_then(BlockEntity::get_inventory) else {
|
||||
return BlockActionResult::Fail;
|
||||
};
|
||||
let first_inventory = first_chest.and_then(BlockEntity::get_inventory)?;
|
||||
|
||||
let chest_props = ChestLikeProperties::from_state_id(state);
|
||||
let connected_towards = match chest_props.r#type {
|
||||
@ -211,13 +195,13 @@ fn normal_use_chest_impl(args: &NormalUseArgs<'_>) -> BlockActionResult {
|
||||
};
|
||||
|
||||
if is_chest_blocked(args.world, args.position) {
|
||||
return BlockActionResult::Success;
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(direction) = connected_towards {
|
||||
let neighbor_pos = args.position.offset(direction.to_offset());
|
||||
if is_chest_blocked(args.world, &neighbor_pos) {
|
||||
return BlockActionResult::Success;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,8 +221,31 @@ fn normal_use_chest_impl(args: &NormalUseArgs<'_>) -> BlockActionResult {
|
||||
first_inventory
|
||||
};
|
||||
|
||||
Some(Box::new(ChestScreenFactory(inventory)))
|
||||
}
|
||||
|
||||
fn normal_use_chest_impl(args: &NormalUseArgs<'_>) -> BlockActionResult {
|
||||
let stat = if args.block.id == Block::TRAPPED_CHEST.id {
|
||||
pumpkin_data::statistic::CustomStatistic::TriggerTrappedChest
|
||||
} else {
|
||||
pumpkin_data::statistic::CustomStatistic::OpenChest
|
||||
};
|
||||
args.player.increment_stat(
|
||||
pumpkin_data::statistic::StatisticCategory::Custom,
|
||||
stat as i32,
|
||||
1,
|
||||
);
|
||||
|
||||
if let Some(factory) = get_chest_screen_handler_factory(GetScreenHandlerFactoryArgs {
|
||||
server: args.server,
|
||||
world: args.world,
|
||||
block: args.block,
|
||||
position: args.position,
|
||||
player: args.player,
|
||||
}) {
|
||||
args.player
|
||||
.open_handled_screen(&ChestScreenFactory(inventory), Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
@ -293,6 +300,13 @@ impl BlockBehaviour for ChestBlock {
|
||||
normal_use_chest_impl(&args)
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
get_chest_screen_handler_factory(args)
|
||||
}
|
||||
|
||||
fn broken(&self, args: BrokenArgs<'_>) {
|
||||
broken_chest_impl(&args);
|
||||
}
|
||||
@ -365,6 +379,13 @@ impl BlockBehaviour for CopperChestBlock {
|
||||
normal_use_chest_impl(&args)
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
get_chest_screen_handler_factory(args)
|
||||
}
|
||||
|
||||
fn broken(&self, args: BrokenArgs<'_>) {
|
||||
broken_chest_impl(&args);
|
||||
}
|
||||
@ -428,6 +449,13 @@ impl BlockBehaviour for TrappedChestBlock {
|
||||
normal_use_chest_impl(&args)
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
get_chest_screen_handler_factory(args)
|
||||
}
|
||||
|
||||
fn broken(&self, args: BrokenArgs<'_>) {
|
||||
broken_chest_impl(&args);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{BlockBehaviour, NormalUseArgs};
|
||||
use crate::block::{BlockBehaviour, GetScreenHandlerFactoryArgs, NormalUseArgs};
|
||||
|
||||
use pumpkin_data::translation;
|
||||
use pumpkin_inventory::crafting::crafting_screen_handler::CraftingTableScreenHandler;
|
||||
@ -17,19 +17,32 @@ pub struct CraftingTableBlock;
|
||||
|
||||
impl BlockBehaviour for CraftingTableBlock {
|
||||
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::InteractWithCraftingTable as i32,
|
||||
1,
|
||||
);
|
||||
let recipe_manager = args.server.recipe_manager.clone();
|
||||
args.player.open_handled_screen(
|
||||
&CraftingTableScreenFactory(recipe_manager),
|
||||
Some(*args.position),
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let recipe_manager = args.server.recipe_manager.clone();
|
||||
Some(Box::new(CraftingTableScreenFactory(recipe_manager)))
|
||||
}
|
||||
}
|
||||
|
||||
struct CraftingTableScreenFactory(Arc<crate::server::RecipeManager>);
|
||||
|
||||
@ -3,7 +3,9 @@ use std::sync::Mutex;
|
||||
|
||||
use crate::block::entities::enchanting_table::EnchantingTableBlockEntity;
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{BlockBehaviour, NormalUseArgs, PathComputationType, PlacedArgs};
|
||||
use crate::block::{
|
||||
BlockBehaviour, GetScreenHandlerFactoryArgs, NormalUseArgs, PathComputationType, PlacedArgs,
|
||||
};
|
||||
use pumpkin_data::{Block, BlockState, BlockStateId, translation};
|
||||
use pumpkin_inventory::enchanting::enchanting_screen_handler::EnchantingTableScreenHandler;
|
||||
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
||||
@ -25,6 +27,23 @@ impl BlockBehaviour for EnchantingTableBlock {
|
||||
}
|
||||
|
||||
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
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let mut bookshelf_count = 0;
|
||||
|
||||
for off_z in -1..=1 {
|
||||
@ -70,14 +89,10 @@ impl BlockBehaviour for EnchantingTableBlock {
|
||||
let bookshelf_count = bookshelf_count.min(15);
|
||||
|
||||
let seed = args.player.enchantment_seed();
|
||||
args.player.open_handled_screen(
|
||||
&EnchantingTableScreenFactory {
|
||||
Some(Box::new(EnchantingTableScreenFactory {
|
||||
bookshelf_count,
|
||||
seed,
|
||||
},
|
||||
Some(*args.position),
|
||||
);
|
||||
BlockActionResult::Success
|
||||
}))
|
||||
}
|
||||
|
||||
fn is_pathfindable(&self, _state: &BlockState, _computation_type: PathComputationType) -> bool {
|
||||
|
||||
@ -3,8 +3,8 @@ use std::sync::Mutex;
|
||||
|
||||
use crate::block::entities::ender_chest::EnderChestBlockEntity;
|
||||
use crate::block::{
|
||||
BlockBehaviour, NormalUseArgs, OnPlaceArgs, OnSyncedBlockEventArgs, PathComputationType,
|
||||
PlacedArgs, registry::BlockActionResult,
|
||||
BlockBehaviour, GetScreenHandlerFactoryArgs, NormalUseArgs, OnPlaceArgs,
|
||||
OnSyncedBlockEventArgs, PathComputationType, PlacedArgs, registry::BlockActionResult,
|
||||
};
|
||||
use crate::world::World;
|
||||
use pumpkin_data::block_properties::LadderLikeProperties;
|
||||
@ -30,12 +30,14 @@ impl ScreenHandlerFactory for EnderChestScreenFactory {
|
||||
&self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> Option<SharedScreenHandler> {
|
||||
if let Some(tracker) = &self.tracker {
|
||||
if !player.is_spectator()
|
||||
&& let Some(tracker) = &self.tracker
|
||||
{
|
||||
self.inventory.set_tracker(tracker.clone());
|
||||
}
|
||||
let handler = create_generic_9x3(sync_id, player_inventory, self.inventory.clone());
|
||||
let handler = create_generic_9x3(sync_id, player_inventory, self.inventory.clone(), player);
|
||||
let concrete_arc = Arc::new(Mutex::new(handler));
|
||||
|
||||
Some(concrete_arc as SharedScreenHandler)
|
||||
@ -71,8 +73,32 @@ impl BlockBehaviour for EnderChestBlock {
|
||||
}
|
||||
|
||||
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::OpenEnderchest as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
// TODO: PiglinBrain.onGuardedBlockInteracted(serverWorld, player, true);
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
if is_chest_blocked(args.world, args.position) {
|
||||
return BlockActionResult::Success;
|
||||
return None;
|
||||
}
|
||||
|
||||
let block_entity = if let Some(be) = args.world.get_block_entity(args.position) {
|
||||
@ -83,28 +109,16 @@ impl BlockBehaviour for EnderChestBlock {
|
||||
be
|
||||
};
|
||||
|
||||
if let Some(block_entity) = block_entity
|
||||
let block_entity = block_entity
|
||||
.as_any()
|
||||
.downcast_ref::<EnderChestBlockEntity>()
|
||||
{
|
||||
args.player.increment_stat(
|
||||
pumpkin_data::statistic::StatisticCategory::Custom,
|
||||
pumpkin_data::statistic::CustomStatistic::OpenEnderchest as i32,
|
||||
1,
|
||||
);
|
||||
.downcast_ref::<EnderChestBlockEntity>()?;
|
||||
|
||||
let tracker = block_entity.get_tracker();
|
||||
let inventory = args.player.ender_chest_inventory();
|
||||
args.player.open_handled_screen(
|
||||
&EnderChestScreenFactory {
|
||||
Some(Box::new(EnderChestScreenFactory {
|
||||
inventory: inventory.clone(),
|
||||
tracker: Some(tracker),
|
||||
},
|
||||
Some(*args.position),
|
||||
);
|
||||
// TODO: PiglinBrain.onGuardedBlockInteracted(serverWorld, player, true);
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}))
|
||||
}
|
||||
|
||||
fn placed(&self, args: PlacedArgs<'_>) {
|
||||
|
||||
@ -17,8 +17,8 @@ use pumpkin_world::inventory::Inventory;
|
||||
|
||||
use crate::{
|
||||
block::{
|
||||
BlockBehaviour, BrokenArgs, GetComparatorOutputArgs, NormalUseArgs, OnPlaceArgs,
|
||||
PlacedArgs, registry::BlockActionResult,
|
||||
BlockBehaviour, BrokenArgs, GetComparatorOutputArgs, GetScreenHandlerFactoryArgs,
|
||||
NormalUseArgs, OnPlaceArgs, PlacedArgs, registry::BlockActionResult,
|
||||
},
|
||||
entity::experience_orb::ExperienceOrbEntity,
|
||||
};
|
||||
@ -77,24 +77,39 @@ pub struct FurnaceBlock;
|
||||
|
||||
impl BlockBehaviour for FurnaceBlock {
|
||||
fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(inventory) = block_entity.clone().get_inventory()
|
||||
&& let Some(property_delegate) = block_entity.clone().to_property_delegate()
|
||||
&& let Some(experience_container) = block_entity.to_experience_container()
|
||||
{
|
||||
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::InteractWithFurnace as i32,
|
||||
1,
|
||||
);
|
||||
let furnace_screen_factory =
|
||||
FurnaceScreenFactory::new(inventory, property_delegate, experience_container);
|
||||
args.player
|
||||
.open_handled_screen(&furnace_screen_factory, Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
crate::block::registry::BlockActionResult::Consume
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.clone().get_inventory()?;
|
||||
let property_delegate = block_entity.clone().to_property_delegate()?;
|
||||
let experience_container = block_entity.to_experience_container()?;
|
||||
Some(Box::new(FurnaceScreenFactory::new(
|
||||
inventory,
|
||||
property_delegate,
|
||||
experience_container,
|
||||
)))
|
||||
}
|
||||
|
||||
fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
|
||||
let mut props = FurnaceLikeProperties::default(args.block);
|
||||
props.facing = args
|
||||
|
||||
@ -19,8 +19,8 @@ use pumpkin_world::world::BlockAccessor;
|
||||
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{
|
||||
BlockBehaviour, CanPlaceAtArgs, GetStateForNeighborUpdateArgs, NormalUseArgs, OnPlaceArgs,
|
||||
PathComputationType,
|
||||
BlockBehaviour, CanPlaceAtArgs, GetScreenHandlerFactoryArgs, GetStateForNeighborUpdateArgs,
|
||||
NormalUseArgs, OnPlaceArgs, PathComputationType,
|
||||
};
|
||||
use pumpkin_data::BlockState;
|
||||
|
||||
@ -31,17 +31,32 @@ 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(&GrindstoneScreenFactory, Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
_args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
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) =
|
||||
|
||||
@ -3,7 +3,8 @@ use std::sync::Mutex;
|
||||
|
||||
use crate::block::blocks::redstone::block_receives_redstone_power;
|
||||
use crate::block::{
|
||||
GetComparatorOutputArgs, OnNeighborUpdateArgs, OnPlaceArgs, PathComputationType, PlacedArgs,
|
||||
GetComparatorOutputArgs, GetScreenHandlerFactoryArgs, OnNeighborUpdateArgs, OnPlaceArgs,
|
||||
PathComputationType, PlacedArgs,
|
||||
};
|
||||
use crate::block::{
|
||||
registry::BlockActionResult,
|
||||
@ -32,9 +33,9 @@ impl ScreenHandlerFactory for HopperBlockScreenFactory {
|
||||
&self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> Option<SharedScreenHandler> {
|
||||
let concrete_handler = create_hopper(sync_id, player_inventory, self.0.clone());
|
||||
let concrete_handler = create_hopper(sync_id, player_inventory, self.0.clone(), player);
|
||||
let concrete_arc = Arc::new(Mutex::new(concrete_handler));
|
||||
|
||||
Some(concrete_arc as SharedScreenHandler)
|
||||
@ -55,21 +56,34 @@ type HopperLikeProperties = pumpkin_data::block_properties::HopperLikeProperties
|
||||
|
||||
impl BlockBehaviour for HopperBlock {
|
||||
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()
|
||||
{
|
||||
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::InspectHopper as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&HopperBlockScreenFactory(inventory), Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.get_inventory()?;
|
||||
Some(Box::new(HopperBlockScreenFactory(inventory)))
|
||||
}
|
||||
|
||||
fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
|
||||
let mut props = HopperLikeProperties::default(args.block);
|
||||
props.facing = match args.direction {
|
||||
|
||||
@ -5,8 +5,8 @@ use crate::block::entities::lectern::LecternBlockEntity;
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{
|
||||
BlockBehaviour, BrokenArgs, EmitsRedstonePowerArgs, GetComparatorOutputArgs,
|
||||
GetRedstonePowerArgs, NormalUseArgs, OnPlaceArgs, OnScheduledTickArgs, OnStateReplacedArgs,
|
||||
PathComputationType, PlacedArgs, UseWithItemArgs,
|
||||
GetRedstonePowerArgs, GetScreenHandlerFactoryArgs, NormalUseArgs, OnPlaceArgs,
|
||||
OnScheduledTickArgs, OnStateReplacedArgs, PathComputationType, PlacedArgs, UseWithItemArgs,
|
||||
};
|
||||
use crate::entity::Entity;
|
||||
use crate::entity::item::ItemEntity;
|
||||
@ -162,39 +162,50 @@ impl BlockBehaviour for LecternBlock {
|
||||
}
|
||||
|
||||
fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
|
||||
let props =
|
||||
LecternLikeProperties::from_state_id(args.world.get_block_state(args.position).id);
|
||||
if !props.has_book {
|
||||
return BlockActionResult::Pass;
|
||||
}
|
||||
|
||||
let Some(block_entity) = args.world.get_block_entity(args.position) else {
|
||||
return BlockActionResult::Pass;
|
||||
};
|
||||
let Some(inventory) = block_entity.get_inventory() else {
|
||||
return BlockActionResult::Pass;
|
||||
};
|
||||
|
||||
self.get_screen_handler_factory(GetScreenHandlerFactoryArgs {
|
||||
server: args.server,
|
||||
world: args.world,
|
||||
block: args.block,
|
||||
position: args.position,
|
||||
player: args.player,
|
||||
})
|
||||
.map_or(BlockActionResult::Pass, |factory| {
|
||||
args.player.increment_stat(
|
||||
pumpkin_data::statistic::StatisticCategory::Custom,
|
||||
pumpkin_data::statistic::CustomStatistic::InteractWithLectern 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<Box<dyn ScreenHandlerFactory>> {
|
||||
let props =
|
||||
LecternLikeProperties::from_state_id(args.world.get_block_state(args.position).id);
|
||||
if !props.has_book {
|
||||
return None;
|
||||
}
|
||||
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.get_inventory()?;
|
||||
|
||||
let controller = Arc::new(LecternPageController {
|
||||
world: args.world.clone(),
|
||||
position: *args.position,
|
||||
inventory: inventory.clone(),
|
||||
});
|
||||
args.player.open_handled_screen(
|
||||
&LecternScreenFactory {
|
||||
|
||||
Some(Box::new(LecternScreenFactory {
|
||||
inventory,
|
||||
controller,
|
||||
},
|
||||
Some(*args.position),
|
||||
);
|
||||
|
||||
BlockActionResult::Success
|
||||
}))
|
||||
}
|
||||
|
||||
fn use_with_item(&self, args: UseWithItemArgs<'_>) -> BlockActionResult {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{BlockBehaviour, NormalUseArgs, OnPlaceArgs};
|
||||
use crate::block::{BlockBehaviour, GetScreenHandlerFactoryArgs, NormalUseArgs, OnPlaceArgs};
|
||||
use crate::entity::EntityBase;
|
||||
|
||||
use pumpkin_data::block_properties::WallTorchLikeProperties;
|
||||
@ -34,16 +34,31 @@ impl BlockBehaviour for LoomBlock {
|
||||
}
|
||||
|
||||
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::InteractWithLoom as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&LoomScreenFactory, Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
_args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
Some(Box::new(LoomScreenFactory))
|
||||
}
|
||||
}
|
||||
|
||||
struct LoomScreenFactory;
|
||||
|
||||
@ -7,8 +7,8 @@ use crate::block::entities::crafter::CrafterBlockEntity;
|
||||
use crate::block::entities::hopper::HopperBlockEntity;
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{
|
||||
BlockBehaviour, GetComparatorOutputArgs, NormalUseArgs, OnNeighborUpdateArgs, OnPlaceArgs,
|
||||
OnScheduledTickArgs, PlacedArgs,
|
||||
BlockBehaviour, GetComparatorOutputArgs, GetScreenHandlerFactoryArgs, NormalUseArgs,
|
||||
OnNeighborUpdateArgs, OnPlaceArgs, OnScheduledTickArgs, PlacedArgs,
|
||||
};
|
||||
use crate::entity::Entity;
|
||||
use crate::entity::item::ItemEntity;
|
||||
@ -42,9 +42,9 @@ impl ScreenHandlerFactory for CrafterScreenFactory {
|
||||
&self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> Option<SharedScreenHandler> {
|
||||
let handler = create_crafter_3x3(sync_id, player_inventory, self.0.clone());
|
||||
let handler = create_crafter_3x3(sync_id, player_inventory, self.0.clone(), player);
|
||||
let screen_handler_arc = Arc::new(Mutex::new(handler));
|
||||
|
||||
Some(screen_handler_arc as SharedScreenHandler)
|
||||
@ -221,15 +221,28 @@ impl 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()
|
||||
{
|
||||
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
|
||||
.open_handled_screen(&CrafterScreenFactory(inventory), Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.get_inventory()?;
|
||||
Some(Box::new(CrafterScreenFactory(inventory)))
|
||||
}
|
||||
|
||||
fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
|
||||
let mut props = CrafterLikeProperties::default(args.block);
|
||||
let facing = args.direction;
|
||||
|
||||
@ -8,8 +8,8 @@ use crate::block::blocks::redstone::block_receives_redstone_power;
|
||||
use crate::block::blocks::tnt::TNTBlock;
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{
|
||||
BlockBehaviour, GetComparatorOutputArgs, NormalUseArgs, OnNeighborUpdateArgs, OnPlaceArgs,
|
||||
OnScheduledTickArgs, PlacedArgs,
|
||||
BlockBehaviour, GetComparatorOutputArgs, GetScreenHandlerFactoryArgs, NormalUseArgs,
|
||||
OnNeighborUpdateArgs, OnPlaceArgs, OnScheduledTickArgs, PlacedArgs,
|
||||
};
|
||||
use crate::entity::decoration::armor_stand::ArmorStandEntity;
|
||||
use crate::entity::item::ItemEntity;
|
||||
@ -69,9 +69,9 @@ impl ScreenHandlerFactory for DispenserScreenFactory {
|
||||
&self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> Option<SharedScreenHandler> {
|
||||
let handler = create_generic_3x3(sync_id, player_inventory, self.0.clone());
|
||||
let handler = create_generic_3x3(sync_id, player_inventory, self.0.clone(), player);
|
||||
let screen_handler_arc = Arc::new(Mutex::new(handler));
|
||||
|
||||
Some(screen_handler_arc as SharedScreenHandler)
|
||||
@ -124,20 +124,33 @@ const fn to_data3d(facing: Facing) -> i32 {
|
||||
|
||||
impl BlockBehaviour for DispenserBlock {
|
||||
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()
|
||||
{
|
||||
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::InspectDispenser as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&DispenserScreenFactory(inventory), Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.get_inventory()?;
|
||||
Some(Box::new(DispenserScreenFactory(inventory)))
|
||||
}
|
||||
|
||||
fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
|
||||
let mut props = DispenserLikeProperties::default(args.block);
|
||||
props.facing = args.player.get_entity().get_facing().opposite();
|
||||
|
||||
@ -5,8 +5,8 @@ use std::sync::Mutex;
|
||||
use crate::block::blocks::redstone::block_receives_redstone_power;
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{
|
||||
BlockBehaviour, GetComparatorOutputArgs, NormalUseArgs, OnNeighborUpdateArgs, OnPlaceArgs,
|
||||
OnScheduledTickArgs, PlacedArgs,
|
||||
BlockBehaviour, GetComparatorOutputArgs, GetScreenHandlerFactoryArgs, NormalUseArgs,
|
||||
OnNeighborUpdateArgs, OnPlaceArgs, OnScheduledTickArgs, PlacedArgs,
|
||||
};
|
||||
use crate::entity::item::ItemEntity;
|
||||
use crate::entity::{Entity, EntityBase};
|
||||
@ -37,9 +37,9 @@ impl ScreenHandlerFactory for DropperScreenFactory {
|
||||
&self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> Option<SharedScreenHandler> {
|
||||
let handler = create_generic_3x3(sync_id, player_inventory, self.0.clone());
|
||||
let handler = create_generic_3x3(sync_id, player_inventory, self.0.clone(), player);
|
||||
let screen_handler_arc = Arc::new(Mutex::new(handler));
|
||||
|
||||
Some(screen_handler_arc as SharedScreenHandler)
|
||||
@ -86,20 +86,33 @@ const fn to_data3d(facing: Facing) -> i32 {
|
||||
|
||||
impl BlockBehaviour for DropperBlock {
|
||||
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()
|
||||
{
|
||||
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::InspectDropper as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&DropperScreenFactory(inventory), Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.get_inventory()?;
|
||||
Some(Box::new(DropperScreenFactory(inventory)))
|
||||
}
|
||||
|
||||
fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
|
||||
let mut props = DispenserLikeProperties::default(args.block);
|
||||
props.facing = args.player.get_entity().get_facing().opposite();
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::block::{GetComparatorOutputArgs, OnPlaceArgs, OnSyncedBlockEventArgs, PlacedArgs};
|
||||
use crate::block::{
|
||||
GetComparatorOutputArgs, GetScreenHandlerFactoryArgs, OnPlaceArgs, OnSyncedBlockEventArgs,
|
||||
PlacedArgs,
|
||||
};
|
||||
use crate::block::{
|
||||
registry::BlockActionResult,
|
||||
{BlockBehaviour, NormalUseArgs},
|
||||
@ -26,9 +29,9 @@ impl ScreenHandlerFactory for ShulkerBoxScreenFactory {
|
||||
&self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> Option<SharedScreenHandler> {
|
||||
let handler = create_generic_9x3(sync_id, player_inventory, self.0.clone());
|
||||
let handler = create_generic_9x3(sync_id, player_inventory, self.0.clone(), player);
|
||||
let screen_handler_arc = Arc::new(Mutex::new(handler));
|
||||
|
||||
Some(screen_handler_arc as SharedScreenHandler)
|
||||
@ -68,21 +71,34 @@ impl BlockBehaviour for ShulkerBoxBlock {
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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::OpenShulkerBox as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&ShulkerBoxScreenFactory(inventory), Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.get_inventory()?;
|
||||
Some(Box::new(ShulkerBoxScreenFactory(inventory)))
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{BlockBehaviour, NormalUseArgs};
|
||||
use crate::block::{BlockBehaviour, GetScreenHandlerFactoryArgs, NormalUseArgs};
|
||||
|
||||
use pumpkin_data::translation;
|
||||
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
||||
@ -17,16 +17,31 @@ pub struct SmithingTableBlock;
|
||||
|
||||
impl BlockBehaviour for SmithingTableBlock {
|
||||
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::InteractWithSmithingTable as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&SmithingTableScreenFactory, Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
_args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
Some(Box::new(SmithingTableScreenFactory))
|
||||
}
|
||||
}
|
||||
|
||||
struct SmithingTableScreenFactory;
|
||||
|
||||
@ -17,8 +17,8 @@ use pumpkin_world::inventory::Inventory;
|
||||
|
||||
use crate::{
|
||||
block::{
|
||||
BlockBehaviour, BrokenArgs, GetComparatorOutputArgs, NormalUseArgs, OnPlaceArgs,
|
||||
PlacedArgs, registry::BlockActionResult,
|
||||
BlockBehaviour, BrokenArgs, GetComparatorOutputArgs, GetScreenHandlerFactoryArgs,
|
||||
NormalUseArgs, OnPlaceArgs, PlacedArgs, registry::BlockActionResult,
|
||||
},
|
||||
entity::experience_orb::ExperienceOrbEntity,
|
||||
};
|
||||
@ -76,24 +76,39 @@ pub struct SmokerBlock;
|
||||
|
||||
impl BlockBehaviour for SmokerBlock {
|
||||
fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(inventory) = block_entity.clone().get_inventory()
|
||||
&& let Some(property_delegate) = block_entity.clone().to_property_delegate()
|
||||
&& let Some(experience_container) = block_entity.to_experience_container()
|
||||
{
|
||||
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::InteractWithSmoker as i32,
|
||||
1,
|
||||
);
|
||||
let smoker_screen_factory =
|
||||
SmokerScreenFactory::new(inventory, property_delegate, experience_container);
|
||||
args.player
|
||||
.open_handled_screen(&smoker_screen_factory, Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
crate::block::registry::BlockActionResult::Consume
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let block_entity = args.world.get_block_entity(args.position)?;
|
||||
let inventory = block_entity.clone().get_inventory()?;
|
||||
let property_delegate = block_entity.clone().to_property_delegate()?;
|
||||
let experience_container = block_entity.to_experience_container()?;
|
||||
Some(Box::new(SmokerScreenFactory::new(
|
||||
inventory,
|
||||
property_delegate,
|
||||
experience_container,
|
||||
)))
|
||||
}
|
||||
|
||||
fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
|
||||
let mut props = FurnaceLikeProperties::default(args.block);
|
||||
props.facing = args
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{BlockBehaviour, NormalUseArgs, OnPlaceArgs, PathComputationType};
|
||||
use crate::block::{
|
||||
BlockBehaviour, GetScreenHandlerFactoryArgs, NormalUseArgs, OnPlaceArgs, PathComputationType,
|
||||
};
|
||||
|
||||
use pumpkin_data::block_properties::WallTorchLikeProperties;
|
||||
use pumpkin_data::{BlockState, BlockStateId, translation};
|
||||
@ -30,17 +32,32 @@ impl BlockBehaviour for StonecutterBlock {
|
||||
}
|
||||
|
||||
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::InteractWithStonecutter as i32,
|
||||
1,
|
||||
);
|
||||
args.player
|
||||
.open_handled_screen(&StonecutterScreenFactory, Some(*args.position));
|
||||
.open_handled_screen(factory.as_ref(), Some(*args.position));
|
||||
}
|
||||
|
||||
BlockActionResult::Success
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
_args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
Some(Box::new(StonecutterScreenFactory))
|
||||
}
|
||||
|
||||
fn is_pathfindable(&self, _state: &BlockState, _computation_type: PathComputationType) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ use pumpkin_data::BlockDirection;
|
||||
use pumpkin_data::block_rotation::{Mirror, Rotation};
|
||||
use pumpkin_data::data_component_impl::EquipmentSlot;
|
||||
use pumpkin_data::item_stack::ItemStack;
|
||||
use pumpkin_inventory::screen_handler::ScreenHandlerFactory;
|
||||
use pumpkin_protocol::java::server::play::SUseItemOn;
|
||||
use pumpkin_util::math::boundingbox::BoundingBox;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
@ -85,6 +86,13 @@ pub trait BlockBehaviour: Send + Sync {
|
||||
BlockActionResult::Pass
|
||||
}
|
||||
|
||||
fn get_screen_handler_factory(
|
||||
&self,
|
||||
_args: GetScreenHandlerFactoryArgs<'_>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn use_with_item(&self, _args: UseWithItemArgs<'_>) -> BlockActionResult {
|
||||
BlockActionResult::PassToDefaultBlockAction
|
||||
}
|
||||
@ -224,6 +232,15 @@ pub struct NormalUseArgs<'a> {
|
||||
pub hit: &'a BlockHitResult<'a>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GetScreenHandlerFactoryArgs<'a> {
|
||||
pub server: &'a Server,
|
||||
pub world: &'a Arc<World>,
|
||||
pub block: &'a Block,
|
||||
pub position: &'a BlockPos,
|
||||
pub player: &'a Arc<Player>,
|
||||
}
|
||||
|
||||
pub struct UseWithItemArgs<'a> {
|
||||
pub server: &'a Server,
|
||||
pub world: &'a Arc<World>,
|
||||
|
||||
@ -171,9 +171,9 @@ use crate::block::fluid::lava::FlowingLava;
|
||||
use crate::block::fluid::water::FlowingWater;
|
||||
use crate::block::{
|
||||
BlockBehaviour, BlockHitResult, BlockMetadata, BonemealArgs, FluidMetadata,
|
||||
GetInsideCollisionShapeArgs, OnEntityCollisionArgs, OnEntityStepArgs, OnLandedUponArgs,
|
||||
OnProjectileHitArgs, PathComputationType, UpdateEntityMovementAfterFallOnArgs,
|
||||
stop_vertical_movement_after_fall,
|
||||
GetInsideCollisionShapeArgs, GetScreenHandlerFactoryArgs, OnEntityCollisionArgs,
|
||||
OnEntityStepArgs, OnLandedUponArgs, OnProjectileHitArgs, PathComputationType,
|
||||
UpdateEntityMovementAfterFallOnArgs, stop_vertical_movement_after_fall,
|
||||
};
|
||||
use crate::entity::EntityBase;
|
||||
use crate::entity::player::Player;
|
||||
@ -187,6 +187,7 @@ use pumpkin_data::item::Item;
|
||||
use pumpkin_data::item_stack::ItemStack;
|
||||
use pumpkin_data::tag::{self, Taggable};
|
||||
use pumpkin_data::{Block, BlockDirection, BlockId, BlockState};
|
||||
use pumpkin_inventory::screen_handler::ScreenHandlerFactory;
|
||||
use pumpkin_protocol::java::server::play::SUseItemOn;
|
||||
use pumpkin_util::math::boundingbox::BoundingBox;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
@ -905,6 +906,27 @@ impl BlockRegistry {
|
||||
BlockActionResult::Pass
|
||||
}
|
||||
|
||||
pub fn get_screen_handler_factory(
|
||||
&self,
|
||||
block: &Block,
|
||||
player: &Arc<Player>,
|
||||
position: &BlockPos,
|
||||
server: &Server,
|
||||
world: &Arc<World>,
|
||||
) -> Option<Box<dyn ScreenHandlerFactory>> {
|
||||
let pumpkin_block = self.get_pumpkin_block(block.id);
|
||||
if let Some(pumpkin_block) = pumpkin_block {
|
||||
return pumpkin_block.get_screen_handler_factory(GetScreenHandlerFactoryArgs {
|
||||
server,
|
||||
world,
|
||||
block,
|
||||
position,
|
||||
player,
|
||||
});
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn explode(&self, block: &Block, world: &Arc<World>, position: &BlockPos) {
|
||||
let pumpkin_block = self.get_pumpkin_block(block.id);
|
||||
if let Some(pumpkin_block) = pumpkin_block {
|
||||
|
||||
@ -7135,6 +7135,10 @@ impl InventoryPlayer for Player {
|
||||
self.gamemode.load() == GameMode::Creative
|
||||
}
|
||||
|
||||
fn is_spectator(&self) -> bool {
|
||||
self.gamemode.load() == GameMode::Spectator
|
||||
}
|
||||
|
||||
fn experience_level(&self) -> i32 {
|
||||
self.experience_level
|
||||
.load(std::sync::atomic::Ordering::Relaxed)
|
||||
|
||||
@ -182,13 +182,13 @@ impl ScreenHandlerFactory for MinecartScreenFactory {
|
||||
&self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> Option<SharedScreenHandler> {
|
||||
let inventory: Arc<dyn Inventory> = self.inventory.clone();
|
||||
let handler = if self.hopper {
|
||||
create_hopper(sync_id, player_inventory, inventory)
|
||||
create_hopper(sync_id, player_inventory, inventory, player)
|
||||
} else {
|
||||
create_generic_9x3(sync_id, player_inventory, inventory)
|
||||
create_generic_9x3(sync_id, player_inventory, inventory, player)
|
||||
};
|
||||
Some(Arc::new(Mutex::new(handler)) as SharedScreenHandler)
|
||||
}
|
||||
|
||||
@ -159,7 +159,15 @@ impl BedrockClient {
|
||||
};
|
||||
|
||||
if player.gamemode.load() == GameMode::Spectator {
|
||||
// TODO: openMenu ?
|
||||
if let Some(factory) = server.block_registry.get_screen_handler_factory(
|
||||
block,
|
||||
player,
|
||||
&data.block_position,
|
||||
&server,
|
||||
&world,
|
||||
) {
|
||||
player.open_handled_screen(factory.as_ref(), Some(data.block_position));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,36 @@ impl JavaClient {
|
||||
};
|
||||
|
||||
if player.gamemode.load() == GameMode::Spectator {
|
||||
// TODO: openMenu
|
||||
let entity = &player.get_entity();
|
||||
let world = entity.world.load_full();
|
||||
let block = world.get_block(&position);
|
||||
|
||||
let event = PlayerInteractEvent::new(
|
||||
player,
|
||||
InteractAction::RightClickBlock,
|
||||
block,
|
||||
Some(position),
|
||||
);
|
||||
|
||||
send_cancellable_blocking! {{
|
||||
server;
|
||||
event;
|
||||
'cancelled: {
|
||||
let state_id = world.get_block_state_id(&position);
|
||||
player.try_send_client_packet(&CBlockUpdate::new(
|
||||
position,
|
||||
VarInt(i32::from(state_id.as_u16())),
|
||||
));
|
||||
return Ok(());
|
||||
}
|
||||
}}
|
||||
|
||||
if let Some(factory) = server
|
||||
.block_registry
|
||||
.get_screen_handler_factory(block, player, &position, server, &world)
|
||||
{
|
||||
player.open_handled_screen(factory.as_ref(), Some(position));
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user