From a115106899c305df8a0370c3adda9e32296d004c Mon Sep 17 00:00:00 2001 From: Alexander Medvedev Date: Sun, 12 Jan 2025 18:04:06 +0100 Subject: [PATCH] fix screen deadlock --- pumpkin-data/build/sound_category.rs | 1 + pumpkin/src/block/blocks/chest.rs | 9 +++-- pumpkin/src/block/blocks/mod.rs | 54 +++++++++++++++------------- pumpkin/src/entity/player.rs | 33 +++++++++++++++-- pumpkin/src/net/packet/play.rs | 5 ++- pumpkin/src/world/mod.rs | 35 +++++++++--------- 6 files changed, 88 insertions(+), 49 deletions(-) diff --git a/pumpkin-data/build/sound_category.rs b/pumpkin-data/build/sound_category.rs index 09a83cc2..84306951 100644 --- a/pumpkin-data/build/sound_category.rs +++ b/pumpkin-data/build/sound_category.rs @@ -12,6 +12,7 @@ pub(crate) fn build() -> TokenStream { let variants = array_to_tokenstream(sound_categories); quote! { + #[derive(Clone, Copy)] #[repr(u8)] pub enum SoundCategory { #variants diff --git a/pumpkin/src/block/blocks/chest.rs b/pumpkin/src/block/blocks/chest.rs index 9a4c5452..708edbe9 100644 --- a/pumpkin/src/block/blocks/chest.rs +++ b/pumpkin/src/block/blocks/chest.rs @@ -1,5 +1,8 @@ use async_trait::async_trait; -use pumpkin_data::{screen::WindowType, sound::Sound}; +use pumpkin_data::{ + screen::WindowType, + sound::{Sound, SoundCategory}, +}; use pumpkin_inventory::{Chest, OpenContainer}; use pumpkin_macros::pumpkin_block; use pumpkin_protocol::{client::play::CBlockAction, codec::var_int::VarInt}; @@ -114,12 +117,12 @@ impl ChestBlock { if state == ChestState::IsClosed && num_players == 0 { player .world() - .play_block_sound(Sound::BlockChestClose, location) + .play_block_sound(Sound::BlockChestClose, SoundCategory::Blocks, location) .await; } else if state == ChestState::IsOpened && num_players == 1 { player .world() - .play_block_sound(Sound::BlockChestOpen, location) + .play_block_sound(Sound::BlockChestOpen, SoundCategory::Blocks, location) .await; } diff --git a/pumpkin/src/block/blocks/mod.rs b/pumpkin/src/block/blocks/mod.rs index 8ac11597..1a4d452f 100644 --- a/pumpkin/src/block/blocks/mod.rs +++ b/pumpkin/src/block/blocks/mod.rs @@ -70,39 +70,43 @@ pub async fn standard_open_container_unique( server: &Server, window_type: WindowType, ) { - let entity_id = player.entity_id(); - let mut open_containers = server.open_containers.write().await; - let mut id_to_use = -1; + { + let entity_id = player.entity_id(); + let mut open_containers = server.open_containers.write().await; + let mut id_to_use = -1; - // TODO: we can do better than brute force - for (id, container) in open_containers.iter() { - if let Some(a_block) = container.get_block() { - if a_block.id == block.id && container.all_player_ids().is_empty() { - id_to_use = *id as i64; + // TODO: we can do better than brute force + for (id, container) in open_containers.iter() { + if let Some(a_block) = container.get_block() { + if a_block.id == block.id && container.all_player_ids().is_empty() { + id_to_use = *id as i64; + } } } - } - if id_to_use == -1 { - let new_id = server.new_container_id(); - log::debug!("Creating new unqiue container ID: {}", new_id); - let open_container = - OpenContainer::new_empty_container::(entity_id, Some(location), Some(block.clone())); + if id_to_use == -1 { + let new_id = server.new_container_id(); + log::debug!("Creating new unqiue container ID: {}", new_id); + let open_container = OpenContainer::new_empty_container::( + entity_id, + Some(location), + Some(block.clone()), + ); - open_containers.insert(new_id.into(), open_container); + open_containers.insert(new_id.into(), open_container); - player.open_container.store(Some(new_id.into())); - } else { - log::debug!("Using previous unqiue container ID: {}", id_to_use); - if let Some(unique_container) = open_containers.get_mut(&(id_to_use as u64)) { - unique_container.set_location(Some(location)).await; - unique_container.add_player(entity_id); - player - .open_container - .store(Some(id_to_use.try_into().unwrap())); + player.open_container.store(Some(new_id.into())); + } else { + log::debug!("Using previous unqiue container ID: {}", id_to_use); + if let Some(unique_container) = open_containers.get_mut(&(id_to_use as u64)) { + unique_container.set_location(Some(location)).await; + unique_container.add_player(entity_id); + player + .open_container + .store(Some(id_to_use.try_into().unwrap())); + } } } - drop(open_containers); player.open_container(server, window_type).await; } diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index 1515de8c..d95ee7f6 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -14,9 +14,6 @@ use pumpkin_data::{ sound::{Sound, SoundCategory}, }; use pumpkin_inventory::player::PlayerInventory; -use pumpkin_protocol::server::play::{ - SCloseContainer, SCookieResponse as SPCookieResponse, SPlayPingRequest, SPlayerLoaded, -}; use pumpkin_protocol::{ bytebuf::packet_id::Packet, client::play::{ @@ -33,6 +30,12 @@ use pumpkin_protocol::{ }, RawPacket, ServerPacket, }; +use pumpkin_protocol::{ + client::play::CSoundEffect, + server::play::{ + SCloseContainer, SCookieResponse as SPCookieResponse, SPlayPingRequest, SPlayerLoaded, + }, +}; use pumpkin_protocol::{client::play::CUpdateTime, codec::var_int::VarInt}; use pumpkin_protocol::{ client::play::{CSetEntityMetadata, Metadata}, @@ -368,6 +371,30 @@ impl Player { if config.swing {} } + pub async fn play_sound( + &self, + sound_id: u16, + category: SoundCategory, + position: &Vector3, + volume: f32, + pitch: f32, + seed: f64, + ) { + self.client + .send_packet(&CSoundEffect::new( + VarInt(i32::from(sound_id)), + None, + category, + position.x, + position.y, + position.z, + volume, + pitch, + seed, + )) + .await + } + pub async fn await_cancel(&self) { self.cancel_tasks.notified().await; } diff --git a/pumpkin/src/net/packet/play.rs b/pumpkin/src/net/packet/play.rs index 3d47d6ca..3ae48098 100644 --- a/pumpkin/src/net/packet/play.rs +++ b/pumpkin/src/net/packet/play.rs @@ -856,7 +856,8 @@ impl Player { let world = &entity.world; let slot_id = inventory.get_selected(); let mut state_id = inventory.state_id; - let item_slot = inventory.held_item_mut(); + let item_slot = inventory.held_item_mut().clone(); + drop(inventory); if let Some(item_stack) = item_slot { // check if block is interactive @@ -892,6 +893,8 @@ impl Player { // TODO: Config // Decrease Block count if self.gamemode.load() != GameMode::Creative { + let mut inventory = self.inventory().lock().await; + let item_slot = inventory.held_item_mut(); // This should never be possible let Some(item_stack) = item_slot else { return Err(BlockPlacingError::InventoryInvalid.into()); diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 432b9693..52b83b79 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -16,7 +16,7 @@ use pumpkin_data::{ sound::{Sound, SoundCategory}, world::WorldEvent, }; -use pumpkin_protocol::client::play::{CBlockUpdate, CRespawn, CSoundEffect, CWorldEvent}; +use pumpkin_protocol::client::play::{CBlockUpdate, CRespawn, CWorldEvent}; use pumpkin_protocol::{ client::play::CLevelEvent, codec::{identifier::Identifier, var_int::VarInt}, @@ -157,7 +157,8 @@ impl World { } pub async fn play_sound(&self, sound: Sound, category: SoundCategory, position: &Vector3) { - self.play_sound_raw(sound as u16, category, position).await; + self.play_sound_raw(sound as u16, category, position, 1.0, 1.0) + .await; } pub async fn play_sound_raw( @@ -165,30 +166,30 @@ impl World { sound_id: u16, category: SoundCategory, position: &Vector3, + volume: f32, + pitch: f32, ) { let seed = thread_rng().gen::(); - self.broadcast_packet_all(&CSoundEffect::new( - VarInt(i32::from(sound_id)), - None, - category, - position.x, - position.y, - position.z, - 1.0, - 1.0, - seed, - )) - .await; + let players = self.current_players.lock().await; + for (_, player) in players.iter() { + player + .play_sound(sound_id, category, position, volume, pitch, seed) + .await + } } - pub async fn play_block_sound(&self, sound: Sound, position: BlockPos) { + pub async fn play_block_sound( + &self, + sound: Sound, + category: SoundCategory, + position: BlockPos, + ) { let new_vec = Vector3::new( f64::from(position.0.x) + 0.5, f64::from(position.0.y) + 0.5, f64::from(position.0.z) + 0.5, ); - self.play_sound(sound, SoundCategory::Blocks, &new_vec) - .await; + self.play_sound(sound, category, &new_vec).await; } pub async fn play_record(&self, record_id: i32, position: BlockPos) {