diff --git a/pumpkin/src/entity/experience_orb.rs b/pumpkin/src/entity/experience_orb.rs index c15edc98e..03f35eeb4 100644 --- a/pumpkin/src/entity/experience_orb.rs +++ b/pumpkin/src/entity/experience_orb.rs @@ -87,13 +87,15 @@ impl EntityBase for ExperienceOrbEntity { } async fn on_player_collision(&self, player: &Arc) { - let mut delay = player.experience_pick_up_delay.lock().await; - if *delay == 0 { - *delay = 2; - player.living_entity.pickup(&self.entity, 1).await; - player.add_experience_points(self.amount as i32).await; - // TODO: pickingCount for merging - self.entity.remove().await; + if player.living_entity.health.load() > 0.0 { + let mut delay = player.experience_pick_up_delay.lock().await; + if *delay == 0 { + *delay = 2; + player.living_entity.pickup(&self.entity, 1).await; + player.add_experience_points(self.amount as i32).await; + // TODO: pickingCount for merging + self.entity.remove().await; + } } } diff --git a/pumpkin/src/entity/hunger.rs b/pumpkin/src/entity/hunger.rs index 4eaa48169..7e4703784 100644 --- a/pumpkin/src/entity/hunger.rs +++ b/pumpkin/src/entity/hunger.rs @@ -81,6 +81,13 @@ impl HungerManager { self.exhaustion .store((self.exhaustion.load() + exhaustion).min(40.0)); } + + pub fn restart(&self) { + self.level.store(20); + self.saturation.store(5.0); + self.exhaustion.store(0.0); + self.tick_timer.store(0); + } } #[async_trait] diff --git a/pumpkin/src/entity/item.rs b/pumpkin/src/entity/item.rs index 22e970a67..3ff251746 100644 --- a/pumpkin/src/entity/item.rs +++ b/pumpkin/src/entity/item.rs @@ -98,6 +98,7 @@ impl EntityBase for ItemEntity { }; if can_pickup + && player.living_entity.health.load() > 0.0 && player .inventory .insert_stack_anywhere(&mut *self.item_stack.lock().await) diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index 72bb381cc..c2e4b57e7 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -10,7 +10,7 @@ use async_trait::async_trait; use crossbeam::atomic::AtomicCell; use log::warn; use pumpkin_world::chunk::{ChunkData, ChunkEntityData}; -use pumpkin_world::inventory::Inventory; +use pumpkin_world::inventory::{Clearable, Inventory}; use tokio::sync::{Mutex, RwLock}; use tokio::task::JoinHandle; use uuid::Uuid; @@ -72,10 +72,17 @@ use pumpkin_world::entity::entity_data_flags::{ use pumpkin_world::item::ItemStack; use pumpkin_world::level::{SyncChunk, SyncEntityChunk}; +use super::combat::{self, AttackType, player_attack_sound}; +use super::effect::Effect; +use super::hunger::HungerManager; +use super::item::ItemEntity; +use super::living::LivingEntity; +use super::{Entity, EntityBase, EntityId, NBTStorage}; use crate::block::blocks::bed::BedBlock; use crate::command::client_suggestions; use crate::command::dispatcher::CommandDispatcher; use crate::data::op_data::OPERATOR_CONFIG; +use crate::entity::experience_orb::ExperienceOrbEntity; use crate::error::PumpkinError; use crate::net::GameProfile; use crate::net::{Client, PlayerConfig}; @@ -86,13 +93,6 @@ use crate::server::Server; use crate::world::World; use crate::{PERMISSION_MANAGER, block}; -use super::combat::{self, AttackType, player_attack_sound}; -use super::effect::Effect; -use super::hunger::HungerManager; -use super::item::ItemEntity; -use super::living::LivingEntity; -use super::{Entity, EntityBase, EntityId, NBTStorage}; - const MAX_CACHED_SIGNATURES: u8 = 128; // Vanilla: 128 const MAX_PREVIOUS_MESSAGES: u8 = 20; // Vanilla: 20 @@ -1277,6 +1277,35 @@ impl Player { pub async fn kill(&self) { self.living_entity.kill().await; + + let world = self.world().await; + if !world.level_info.read().await.game_rules.keep_inventory { + let pos = self.living_entity.entity.block_pos.load(); + for item in &self.inventory.main_inventory { + world.drop_stack(&pos, *item.lock().await).await; + } + for item in self + .inventory + .entity_equipment + .lock() + .await + .equipment + .values() + { + world.drop_stack(&pos, *item.lock().await).await; + } + self.inventory.clear().await; + + if self.gamemode.load() != GameMode::Spectator { + ExperienceOrbEntity::spawn( + &world, + pos.to_f64(), + (self.experience_level.load(Ordering::Relaxed) * 7).min(100) as u32, + ) + .await; + } + } + self.handle_killed().await; } diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 65748c163..33cf8c8ad 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -1091,8 +1091,14 @@ impl World { player.send_permission_lvl_update().await; - // Teleport + player.hunger_manager.restart(); + let info = &self.level_info.read().await; + if !info.game_rules.keep_inventory { + player.set_experience(0, 0.0, 0).await; + } + + // Teleport let pitch = 0.0; let (position, yaw) = if let Some(respawn) = player.get_respawn_point().await { respawn