diff --git a/pumpkin/src/block/blocks/barrel.rs b/pumpkin/src/block/blocks/barrel.rs index 5057f9d95..8c5458bde 100644 --- a/pumpkin/src/block/blocks/barrel.rs +++ b/pumpkin/src/block/blocks/barrel.rs @@ -60,7 +60,7 @@ impl BlockBehaviour for BarrelBlock { && let Some(inventory) = block_entity.get_inventory() { args.player - .open_handled_screen(&BarrelScreenFactory(inventory)) + .open_handled_screen(&BarrelScreenFactory(inventory), Some(*args.position)) .await; } diff --git a/pumpkin/src/block/blocks/blast_furnace.rs b/pumpkin/src/block/blocks/blast_furnace.rs index 5d07b843b..f883538a8 100644 --- a/pumpkin/src/block/blocks/blast_furnace.rs +++ b/pumpkin/src/block/blocks/blast_furnace.rs @@ -96,7 +96,7 @@ impl BlockBehaviour for BlastFurnaceBlock { experience_container, ); args.player - .open_handled_screen(&blasting_furnace_screen_factory) + .open_handled_screen(&blasting_furnace_screen_factory, Some(*args.position)) .await; } crate::block::registry::BlockActionResult::Consume diff --git a/pumpkin/src/block/blocks/chests.rs b/pumpkin/src/block/blocks/chests.rs index fc35984f6..46e316550 100644 --- a/pumpkin/src/block/blocks/chests.rs +++ b/pumpkin/src/block/blocks/chests.rs @@ -182,7 +182,7 @@ impl BlockBehaviour for ChestBlock { }; args.player - .open_handled_screen(&ChestScreenFactory(inventory)) + .open_handled_screen(&ChestScreenFactory(inventory), Some(*args.position)) .await; BlockActionResult::Success @@ -330,7 +330,7 @@ impl BlockBehaviour for CopperChestBlock { }; args.player - .open_handled_screen(&ChestScreenFactory(inventory)) + .open_handled_screen(&ChestScreenFactory(inventory), Some(*args.position)) .await; BlockActionResult::Success diff --git a/pumpkin/src/block/blocks/crafting_table.rs b/pumpkin/src/block/blocks/crafting_table.rs index c2e7c9c59..3c800cf7f 100644 --- a/pumpkin/src/block/blocks/crafting_table.rs +++ b/pumpkin/src/block/blocks/crafting_table.rs @@ -19,7 +19,7 @@ impl BlockBehaviour for CraftingTableBlock { fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> { Box::pin(async move { args.player - .open_handled_screen(&CraftingTableScreenFactory) + .open_handled_screen(&CraftingTableScreenFactory, Some(*args.position)) .await; BlockActionResult::Success diff --git a/pumpkin/src/block/blocks/ender_chest.rs b/pumpkin/src/block/blocks/ender_chest.rs index b65d47dc3..c0d694504 100644 --- a/pumpkin/src/block/blocks/ender_chest.rs +++ b/pumpkin/src/block/blocks/ender_chest.rs @@ -83,7 +83,10 @@ impl BlockBehaviour for EnderChestBlock { let inventory = args.player.ender_chest_inventory(); inventory.set_tracker(block_entity.get_tracker()).await; args.player - .open_handled_screen(&EnderChestScreenFactory(inventory.clone())) + .open_handled_screen( + &EnderChestScreenFactory(inventory.clone()), + Some(*args.position), + ) .await; // TODO: player.incrementStat(Stats.OPEN_ENDERCHEST); diff --git a/pumpkin/src/block/blocks/furnace.rs b/pumpkin/src/block/blocks/furnace.rs index 312bea01f..d3e9af99e 100644 --- a/pumpkin/src/block/blocks/furnace.rs +++ b/pumpkin/src/block/blocks/furnace.rs @@ -93,7 +93,7 @@ impl BlockBehaviour for FurnaceBlock { let furnace_screen_factory = FurnaceScreenFactory::new(inventory, property_delegate, experience_container); args.player - .open_handled_screen(&furnace_screen_factory) + .open_handled_screen(&furnace_screen_factory, Some(*args.position)) .await; } crate::block::registry::BlockActionResult::Consume diff --git a/pumpkin/src/block/blocks/hopper.rs b/pumpkin/src/block/blocks/hopper.rs index af49e06f8..3135b11b1 100644 --- a/pumpkin/src/block/blocks/hopper.rs +++ b/pumpkin/src/block/blocks/hopper.rs @@ -59,7 +59,7 @@ impl BlockBehaviour for HopperBlock { && let Some(inventory) = block_entity.get_inventory() { args.player - .open_handled_screen(&HopperBlockScreenFactory(inventory)) + .open_handled_screen(&HopperBlockScreenFactory(inventory), Some(*args.position)) .await; } diff --git a/pumpkin/src/block/blocks/redstone/dropper.rs b/pumpkin/src/block/blocks/redstone/dropper.rs index c7c2b280a..680dbdc54 100644 --- a/pumpkin/src/block/blocks/redstone/dropper.rs +++ b/pumpkin/src/block/blocks/redstone/dropper.rs @@ -89,7 +89,7 @@ impl BlockBehaviour for DropperBlock { && let Some(inventory) = block_entity.get_inventory() { args.player - .open_handled_screen(&DropperScreenFactory(inventory)) + .open_handled_screen(&DropperScreenFactory(inventory), Some(*args.position)) .await; } BlockActionResult::Success diff --git a/pumpkin/src/block/blocks/shulker_box.rs b/pumpkin/src/block/blocks/shulker_box.rs index 809a5737e..9f520460e 100644 --- a/pumpkin/src/block/blocks/shulker_box.rs +++ b/pumpkin/src/block/blocks/shulker_box.rs @@ -87,7 +87,7 @@ impl BlockBehaviour for ShulkerBoxBlock { && let Some(inventory) = block_entity.get_inventory() { args.player - .open_handled_screen(&ShulkerBoxScreenFactory(inventory)) + .open_handled_screen(&ShulkerBoxScreenFactory(inventory), Some(*args.position)) .await; } diff --git a/pumpkin/src/block/blocks/smoker.rs b/pumpkin/src/block/blocks/smoker.rs index 143d453d0..a5454aa04 100644 --- a/pumpkin/src/block/blocks/smoker.rs +++ b/pumpkin/src/block/blocks/smoker.rs @@ -91,7 +91,7 @@ impl BlockBehaviour for SmokerBlock { let smoker_screen_factory = SmokerScreenFactory::new(inventory, property_delegate, experience_container); args.player - .open_handled_screen(&smoker_screen_factory) + .open_handled_screen(&smoker_screen_factory, Some(*args.position)) .await; } crate::block::registry::BlockActionResult::Consume diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index 112e5d434..40adf3c78 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -374,6 +374,8 @@ pub struct Player { pub hunger_manager: HungerManager, /// The ID of the currently open container (if any). pub open_container: AtomicCell>, + /// The block position of the currently open container screen (if any). + pub open_container_pos: AtomicCell>, /// The item currently being held by the player. pub carried_item: Mutex>, /// The player's abilities and special powers. @@ -490,6 +492,7 @@ impl Player { hunger_manager: HungerManager::default(), current_block_destroy_stage: AtomicI32::new(-1), open_container: AtomicCell::new(None), + open_container_pos: AtomicCell::new(None), tick_counter: AtomicI32::new(0), packet_sequence: AtomicI32::new(-1), start_mining_time: AtomicI32::new(0), @@ -2577,6 +2580,7 @@ impl Player { } *self.current_screen_handler.lock().await = self.player_screen_handler.clone(); + self.open_container_pos.store(None); } pub async fn on_screen_handler_opened(&self, screen_handler: Arc>) { @@ -2594,6 +2598,7 @@ impl Player { pub async fn open_handled_screen( &self, screen_handler_factory: &dyn ScreenHandlerFactory, + block_pos: Option, ) -> Option { if !self .current_screen_handler @@ -2631,6 +2636,7 @@ impl Player { drop(screen_handler_temp); self.on_screen_handler_opened(screen_handler.clone()).await; *self.current_screen_handler.lock().await = screen_handler; + self.open_container_pos.store(block_pos); Some(self.screen_handler_sync_id.load(Ordering::Relaxed)) } else { //TODO: Send message if spectator diff --git a/pumpkin/src/world/explosion.rs b/pumpkin/src/world/explosion.rs index 04859754b..731f7c27f 100644 --- a/pumpkin/src/world/explosion.rs +++ b/pumpkin/src/world/explosion.rs @@ -207,6 +207,7 @@ impl Explosion { self.damage_entities(world).await; for (pos, (block, state)) in &blocks { world.set_block_state(pos, 0, BlockFlags::NOTIFY_ALL).await; + world.close_container_screens_at(pos).await; let pumpkin_block = world.block_registry.get_pumpkin_block(block.id); diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index be7d71aa0..a7eb448d6 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -2930,6 +2930,9 @@ impl World { let broken_state_id = self.set_block_state(position, new_state_id, flags).await; + // Close container screens for any players viewing this block + self.close_container_screens_at(position).await; + if Block::from_state_id(broken_state_id) != &Block::FIRE { let particles_packet = CWorldEvent::new( WorldEvent::BlockBroken as i32, @@ -2958,6 +2961,16 @@ impl World { None } + /// Close container screens for all players who have a container open at the given block position. + pub async fn close_container_screens_at(&self, position: &BlockPos) { + let players = self.players.load(); + for player in players.iter() { + if player.open_container_pos.load() == Some(*position) { + player.close_handled_screen().await; + } + } + } + pub async fn drop_stack(self: &Arc, pos: &BlockPos, stack: ItemStack) { let height = EntityType::ITEM.dimension[1] / 2.0; let spawn_pos = {