From 314547eb5fbce57b2614a3f27f39d7fcb797c5dd Mon Sep 17 00:00:00 2001 From: Alexander Medvedev Date: Tue, 19 Aug 2025 13:03:52 +0200 Subject: [PATCH] entity: Arc> to Arc This removed a bunch of locks and .awaits, now instead of switching the world inside a entity we will just recreate it in a new World --- pumpkin-world/src/level.rs | 8 +- pumpkin/src/block/blocks/jukebox.rs | 2 +- pumpkin/src/block/blocks/signs.rs | 4 +- pumpkin/src/block/blocks/tnt.rs | 4 +- pumpkin/src/command/commands/fill.rs | 5 +- pumpkin/src/command/commands/particle.rs | 2 +- pumpkin/src/command/commands/seed.rs | 4 +- pumpkin/src/command/commands/setblock.rs | 2 +- pumpkin/src/command/commands/setworldspawn.rs | 2 +- pumpkin/src/command/commands/summon.rs | 2 +- pumpkin/src/command/commands/teleport.rs | 12 +-- pumpkin/src/command/mod.rs | 4 +- .../src/entity/ai/goal/active_target_goal.rs | 2 +- pumpkin/src/entity/ai/goal/look_at_entity.rs | 2 +- .../src/entity/ai/goal/melee_attack_goal.rs | 2 +- .../entity/ai/goal/move_to_target_pos_goal.rs | 4 +- .../ai/goal/step_and_destroy_block_goal.rs | 4 +- .../src/entity/ai/goal/track_target_goal.rs | 7 +- pumpkin/src/entity/ai/path/mod.rs | 2 +- pumpkin/src/entity/experience_orb.rs | 2 - pumpkin/src/entity/falling.rs | 2 - pumpkin/src/entity/hunger.rs | 2 +- pumpkin/src/entity/item.rs | 4 - pumpkin/src/entity/living.rs | 27 ++---- pumpkin/src/entity/mod.rs | 86 ++++++------------- pumpkin/src/entity/player.rs | 81 ++++++++--------- pumpkin/src/entity/tnt.rs | 2 - pumpkin/src/item/items/axe.rs | 2 +- pumpkin/src/item/items/bucket.rs | 4 +- pumpkin/src/item/items/egg.rs | 2 +- pumpkin/src/item/items/ender_eye.rs | 6 +- pumpkin/src/item/items/hoe.rs | 2 +- pumpkin/src/item/items/honeycomb.rs | 2 +- pumpkin/src/item/items/ignite/ignition.rs | 12 +-- pumpkin/src/item/items/minecart.rs | 2 +- pumpkin/src/item/items/shovel.rs | 2 +- pumpkin/src/item/items/snowball.rs | 2 +- pumpkin/src/net/bedrock/play.rs | 2 +- pumpkin/src/net/java/play.rs | 41 ++++----- pumpkin/src/server/mod.rs | 9 +- pumpkin/src/world/chunker.rs | 12 ++- pumpkin/src/world/mod.rs | 6 +- pumpkin/src/world/time.rs | 2 +- 43 files changed, 147 insertions(+), 241 deletions(-) diff --git a/pumpkin-world/src/level.rs b/pumpkin-world/src/level.rs index f5a72ff62..8830390a6 100644 --- a/pumpkin-world/src/level.rs +++ b/pumpkin-world/src/level.rs @@ -656,7 +656,7 @@ impl Level { let (sender, receiver) = mpsc::unbounded_channel(); let level = self.clone(); - log::debug!("Receiving chunks: {}", chunks.len()); + log::trace!("Receiving chunks: {}", chunks.len()); self.spawn_task(async move { let cancel_notifier = level.shutdown_notifier.notified(); @@ -848,8 +848,7 @@ impl Level { let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position(); let chunk = self.get_chunk(chunk_coordinate).await; - let chunk = chunk.read().await; - let Some(id) = chunk.section.get_block_absolute_y( + let Some(id) = chunk.read().await.section.get_block_absolute_y( relative.x as usize, relative.y, relative.z as usize, @@ -863,8 +862,7 @@ impl Level { let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position(); let chunk = self.get_chunk(chunk_coordinate).await; - let chunk = chunk.read().await; - let Some(id) = chunk.section.get_rough_biome_absolute_y( + let Some(id) = chunk.read().await.section.get_rough_biome_absolute_y( relative.x as usize, relative.y, relative.z as usize, diff --git a/pumpkin/src/block/blocks/jukebox.rs b/pumpkin/src/block/blocks/jukebox.rs index fa4411b16..7ef23da51 100644 --- a/pumpkin/src/block/blocks/jukebox.rs +++ b/pumpkin/src/block/blocks/jukebox.rs @@ -48,7 +48,7 @@ impl JukeboxBlock { #[async_trait] impl BlockBehaviour for JukeboxBlock { async fn use_with_item(&self, args: UseWithItemArgs<'_>) -> BlockActionResult { - let world = &args.player.living_entity.entity.world.read().await; + let world = &args.player.living_entity.entity.world; // if the jukebox already has a record, stop playing if self.has_record(args.block, args.position, world).await { diff --git a/pumpkin/src/block/blocks/signs.rs b/pumpkin/src/block/blocks/signs.rs index 94e9b3b11..30fd24f9c 100644 --- a/pumpkin/src/block/blocks/signs.rs +++ b/pumpkin/src/block/blocks/signs.rs @@ -55,7 +55,7 @@ impl BlockBehaviour for SignBlock { } async fn player_placed(&self, args: PlayerPlacedArgs<'_>) { - match &args.player.client { + match args.player.client.as_ref() { crate::net::ClientPlatform::Java(java) => { java.send_sign_packet(*args.position, true).await; } @@ -100,7 +100,7 @@ impl BlockBehaviour for SignBlock { let is_facing_front_text = is_facing_front_text(args.world, args.position, args.block, args.player).await; - match &args.player.client { + match args.player.client.as_ref() { crate::net::ClientPlatform::Java(java) => { java.send_sign_packet(*args.position, is_facing_front_text) .await; diff --git a/pumpkin/src/block/blocks/tnt.rs b/pumpkin/src/block/blocks/tnt.rs index 2a65222ed..f00e2c82a 100644 --- a/pumpkin/src/block/blocks/tnt.rs +++ b/pumpkin/src/block/blocks/tnt.rs @@ -58,8 +58,8 @@ impl BlockBehaviour for TNTBlock { if item != &Item::FLINT_AND_STEEL || item == &Item::FIRE_CHARGE { return BlockActionResult::Pass; } - let world = args.player.world().await; - Self::prime(&world, args.position).await; + let world = args.player.world(); + Self::prime(world, args.position).await; BlockActionResult::Consume } diff --git a/pumpkin/src/command/commands/fill.rs b/pumpkin/src/command/commands/fill.rs index 4573d40ca..578913149 100644 --- a/pumpkin/src/command/commands/fill.rs +++ b/pumpkin/src/command/commands/fill.rs @@ -74,10 +74,7 @@ impl CommandExecutor for Executor { let end_z = from.0.z.max(to.0.z); // TODO: check isInWorldBounds and throw argument.pos.outofbounds - let world = sender - .world() - .await - .ok_or(CommandError::InvalidRequirement)?; + let world = sender.world().ok_or(CommandError::InvalidRequirement)?; let mut placed_blocks = 0; let mut to_update = Vec::new(); match mode { diff --git a/pumpkin/src/command/commands/particle.rs b/pumpkin/src/command/commands/particle.rs index ac7882053..01ef985a3 100644 --- a/pumpkin/src/command/commands/particle.rs +++ b/pumpkin/src/command/commands/particle.rs @@ -63,7 +63,7 @@ impl CommandExecutor for Executor { CommandSender::Player(player) => { let pos = pos.unwrap_or(player.living_entity.entity.pos.load()); - (player.world().await, pos) + (player.world().clone(), pos) } }; diff --git a/pumpkin/src/command/commands/seed.rs b/pumpkin/src/command/commands/seed.rs index f40c6c8bc..54e827ede 100644 --- a/pumpkin/src/command/commands/seed.rs +++ b/pumpkin/src/command/commands/seed.rs @@ -22,9 +22,7 @@ impl CommandExecutor for Executor { _args: &ConsumedArgs<'a>, ) -> Result<(), CommandError> { let seed = match sender { - CommandSender::Player(player) => { - player.living_entity.entity.world.read().await.level.seed.0 - } + CommandSender::Player(player) => player.living_entity.entity.world.level.seed.0, // TODO: Maybe ask player for world, or get the current world _ => match server.worlds.read().await.first() { Some(world) => world.level.seed.0, diff --git a/pumpkin/src/command/commands/setblock.rs b/pumpkin/src/command/commands/setblock.rs index cb7965348..976bbd315 100644 --- a/pumpkin/src/command/commands/setblock.rs +++ b/pumpkin/src/command/commands/setblock.rs @@ -51,7 +51,7 @@ impl CommandExecutor for Executor { .cloned() .ok_or(CommandError::InvalidRequirement)? } - CommandSender::Player(player) => player.world().await, + CommandSender::Player(player) => player.world().clone(), }; let success = match mode { Mode::Destroy => { diff --git a/pumpkin/src/command/commands/setworldspawn.rs b/pumpkin/src/command/commands/setworldspawn.rs index 3de19739b..fd0e029ff 100644 --- a/pumpkin/src/command/commands/setworldspawn.rs +++ b/pumpkin/src/command/commands/setworldspawn.rs @@ -98,7 +98,7 @@ async fn setworldspawn( block_pos: BlockPos, yaw: f32, ) -> Result<(), CommandError> { - let Some(world) = sender.world().await else { + let Some(world) = sender.world() else { return Err(CommandError::CommandFailed(Box::new(TextComponent::text( "Failed to get world.", )))); diff --git a/pumpkin/src/command/commands/summon.rs b/pumpkin/src/command/commands/summon.rs index 521b5c003..55b05fb11 100644 --- a/pumpkin/src/command/commands/summon.rs +++ b/pumpkin/src/command/commands/summon.rs @@ -55,7 +55,7 @@ impl CommandExecutor for Executor { CommandSender::Player(player) => { let pos = pos.unwrap_or(player.living_entity.entity.pos.load()); - (player.world().await, pos) + (player.world().clone(), pos) } }; let mob = from_type(entity, pos, &world, Uuid::new_v4()).await; diff --git a/pumpkin/src/command/commands/teleport.rs b/pumpkin/src/command/commands/teleport.rs index baa8916f2..634a2e2e2 100644 --- a/pumpkin/src/command/commands/teleport.rs +++ b/pumpkin/src/command/commands/teleport.rs @@ -74,7 +74,7 @@ impl CommandExecutor for EntitiesToEntityExecutor { let base_entity = target.get_entity(); let yaw = base_entity.yaw.load(); let pitch = base_entity.pitch.load(); - let world = base_entity.world.read().await.clone(); + let world = base_entity.world.clone(); target .clone() .teleport(pos, yaw.into(), pitch.into(), world) @@ -110,7 +110,7 @@ impl CommandExecutor for EntitiesToPosFacingPosExecutor { CommandSender::Rcon(_) | CommandSender::Console => { server.worlds.read().await.first().unwrap().clone() } - CommandSender::Player(player) => player.world().await, + CommandSender::Player(player) => player.world().clone(), }; for target in targets { @@ -152,7 +152,7 @@ impl CommandExecutor for EntitiesToPosFacingEntityExecutor { pos, Some(yaw), Some(pitch), - facing_entity.get_entity().world.read().await.clone(), + facing_entity.get_entity().world.clone(), ) .await; } @@ -217,7 +217,7 @@ impl CommandExecutor for EntitiesToPosExecutor { CommandSender::Rcon(_) | CommandSender::Console => { server.worlds.read().await.first().unwrap().clone() } - CommandSender::Player(player) => player.world().await, + CommandSender::Player(player) => player.world().clone(), }; for target in targets { let yaw = target.get_entity().yaw.load(); @@ -244,7 +244,7 @@ impl CommandExecutor for SelfToEntityExecutor { ) -> Result<(), CommandError> { let destination = EntityArgumentConsumer::find_arg(args, ARG_DESTINATION)?; let pos = destination.get_entity().pos.load(); - let world = destination.get_entity().world.read().await.clone(); + let world = destination.get_entity().world.clone(); match sender { CommandSender::Player(player) => { @@ -292,7 +292,7 @@ impl CommandExecutor for SelfToPosExecutor { } player .clone() - .teleport(pos, Some(yaw), Some(pitch), player.world().await) + .teleport(pos, Some(yaw), Some(pitch), player.world().clone()) .await; } _ => { diff --git a/pumpkin/src/command/mod.rs b/pumpkin/src/command/mod.rs index 9fb7392ea..93e2ae505 100644 --- a/pumpkin/src/command/mod.rs +++ b/pumpkin/src/command/mod.rs @@ -100,11 +100,11 @@ impl CommandSender { } #[must_use] - pub async fn world(&self) -> Option> { + pub fn world(&self) -> Option> { match self { // TODO: maybe return first world when console Self::Console | Self::Rcon(..) => None, - Self::Player(p) => Some(p.living_entity.entity.world.read().await.clone()), + Self::Player(p) => Some(p.living_entity.entity.world.clone()), } } diff --git a/pumpkin/src/entity/ai/goal/active_target_goal.rs b/pumpkin/src/entity/ai/goal/active_target_goal.rs index 42a77567e..22f087639 100644 --- a/pumpkin/src/entity/ai/goal/active_target_goal.rs +++ b/pumpkin/src/entity/ai/goal/active_target_goal.rs @@ -73,7 +73,7 @@ impl ActiveTargetGoal { async fn find_closest_target(&self, mob: &MobEntity) { let mut target = self.target.lock().await; - let world = mob.living_entity.entity.world.read().await; + let world = &mob.living_entity.entity.world; if self.target_type == &EntityType::PLAYER { *target = world .get_closest_player( diff --git a/pumpkin/src/entity/ai/goal/look_at_entity.rs b/pumpkin/src/entity/ai/goal/look_at_entity.rs index 1b147b161..3b9f7bb9c 100644 --- a/pumpkin/src/entity/ai/goal/look_at_entity.rs +++ b/pumpkin/src/entity/ai/goal/look_at_entity.rs @@ -95,7 +95,7 @@ impl Goal for LookAtEntityGoal { } drop(mob_target); - let world = mob_entity.living_entity.entity.world.read().await; + let world = &mob_entity.living_entity.entity.world; if self.target_type == &EntityType::PLAYER { *target = world .get_closest_player(mob_entity.living_entity.entity.pos.load(), self.range) diff --git a/pumpkin/src/entity/ai/goal/melee_attack_goal.rs b/pumpkin/src/entity/ai/goal/melee_attack_goal.rs index d6649172d..8ba8ea703 100644 --- a/pumpkin/src/entity/ai/goal/melee_attack_goal.rs +++ b/pumpkin/src/entity/ai/goal/melee_attack_goal.rs @@ -49,7 +49,7 @@ impl MeleeAttackGoal { impl Goal for MeleeAttackGoal { async fn can_start(&self, mob: &dyn Mob) -> bool { let time = { - let world = mob.get_entity().world.read().await; + let world = &mob.get_entity().world; let level_time = world.level_time.lock().await; level_time.world_age }; diff --git a/pumpkin/src/entity/ai/goal/move_to_target_pos_goal.rs b/pumpkin/src/entity/ai/goal/move_to_target_pos_goal.rs index 5b13f36f6..2e37b18d1 100644 --- a/pumpkin/src/entity/ai/goal/move_to_target_pos_goal.rs +++ b/pumpkin/src/entity/ai/goal/move_to_target_pos_goal.rs @@ -82,7 +82,7 @@ impl MoveToTargetPosGoal { block_pos_mutable.0.z = block_pos.0.z + n; // Make sure the world lock is dropped { - let world = mob.get_entity().world.read().await; + let world = &mob.get_entity().world; let can_target = if let Some(x) = self.move_to_target_pos.upgrade() { x.is_target_pos(world.clone(), block_pos_mutable).await } else { @@ -144,7 +144,7 @@ impl Goal for MoveToTargetPosGoal { } async fn should_continue(&self, mob: &dyn Mob) -> bool { - let world = mob.get_entity().world.read().await; + let world = &mob.get_entity().world; let can_target = if let Some(x) = self.move_to_target_pos.upgrade() { x.is_target_pos(world.clone(), self.target_pos.load()).await } else { diff --git a/pumpkin/src/entity/ai/goal/step_and_destroy_block_goal.rs b/pumpkin/src/entity/ai/goal/step_and_destroy_block_goal.rs index dd2c1335d..5a5f87a1e 100644 --- a/pumpkin/src/entity/ai/goal/step_and_destroy_block_goal.rs +++ b/pumpkin/src/entity/ai/goal/step_and_destroy_block_goal.rs @@ -93,7 +93,7 @@ pub trait Stepping: Send + Sync { #[async_trait] impl Goal for StepAndDestroyBlockGoal { async fn can_start(&self, mob: &dyn Mob) -> bool { - let world = mob.get_entity().world.read().await; + let world = &mob.get_entity().world; let level_info = world.level_info.read().await; if !level_info.game_rules.mob_griefing { false @@ -129,7 +129,7 @@ impl Goal for StepAndDestroyBlockGoal { async fn tick(&self, mob: &dyn Mob) { self.move_to_target_pos_goal.tick(mob).await; let mob_entity = mob.get_mob_entity(); - let world = mob.get_entity().world.read().await; + let world = &mob.get_entity().world; let block_pos = mob.get_entity().block_pos.load(); let tweak_pos = self.tweak_to_proper_pos(block_pos, world.clone()).await; // TODO: drop world? diff --git a/pumpkin/src/entity/ai/goal/track_target_goal.rs b/pumpkin/src/entity/ai/goal/track_target_goal.rs index cd12265f2..0d3b48fb2 100644 --- a/pumpkin/src/entity/ai/goal/track_target_goal.rs +++ b/pumpkin/src/entity/ai/goal/track_target_goal.rs @@ -66,25 +66,24 @@ impl TrackTargetGoal { false } - pub async fn can_track( + pub fn can_track( &self, mob: &dyn Mob, target: Option<&LivingEntity>, - target_predicate: TargetPredicate, + target_predicate: &TargetPredicate, ) -> bool { if target.is_none() { return false; } let mob_entity = mob.get_mob_entity(); let target = target.unwrap(); - let world = mob_entity.living_entity.entity.world.read().await; + let world = &mob_entity.living_entity.entity.world; if !target_predicate.test(world.clone(), Some(&mob_entity.living_entity), target) { return false; } /*else if (!this.mob.isInPositionTargetRange(target.getBlockPos())) { return false; }*/ // TODO: implement this - drop(world); // Drop the lock because is useless now if self.check_can_navigate { if self.check_can_navigate_cooldown.fetch_sub(1, Relaxed) - 1 <= 0 { diff --git a/pumpkin/src/entity/ai/path/mod.rs b/pumpkin/src/entity/ai/path/mod.rs index 48a84183f..a5c63d782 100644 --- a/pumpkin/src/entity/ai/path/mod.rs +++ b/pumpkin/src/entity/ai/path/mod.rs @@ -35,7 +35,7 @@ impl Navigator { let mut best_move = Vector3::new(0.0, 0.0, 0.0); let mut lowest_cost = f64::MAX; - let world = entity.entity.world.read().await; + let world = &entity.entity.world; for x in -1..=1 { for z in -1..=1 { diff --git a/pumpkin/src/entity/experience_orb.rs b/pumpkin/src/entity/experience_orb.rs index 503a7a7d7..a8cc43807 100644 --- a/pumpkin/src/entity/experience_orb.rs +++ b/pumpkin/src/entity/experience_orb.rs @@ -89,8 +89,6 @@ impl EntityBase for ExperienceOrbEntity { let no_clip = !self .entity .world - .read() - .await .is_space_empty(bounding_box.expand(-1.0e-7, -1.0e-7, -1.0e-7)) .await; // TODO: isSubmergedIn diff --git a/pumpkin/src/entity/falling.rs b/pumpkin/src/entity/falling.rs index 4b8d9b67a..a377fe4e5 100644 --- a/pumpkin/src/entity/falling.rs +++ b/pumpkin/src/entity/falling.rs @@ -71,8 +71,6 @@ impl EntityBase for FallingEntity { entity.velocity.store(velo.multiply(0.7, -0.5, 0.7)); entity .world - .read() - .await .set_block_state( &self.entity.block_pos.load(), self.block_state_id, diff --git a/pumpkin/src/entity/hunger.rs b/pumpkin/src/entity/hunger.rs index 755bc0cb1..600c2a8e3 100644 --- a/pumpkin/src/entity/hunger.rs +++ b/pumpkin/src/entity/hunger.rs @@ -32,7 +32,7 @@ impl HungerManager { let level = self.level.load(); let exhaustion = self.exhaustion.load(); let health = player.living_entity.health.load(); - let difficulty = player.world().await.level_info.read().await.difficulty; + let difficulty = player.world().level_info.read().await.difficulty; // Decrease hunger level on exhaustion if level != 0 && exhaustion > 4.0 { self.exhaustion.store(exhaustion - 4.0); diff --git a/pumpkin/src/entity/item.rs b/pumpkin/src/entity/item.rs index 6828a3362..7977a4b1b 100644 --- a/pumpkin/src/entity/item.rs +++ b/pumpkin/src/entity/item.rs @@ -91,8 +91,6 @@ impl ItemEntity { let items: Vec<_> = self .entity .world - .read() - .await .entities .read() .await @@ -239,8 +237,6 @@ impl EntityBase for ItemEntity { let no_clip = !self .entity .world - .read() - .await .is_space_empty(bounding_box.expand(-1.0e-7, -1.0e-7, -1.0e-7)) .await; diff --git a/pumpkin/src/entity/living.rs b/pumpkin/src/entity/living.rs index 0e8c1e0d1..fb220c1af 100644 --- a/pumpkin/src/entity/living.rs +++ b/pumpkin/src/entity/living.rs @@ -121,8 +121,6 @@ impl LivingEntity { .collect(); self.entity .world - .read() - .await .broadcast_packet_except( &[self.entity.entity_uuid], &CSetEquipment::new(self.entity_id().into(), equipment), @@ -135,8 +133,6 @@ impl LivingEntity { // TODO: Only nearby self.entity .world - .read() - .await .broadcast_packet_all(&CTakeItemEntity::new( item.entity_id.into(), self.entity.entity_id.into(), @@ -175,8 +171,6 @@ impl LivingEntity { self.active_effects.lock().await.remove(&effect_type); self.entity .world - .read() - .await .send_remove_mob_effect(&self.entity, effect_type) .await; } @@ -193,16 +187,14 @@ impl LivingEntity { // Check if the entity is in water pub async fn is_in_water(&self) -> bool { - let world = self.entity.world.read().await; let block_pos = self.entity.block_pos.load(); - world.get_block(&block_pos).await == &Block::WATER + self.entity.world.get_block(&block_pos).await == &Block::WATER } // Check if the entity is in powder snow pub async fn is_in_powder_snow(&self) -> bool { - let world = self.entity.world.read().await; let block_pos = self.entity.block_pos.load(); - world.get_block(&block_pos).await == &Block::POWDER_SNOW + self.entity.world.get_block(&block_pos).await == &Block::POWDER_SNOW } async fn get_effective_gravity(&self, caller: &Arc) -> f64 { @@ -462,8 +454,6 @@ impl LivingEntity { && !self .entity .world - .read() - .await .check_fluid_collision(self.entity.bounding_box.load().shift(velo)) .await { @@ -742,7 +732,7 @@ impl LivingEntity { source: Option<&dyn EntityBase>, cause: Option<&dyn EntityBase>, ) { - let world = self.entity.world.read().await; + let world = &self.entity.world; let dyn_self = world .get_entity_by_id(self.entity.entity_id) .await @@ -784,10 +774,9 @@ impl LivingEntity { async fn drop_loot(&self, params: LootContextParameters) { if let Some(loot_table) = &self.get_entity().entity_type.loot_table { - let world = self.entity.world.read().await; let pos = self.entity.block_pos.load(); for stack in loot_table.get_loot(params) { - world.drop_stack(&pos, stack).await; + self.entity.world.drop_stack(&pos, stack).await; } } } @@ -906,7 +895,7 @@ impl EntityBase for LivingEntity { return false; // Fire resistance } - let world = self.entity.world.read().await; + let world = &self.entity.world; let last_damage = self.last_damage_taken.load(); let play_sound; @@ -935,8 +924,6 @@ impl EntityBase for LivingEntity { self.entity .world - .read() - .await .broadcast_packet_all(&CDamageEvent::new( self.entity.entity_id.into(), damage_type.id.into(), @@ -949,8 +936,6 @@ impl EntityBase for LivingEntity { if play_sound { self.entity .world - .read() - .await .play_sound( // Sound::EntityPlayerHurt, Sound::EntityGenericHurt, @@ -997,8 +982,6 @@ impl EntityBase for LivingEntity { // Spawn Death particles self.entity .world - .read() - .await .send_entity_status(&self.entity, EntityStatus::AddDeathParticles) .await; self.entity.remove().await; diff --git a/pumpkin/src/entity/mod.rs b/pumpkin/src/entity/mod.rs index 763b8306f..17e6b1df2 100644 --- a/pumpkin/src/entity/mod.rs +++ b/pumpkin/src/entity/mod.rs @@ -47,7 +47,7 @@ use std::sync::{ Ordering::{self, Relaxed}, }, }; -use tokio::sync::{Mutex, RwLock}; +use tokio::sync::Mutex; pub mod ai; pub mod decoration; @@ -234,7 +234,7 @@ pub struct Entity { /// The type of entity (e.g., player, zombie, item) pub entity_type: &'static EntityType, /// The world in which the entity exists. - pub world: Arc>>, + pub world: Arc, /// The entity's current position in the world pub pos: AtomicCell>, /// The last known position of the entity. @@ -351,7 +351,7 @@ impl Entity { get_section_cord(floor_z), )), sneaking: AtomicBool::new(false), - world: Arc::new(RwLock::new(world)), + world, sprinting: AtomicBool::new(false), fall_flying: AtomicBool::new(false), yaw: AtomicCell::new(0.0), @@ -397,8 +397,6 @@ impl Entity { pub async fn send_velocity(&self) { let velocity = self.velocity.load(); self.world - .read() - .await .broadcast_packet_all(&CEntityVelocity::new(self.entity_id.into(), velocity)) .await; } @@ -486,8 +484,6 @@ impl Entity { let pitch = (pitch * 256.0 / 360.0).rem_euclid(256.0); self.world - .read() - .await .broadcast_packet_all(&CUpdateEntityRot::new( self.entity_id.into(), yaw, @@ -501,8 +497,6 @@ impl Entity { pub async fn send_head_rot(&self, head_yaw: u8) { self.world - .read() - .await .broadcast_packet_all(&CHeadRot::new(self.entity_id.into(), head_yaw)) .await; } @@ -531,8 +525,6 @@ impl Entity { let (collisions, block_positions) = self .world - .read() - .await .get_block_collisions(bounding_box.stretch(movement)) .await; @@ -765,13 +757,12 @@ impl Entity { eye_level_box.max.y = eye_level_box.min.y; - let world = self.world.read().await; for x in min.0.x..=max.0.x { for y in min.0.y..=max.0.y { for z in min.0.z..=max.0.z { let pos = BlockPos::new(x, y, z); - let (block, state) = world.get_block_and_state(&pos).await; + let (block, state) = self.world.get_block_and_state(&pos).await; let collided = World::check_outline( &bounding_box, @@ -784,11 +775,11 @@ impl Entity { ); if collided { - world + self.world .block_registry .on_entity_collision( block, - &world, + &self.world, caller.as_ref(), &pos, state, @@ -827,8 +818,6 @@ impl Entity { let pitch = (pitch * 256.0 / 360.0).rem_euclid(256.0); self.world - .read() - .await .broadcast_packet_all(&CUpdateEntityPosRot::new( self.entity_id.into(), Vector3::new(converted.x, converted.y, converted.z), @@ -859,8 +848,6 @@ impl Entity { ); self.world - .read() - .await .broadcast_packet_all(&CUpdateEntityPos::new( self.entity_id.into(), Vector3::new(converted.x, converted.y, converted.z), @@ -900,14 +887,12 @@ impl Entity { let max = bounding_box.max_block_pos(); - let world = self.world.read().await; - for x in min.0.x..=max.0.x { for y in min.0.y..=max.0.y { for z in min.0.z..=max.0.z { let pos = BlockPos::new(x, y, z); - let (fluid, state) = world.get_fluid_and_fluid_state(&pos).await; + let (fluid, state) = self.world.get_fluid_and_fluid_state(&pos).await; if fluid.id != Fluid::EMPTY.id { let marginal_height = @@ -929,7 +914,7 @@ impl Entity { } let mut fluid_velo = - world.get_fluid_velocity(pos, &fluid, &state).await; + self.world.get_fluid_velocity(pos, &fluid, &state).await; if fluid_height[i] < 0.4 { fluid_velo = fluid_velo * fluid_height[i]; @@ -949,18 +934,17 @@ impl Entity { // BTreeMap auto-sorts water before lava as in vanilla for (_, fluid) in fluids { - world + self.world .block_registry .on_entity_collision_fluid(&fluid, caller.as_ref()) .await; } - let lava_speed = - if self.world.read().await.dimension_type == VanillaDimensionType::TheNether { - 0.007 - } else { - 0.002_333_333 - }; + let lava_speed = if self.world.dimension_type == VanillaDimensionType::TheNether { + 0.007 + } else { + 0.002_333_333 + }; self.push_by_fluid(0.014, fluid_push[0], fluid_n[0]); @@ -1035,12 +1019,7 @@ impl Entity { ) { if let Some(mut supporting_block) = self.supporting_block_pos.load() { if offset > 1.0e-5 { - let (block, state) = self - .world - .read() - .await - .get_block_and_state(&supporting_block) - .await; + let (block, state) = self.world.get_block_and_state(&supporting_block).await; // if let Some(props) = block.properties(state.id) { // let name = props.; @@ -1080,7 +1059,7 @@ impl Entity { if let (Some(b), Some(s)) = (block, state) { (pos, b, s) } else { - let (b, s) = self.world.read().await.get_block_and_state(&pos).await; + let (b, s) = self.world.get_block_and_state(&pos).await; (pos, b, s) } @@ -1125,12 +1104,7 @@ impl Entity { #[allow(clippy::float_cmp)] async fn get_velocity_multiplier(&self) -> f32 { - let block = self - .world - .read() - .await - .get_block(&self.block_pos.load()) - .await; + let block = self.world.get_block(&self.block_pos.load()).await; let multiplier = block.velocity_multiplier; @@ -1147,8 +1121,6 @@ impl Entity { async fn get_jump_velocity_multiplier(&self) -> f32 { let f = self .world - .read() - .await .get_block(&self.block_pos.load()) .await .jump_velocity_multiplier; @@ -1225,8 +1197,6 @@ impl Entity { if self .world - .read() - .await .get_block_state(&block_pos.offset(offset)) .await .is_full_cube() @@ -1288,7 +1258,7 @@ impl Entity { }; // TODO: this is bad let scale_factor_current = - if self.world.read().await.dimension_type == VanillaDimensionType::TheNether { + if self.world.dimension_type == VanillaDimensionType::TheNether { 8.0 } else { 1.0 @@ -1364,7 +1334,7 @@ impl Entity { /// Removes the `Entity` from their current `World` pub async fn remove(&self) { - self.world.read().await.remove_entity(self).await; + self.world.remove_entity(self).await; } pub fn create_spawn_packet(&self) -> CSpawnEntity { @@ -1588,8 +1558,6 @@ impl Entity { /// Plays sound at this entity's position with the entity's sound category pub async fn play_sound(&self, sound: Sound) { self.world - .read() - .await .play_sound(sound, SoundCategory::Neutral, &self.pos.load()) .await; } @@ -1604,8 +1572,6 @@ impl Entity { } buf.put_u8(255); self.world - .read() - .await .broadcast_packet_all(&CSetEntityMetadata::new(self.entity_id.into(), buf.into())) .await; } @@ -1634,7 +1600,7 @@ impl Entity { (aabb.max.y - 0.001).floor() as i32, (aabb.max.z - 0.001).floor() as i32, ); - let world = entity.get_entity().world.read().await; + let world = &entity.get_entity().world; for x in blockpos.0.x..=blockpos1.0.x { for y in blockpos.0.y..=blockpos1.0.y { @@ -1647,7 +1613,7 @@ impl Entity { if outlines.is_empty() { world .block_registry - .on_entity_collision(block, &world, entity, &pos, state, server) + .on_entity_collision(block, world, entity, &pos, state, server) .await; let fluid = world.get_fluid(&pos).await; world @@ -1661,7 +1627,7 @@ impl Entity { if outline_aabb.intersects(&aabb) { world .block_registry - .on_entity_collision(block, &world, entity, &pos, state, server) + .on_entity_collision(block, world, entity, &pos, state, server) .await; let fluid = world.get_fluid(&pos).await; world @@ -1674,7 +1640,7 @@ impl Entity { } else { world .block_registry - .on_entity_collision(block, &world, entity, &pos, state, server) + .on_entity_collision(block, world, entity, &pos, state, server) .await; let fluid = world.get_fluid(&pos).await; world @@ -1696,8 +1662,6 @@ impl Entity { ) { // TODO: handle world change self.world - .read() - .await .broadcast_packet_all(&CEntityPositionSync::new( self.entity_id.into(), position, @@ -1731,9 +1695,7 @@ impl Entity { } pub async fn check_out_of_world(&self, dyn_self: &dyn EntityBase) { - if self.pos.load().y - < f64::from(self.world.read().await.generation_settings().shape.min_y) - 64.0 - { + if self.pos.load().y < f64::from(self.world.generation_settings().shape.min_y) - 64.0 { // Tick out of world damage dyn_self.damage(4.0, DamageType::OUT_OF_WORLD).await; } diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index f652d5474..b620636e9 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -200,7 +200,7 @@ pub struct Player { /// The player's game profile information, including their username and UUID. pub gameprofile: GameProfile, /// The client connection associated with the player. - pub client: ClientPlatform, + pub client: Arc, /// The player's inventory. pub inventory: Arc, /// The player's configuration settings. Changes when the player changes their settings. @@ -278,7 +278,7 @@ pub struct Player { impl Player { pub async fn new( - client: ClientPlatform, + client: Arc, gameprofile: GameProfile, config: PlayerConfig, world: Arc, @@ -397,9 +397,8 @@ impl Player { } /// Removes the [`Player`] out of the current [`World`]. - #[allow(unused_variables)] pub async fn remove(self: &Arc) { - let world = self.world().await; + let world = self.world(); world.remove_player(self, true).await; let cylindrical = self.watched_section.load(); @@ -437,7 +436,7 @@ impl Player { } pub async fn attack(&self, victim: Arc) { - let world = self.world().await; + let world = self.world(); let victim_entity = victim.get_entity(); let attacker_entity = &self.living_entity.entity; let config = &advanced_config().pvp; @@ -513,22 +512,17 @@ impl Player { if victim.get_living_entity().is_some() { let mut knockback_strength = 1.0; - player_attack_sound(&pos, &world, attack_type).await; + player_attack_sound(&pos, world, attack_type).await; match attack_type { AttackType::Knockback => knockback_strength += 1.0, AttackType::Sweeping => { - combat::spawn_sweep_particle(attacker_entity, &world, &pos).await; + combat::spawn_sweep_particle(attacker_entity, world, &pos).await; } _ => {} } if config.knockback { - combat::handle_knockback( - attacker_entity, - &world, - victim_entity, - knockback_strength, - ) - .await; + combat::handle_knockback(attacker_entity, world, victim_entity, knockback_strength) + .await; } } @@ -564,7 +558,7 @@ impl Player { pub async fn get_respawn_point(&self) -> Option<(Vector3, f32)> { let respawn_point = self.respawn_point.load()?; - let block = self.world().await.get_block(&respawn_point.position).await; + let block = self.world().get_block(&respawn_point.position).await; if respawn_point.dimension == VanillaDimensionType::Overworld && block.is_tagged_with_by_tag(&tag::Block::MINECRAFT_BEDS) @@ -629,14 +623,14 @@ impl Player { } pub async fn wake_up(&self) { - let world = self.world().await; + let world = self.world(); let respawn_point = self .respawn_point .load() .expect("Player waking up should have it's respawn point set on the bed."); let (bed, bed_state) = world.get_block_and_state_id(&respawn_point.position).await; - BedBlock::set_occupied(false, &world, bed, &respawn_point.position, bed_state).await; + BedBlock::set_occupied(false, world, bed, &respawn_point.position, bed_state).await; self.living_entity .entity @@ -760,7 +754,7 @@ impl Player { let chunk_of_chunks = { let mut chunk_manager = self.chunk_manager.lock().await; - if let ClientPlatform::Java(_) = &self.client { + if let ClientPlatform::Java(_) = self.client.as_ref() { // Java clients can only send a limited amount of chunks per tick. // If we have sent too many chunks without receiving an ack, we stop sending chunks. chunk_manager @@ -773,7 +767,7 @@ impl Player { if let Some(chunk_of_chunks) = chunk_of_chunks { let chunk_count = chunk_of_chunks.len(); - match &self.client { + match self.client.as_ref() { ClientPlatform::Java(java_client) => { java_client.send_packet_now(&CChunkBatchStart).await; for chunk in chunk_of_chunks { @@ -811,7 +805,7 @@ impl Player { if self.mining.load(Ordering::Relaxed) { let pos = self.mining_pos.lock().await; - let world = self.world().await; + let world = self.world(); let state = world.get_block_state(&pos).await; // Is the block broken? if state.is_air() { @@ -824,7 +818,7 @@ impl Player { } else { self.continue_mining( *pos, - &world, + world, state, self.start_mining_time.load(Ordering::Relaxed), ) @@ -847,7 +841,7 @@ impl Player { // TODO This should only be handled by the ClientPlatform let now = Instant::now(); if now.duration_since(self.last_keep_alive_time.load()) >= Duration::from_secs(15) { - if matches!(self.client, ClientPlatform::Bedrock(_)) { + if matches!(self.client.as_ref(), ClientPlatform::Bedrock(_)) { return; } // We never got a response from the last keep alive we sent. @@ -934,8 +928,8 @@ impl Player { self.living_entity.entity.entity_id } - pub async fn world(&self) -> Arc { - self.living_entity.entity.world.read().await.clone() + pub fn world(&self) -> &Arc { + &self.living_entity.entity.world } pub fn position(&self) -> Vector3 { @@ -998,14 +992,13 @@ impl Player { PermissionLvl::Four => EntityStatus::SetOpLevel4, }; self.world() - .await .send_entity_status(&self.living_entity.entity, status) .await; } /// Sets the player's difficulty level. pub async fn send_difficulty_update(&self) { - let world = self.world().await; + let world = self.world(); let level_info = world.level_info.read().await; self.client .enqueue_packet(&CChangeDifficulty::new( @@ -1029,7 +1022,7 @@ impl Player { /// Sends the world time to only this player. pub async fn send_time(&self, world: &World) { let l_world = world.level_time.lock().await; - match &self.client { + match self.client.as_ref() { ClientPlatform::Java(java_client) => { java_client .enqueue_packet(&CUpdateTime::new( @@ -1074,7 +1067,7 @@ impl Player { yaw: Option, pitch: Option, ) { - let current_world = self.living_entity.entity.world.read().await.clone(); + let current_world = self.living_entity.entity.world.clone(); let yaw = yaw.unwrap_or(new_world.level_info.read().await.spawn_angle); let pitch = pitch.unwrap_or(10.0); @@ -1099,12 +1092,18 @@ impl Player { self.set_client_loaded(false); let uuid = self.gameprofile.id; current_world.remove_player(self, false).await; - *self.living_entity.entity.world.write().await = new_world.clone(); - new_world.players.write().await.insert(uuid, self.clone()); + new_world.players.write().await.insert(uuid, Arc::new(Self::new( + self.client.clone(), + self.gameprofile.clone(), + self.config.read().await.clone(), + new_world.clone(), + self.gamemode.load(), + ) + .await)); self.unload_watched_chunks(¤t_world).await; let last_pos = self.living_entity.entity.last_pos.load(); - let death_dimension = self.world().await.dimension_type.resource_location(); + let death_dimension = self.world().dimension_type.resource_location(); let death_location = BlockPos(Vector3::new( last_pos.x.round() as i32, last_pos.y.round() as i32, @@ -1305,8 +1304,6 @@ impl Player { self.living_entity .entity .world - .read() - .await .broadcast_packet_all(&CPlayerInfoUpdate::new( PlayerInfoFlags::UPDATE_GAME_MODE.bits(), &[pumpkin_protocol::java::client::play::Player { @@ -1425,7 +1422,7 @@ impl Player { + Vector3::new(0.0, f64::from(EntityType::PLAYER.eye_height) - 0.3, 0.0); let entity = Entity::new( Uuid::new_v4(), - self.world().await, + self.world().clone(), item_pos, &EntityType::ITEM, false, @@ -1449,7 +1446,7 @@ impl Player { // TODO: Merge stacks together let item_entity = Arc::new(ItemEntity::new_with_velocity(entity, item_stack, velocity, 40).await); - self.world().await.spawn_entity(item_entity).await; + self.world().spawn_entity(item_entity).await; } pub async fn drop_held_item(&self, drop_stack: bool) { @@ -1855,7 +1852,7 @@ impl Player { /// Swing the hand of the player pub async fn swing_hand(&self, hand: Hand, all: bool) { - let world = self.world().await; + let world = self.world(); let entity_id = VarInt(self.entity_id()); let animation = match hand { @@ -1906,11 +1903,7 @@ impl NBTStorage for Player { nbt.put_string( "Dimension", - self.world() - .await - .dimension_type - .resource_location() - .to_string(), + self.world().dimension_type.resource_location().to_string(), ); } @@ -2072,8 +2065,6 @@ impl EntityBase for Player { .living_entity .entity .world - .read() - .await .get_entity_by_id(self.living_entity.entity.entity_id) .await .expect("Entity not found in world"); @@ -2099,7 +2090,7 @@ impl EntityBase for Player { pitch: Option, world: Arc, ) { - if Arc::ptr_eq(&world, &self.world().await) { + if Arc::ptr_eq(&world, self.world()) { // Same world let yaw = yaw.unwrap_or(self.living_entity.entity.yaw.load()); let pitch = pitch.unwrap_or(self.living_entity.entity.pitch.load()); @@ -2116,8 +2107,6 @@ impl EntityBase for Player { self.request_teleport(position, yaw, pitch).await; entity .world - .read() - .await .broadcast_packet_except(&[self.gameprofile.id], &CEntityPositionSync::new( self.living_entity.entity.entity_id.into(), position, diff --git a/pumpkin/src/entity/tnt.rs b/pumpkin/src/entity/tnt.rs index ef97cca2a..b53f53426 100644 --- a/pumpkin/src/entity/tnt.rs +++ b/pumpkin/src/entity/tnt.rs @@ -65,8 +65,6 @@ impl EntityBase for TNTEntity { self.entity.remove().await; self.entity .world - .read() - .await .explode(server, self.entity.pos.load(), self.power) .await; } else { diff --git a/pumpkin/src/item/items/axe.rs b/pumpkin/src/item/items/axe.rs index af751507b..a60492644 100644 --- a/pumpkin/src/item/items/axe.rs +++ b/pumpkin/src/item/items/axe.rs @@ -32,7 +32,7 @@ impl ItemBehaviour for AxeItem { _server: &Server, ) { // I tried to follow mojang order of doing things. - let world = player.world().await; + let world = player.world(); let replacement_block = try_use_axe(block); // First we try to strip the block. by getting his equivalent and applying it the axis. diff --git a/pumpkin/src/item/items/bucket.rs b/pumpkin/src/item/items/bucket.rs index 5ebd61a53..b5a6d847c 100644 --- a/pumpkin/src/item/items/bucket.rs +++ b/pumpkin/src/item/items/bucket.rs @@ -97,7 +97,7 @@ fn set_waterlogged(block: &Block, state: u16, waterlogged: bool) -> u16 { #[async_trait] impl ItemBehaviour for EmptyBucketItem { async fn normal_use(&self, _item: &Item, player: &Player) { - let world = player.world().await.clone(); + let world = player.world(); let (start_pos, end_pos) = get_start_and_end_pos(player); let checker = async |pos: &BlockPos, world_inner: &Arc| { @@ -211,7 +211,7 @@ impl ItemBehaviour for EmptyBucketItem { #[async_trait] impl ItemBehaviour for FilledBucketItem { async fn normal_use(&self, item: &Item, player: &Player) { - let world = player.world().await.clone(); + let world = player.world(); let (start_pos, end_pos) = get_start_and_end_pos(player); let checker = async |pos: &BlockPos, world_inner: &Arc| { let state_id = world_inner.get_block_state_id(pos).await; diff --git a/pumpkin/src/item/items/egg.rs b/pumpkin/src/item/items/egg.rs index 2e1d3a277..982553700 100644 --- a/pumpkin/src/item/items/egg.rs +++ b/pumpkin/src/item/items/egg.rs @@ -24,7 +24,7 @@ const POWER: f32 = 1.5; impl ItemBehaviour for EggItem { async fn normal_use(&self, _block: &Item, player: &Player) { let position = player.position(); - let world = player.world().await; + let world = player.world(); world .play_sound( Sound::EntityEggThrow, diff --git a/pumpkin/src/item/items/ender_eye.rs b/pumpkin/src/item/items/ender_eye.rs index 6c4477cce..a56e7d237 100644 --- a/pumpkin/src/item/items/ender_eye.rs +++ b/pumpkin/src/item/items/ender_eye.rs @@ -32,7 +32,7 @@ impl ItemBehaviour for EnderEyeItem { return; } - let world = player.world().await; + let world = player.world(); let state_id = world.get_block_state_id(&location).await; let original_props = block.properties(state_id).unwrap().to_props(); @@ -52,13 +52,13 @@ impl ItemBehaviour for EnderEyeItem { .set_block_state(&location, new_state_id, BlockFlags::empty()) .await; - EndPortal::get_new_portal(&world, location).await; + EndPortal::get_new_portal(world, location).await; return; } async fn normal_use(&self, _item: &Item, player: &Player) { - let world = player.world().await; + let world = player.world(); let (start_pos, end_pos) = self.get_start_and_end_pos(player); let checker = async |pos: &BlockPos, world_inner: &Arc| { let state_id = world_inner.get_block_state_id(pos).await; diff --git a/pumpkin/src/item/items/hoe.rs b/pumpkin/src/item/items/hoe.rs index 907e9d4c9..0802c6b27 100644 --- a/pumpkin/src/item/items/hoe.rs +++ b/pumpkin/src/item/items/hoe.rs @@ -41,7 +41,7 @@ impl ItemBehaviour for HoeItem { || block == &Block::ROOTED_DIRT { let mut future_block = block; - let world = player.world().await; + let world = player.world(); //Only rooted can be right-clicked on the bottom of the block if face == BlockDirection::Down { diff --git a/pumpkin/src/item/items/honeycomb.rs b/pumpkin/src/item/items/honeycomb.rs index 8957c5a02..97dafd821 100644 --- a/pumpkin/src/item/items/honeycomb.rs +++ b/pumpkin/src/item/items/honeycomb.rs @@ -38,7 +38,7 @@ impl ItemBehaviour for HoneyCombItem { block: &Block, _server: &Server, ) { - let world = player.world().await; + let world = player.world(); // First we try to strip the block. by getting his equivalent and applying it the axis. let replacement_block = get_waxed_equivalent(block); diff --git a/pumpkin/src/item/items/ignite/ignition.rs b/pumpkin/src/item/items/ignite/ignition.rs index 6a4664e87..b7a69032b 100644 --- a/pumpkin/src/item/items/ignite/ignition.rs +++ b/pumpkin/src/item/items/ignite/ignition.rs @@ -24,26 +24,26 @@ impl Ignition { F: FnOnce(Arc, BlockPos, u16) -> Fut, Fut: Future, { - let world = player.world().await; + let world = player.world(); let pos = location.offset(face.to_offset()); if world.get_fluid(&location).await.name != Fluid::EMPTY.name { return; } - let fire_block = FireBlockBase::get_fire_type(&world, &pos).await; + let fire_block = FireBlockBase::get_fire_type(world, &pos).await; let state_id = world.get_block_state_id(&location).await; if let Some(new_state_id) = can_be_lit(block, state_id) { - ignite_logic(world, location, new_state_id).await; + ignite_logic(world.clone(), location, new_state_id).await; return; } let state_id = FireBlock - .get_state_for_position(&world, &fire_block, &pos) + .get_state_for_position(world, &fire_block, &pos) .await; - if FireBlockBase::can_place_at(&world, &pos).await { - ignite_logic(world, pos, state_id).await; + if FireBlockBase::can_place_at(world, &pos).await { + ignite_logic(world.clone(), pos, state_id).await; } } } diff --git a/pumpkin/src/item/items/minecart.rs b/pumpkin/src/item/items/minecart.rs index 918e67419..e92f3f46a 100644 --- a/pumpkin/src/item/items/minecart.rs +++ b/pumpkin/src/item/items/minecart.rs @@ -58,7 +58,7 @@ impl ItemBehaviour for MinecartItem { block: &Block, _server: &Server, ) { - let world = player.world().await; + let world = player.world(); if !block.is_tagged_with_by_tag(&tag::Block::MINECRAFT_RAILS) { return; diff --git a/pumpkin/src/item/items/shovel.rs b/pumpkin/src/item/items/shovel.rs index f101c586e..7b73f12df 100644 --- a/pumpkin/src/item/items/shovel.rs +++ b/pumpkin/src/item/items/shovel.rs @@ -31,7 +31,7 @@ impl ItemBehaviour for ShovelItem { block: &Block, _server: &Server, ) { - let world = player.world().await; + let world = player.world(); // Yes, Minecraft does hardcode these if (block == &Block::GRASS_BLOCK || block == &Block::DIRT diff --git a/pumpkin/src/item/items/snowball.rs b/pumpkin/src/item/items/snowball.rs index 40edd9d51..033f35d1e 100644 --- a/pumpkin/src/item/items/snowball.rs +++ b/pumpkin/src/item/items/snowball.rs @@ -24,7 +24,7 @@ const POWER: f32 = 1.5; impl ItemBehaviour for SnowBallItem { async fn normal_use(&self, _block: &Item, player: &Player) { let position = player.position(); - let world = player.world().await; + let world = player.world(); world .play_sound( Sound::EntitySnowballThrow, diff --git a/pumpkin/src/net/bedrock/play.rs b/pumpkin/src/net/bedrock/play.rs index 5022ebc40..de127530c 100644 --- a/pumpkin/src/net/bedrock/play.rs +++ b/pumpkin/src/net/bedrock/play.rs @@ -119,7 +119,7 @@ impl BedrockClient { message, gameprofile.name.clone() ); - entity.world.read().await.broadcast_editioned(&je_packet, &be_packet).await; + entity.world.broadcast_editioned(&je_packet, &be_packet).await; } } }} diff --git a/pumpkin/src/net/java/play.rs b/pumpkin/src/net/java/play.rs index 9e1328e12..bad563d06 100644 --- a/pumpkin/src/net/java/play.rs +++ b/pumpkin/src/net/java/play.rs @@ -303,7 +303,7 @@ impl JavaClient { } entity.on_ground.store(packet.collision & FLAG_ON_GROUND != 0, Ordering::Relaxed); - let world = &player.world().await; + let world = &player.world(); // TODO: Warn when player moves to quickly if !self.sync_position(player, world, pos, last_pos, entity.yaw.load(), entity.pitch.load(), packet.collision & FLAG_ON_GROUND != 0).await { @@ -416,7 +416,7 @@ impl JavaClient { let yaw = (entity.yaw.load() * 256.0 / 360.0).rem_euclid(256.0); let pitch = (entity.pitch.load() * 256.0 / 360.0).rem_euclid(256.0); // let head_yaw = (entity.head_yaw * 256.0 / 360.0).floor(); - let world = &entity.world.read().await; + let world = &entity.world; // TODO: Warn when player moves to quickly if !self @@ -510,7 +510,7 @@ impl JavaClient { let pitch = (entity.pitch.load() * 256.0 / 360.0).rem_euclid(256.0); // let head_yaw = modulus(entity.head_yaw * 256.0 / 360.0, 256.0); - let world = &entity.world.read().await; + let world = &entity.world; let packet = CUpdateEntityRot::new(entity_id.into(), yaw as u8, pitch as u8, rotation.ground); world @@ -580,7 +580,7 @@ impl JavaClient { return; } - let world = player.world().await; + let world = player.world(); let block = world.get_block(&pick_item.pos).await; if block.item_id == 0 { @@ -626,7 +626,7 @@ impl JavaClient { pub async fn handle_set_command_block(&self, player: &Arc, command: SSetCommandBlock) { // TODO: check things let pos = command.pos; - if let Some(block_entity) = player.world().await.get_block_entity(&pos).await { + if let Some(block_entity) = player.world().get_block_entity(&pos).await { if block_entity.resource_location() != CommandBlockEntity::ID { log::warn!( "Client tried to change Command block but not Command block entity found" @@ -706,7 +706,6 @@ impl JavaClient { let (yaw, pitch) = player.rotation(); let hit_result = player .world() - .await .raycast( player.eye_position(), player @@ -724,7 +723,7 @@ impl JavaClient { player, InteractAction::LeftClickBlock, &item, - player.world().await.get_block(&hit_pos).await, + player.world().get_block(&hit_pos).await, Some(hit_pos), ) } else { @@ -784,7 +783,7 @@ impl JavaClient { ); let entity = &player.living_entity.entity; - let world = &entity.world.read().await; + let world = &entity.world; if BASIC_CONFIG.allow_chat_reports { world.broadcast_secure_player_chat(player, &chat_message, decorated_message).await; } else { @@ -1040,7 +1039,7 @@ impl JavaClient { if player.living_entity.health.load() > 0.0 { return; } - player.world().await.respawn_player(player, false).await; + player.world().respawn_player(player, false).await; let screen_handler = player.current_screen_handler.lock().await; let mut screen_handler = screen_handler.lock().await; @@ -1090,7 +1089,7 @@ impl JavaClient { // TODO: set as camera entity when spectator - let world = &entity.world.read().await; + let world = &entity.world; let player_victim = world.get_player_by_id(entity_id.0).await; if entity_id.0 == player.entity_id() { // This can't be triggered from a non-modded client. @@ -1164,7 +1163,7 @@ impl JavaClient { } let position = player_action.position; let entity = &player.living_entity.entity; - let world = &entity.world.read().await; + let world = &entity.world; let (block, state) = world.get_block_and_state(&position).await; let inventory = player.inventory(); @@ -1245,8 +1244,6 @@ impl JavaClient { let entity = &player.living_entity.entity; entity .world - .read() - .await .set_block_breaking(entity, player_action.position, -1) .await; self.update_sequence(player, player_action.sequence.0); @@ -1265,7 +1262,7 @@ impl JavaClient { // Block break & play sound let entity = &player.living_entity.entity; - let world = &entity.world.read().await; + let world = &entity.world; player.mining.store(false, Ordering::Relaxed); world.set_block_breaking(entity, location, -1).await; @@ -1398,7 +1395,7 @@ impl JavaClient { }; let entity = &player.living_entity.entity; - let world = entity.world.read().await; + let world = &entity.world; let block = world.get_block(&position).await; let sneaking = player.living_entity.entity.sneaking.load(Ordering::Relaxed); @@ -1412,7 +1409,7 @@ impl JavaClient { &cursor_pos, &face, &item, - &world, + world, block, server, ) @@ -1421,7 +1418,6 @@ impl JavaClient { // TODO: Trigger ANY_BLOCK_USE Criteria if matches!(result, BlockActionResult::SuccessServer) { - drop(world); // IMPORTANT: We need to drop this to prevent a deadlock player.swing_hand(hand, true).await; } return Ok(()); @@ -1526,7 +1522,7 @@ impl JavaClient { } pub async fn handle_sign_update(&self, player: &Player, sign_data: SUpdateSign) { - let world = &player.living_entity.entity.world.read().await; + let world = &player.living_entity.entity.world; let Some(block_entity) = world.get_block_entity(&sign_data.location).await else { return; }; @@ -1577,7 +1573,6 @@ impl JavaClient { let hit_result = player .world() - .await .raycast( player.eye_position(), player.eye_position().add( @@ -1596,7 +1591,7 @@ impl JavaClient { player, InteractAction::RightClickBlock, &item_in_hand, - player.world().await.get_block(&hit_pos).await, + player.world().get_block(&hit_pos).await, Some(hit_pos), ) } else { @@ -1744,9 +1739,9 @@ impl JavaClient { // Create rotation like Vanilla let yaw = wrap_degrees(rand::random::() * 360.0) % 360.0; - let world = player.world().await; + let world = player.world(); // Create a new mob and UUID based on the spawn egg id - let mob = from_type(entity_type, pos, &world, Uuid::new_v4()).await; + let mob = from_type(entity_type, pos, world, Uuid::new_v4()).await; // Set the rotation mob.get_entity().set_rotation(yaw, 0.0); @@ -1800,7 +1795,7 @@ impl JavaClient { } let clicked_block_pos = BlockPos(location.0); - let world = &entity.world.read().await; + let world = &entity.world; let (clicked_block, clicked_block_state) = world.get_block_and_state(&clicked_block_pos).await; diff --git a/pumpkin/src/server/mod.rs b/pumpkin/src/server/mod.rs index 55257cd7e..0bc260417 100644 --- a/pumpkin/src/server/mod.rs +++ b/pumpkin/src/server/mod.rs @@ -35,12 +35,9 @@ use rsa::RsaPublicKey; use std::collections::HashSet; use std::fs; use std::net::IpAddr; +use std::sync::Arc; use std::sync::atomic::{AtomicBool, AtomicI32, AtomicI64, AtomicU32}; -use std::{ - future::Future, - sync::{Arc, atomic::Ordering}, - time::Duration, -}; +use std::{future::Future, sync::atomic::Ordering, time::Duration}; use tokio::sync::{Mutex, RwLock}; use tokio::task::JoinHandle; use tokio_util::task::TaskTracker; @@ -325,7 +322,7 @@ impl Server { }; let mut player = Player::new( - client, + Arc::new(client), profile, config.clone().unwrap_or_default(), world.clone(), diff --git a/pumpkin/src/world/chunker.rs b/pumpkin/src/world/chunker.rs index 0c0e92150..7119ddba2 100644 --- a/pumpkin/src/world/chunker.rs +++ b/pumpkin/src/world/chunker.rs @@ -33,7 +33,7 @@ pub async fn update_position(player: &Arc) { let new_cylindrical = Cylindrical::new(new_chunk_center, view_distance); if old_cylindrical != new_cylindrical { - match &player.client { + match player.client.as_ref() { ClientPlatform::Java(client) => { client .send_packet_now(&CCenterChunk { @@ -66,7 +66,7 @@ pub async fn update_position(player: &Arc) { // Make sure the watched section and the chunk watcher updates are async atomic. We want to // ensure what we unload when the player disconnects is correct. - let level = &entity.world.read().await.level; + let level = &entity.world.level; level.mark_chunks_as_newly_watched(&loading_chunks).await; let chunks_to_clean = level.mark_chunks_as_not_watched(&unloading_chunks).await; @@ -90,11 +90,9 @@ pub async fn update_position(player: &Arc) { } if !loading_chunks.is_empty() { - entity.world.read().await.spawn_world_chunks( - player.clone(), - loading_chunks, - new_chunk_center, - ); + entity + .world + .spawn_world_chunks(player.clone(), loading_chunks, new_chunk_center); } } } diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 2a6d0e98a..da5f1fbaf 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -390,7 +390,7 @@ impl World { let current_players = self.players.read().await; for (_, player) in current_players.iter() { - match &player.client { + match player.client.as_ref() { ClientPlatform::Java(client) => client.enqueue_packet(je_packet).await, ClientPlatform::Bedrock(client) => client.send_game_packet(be_packet).await, } @@ -1689,7 +1689,7 @@ impl World { yaw: f32, pitch: f32, ) { - if let ClientPlatform::Java(client) = &player.client { + if let ClientPlatform::Java(client) = player.client.as_ref() { self.worldborder.lock().await.init_client(client).await; } @@ -1753,7 +1753,7 @@ impl World { pub async fn respawn_player(&self, player: &Arc, alive: bool) { let last_pos = player.living_entity.entity.last_pos.load(); - let death_dimension = player.world().await.dimension_type.resource_location(); + let death_dimension = player.world().dimension_type.resource_location(); let death_location = BlockPos(Vector3::new( last_pos.x.round() as i32, last_pos.y.round() as i32, diff --git a/pumpkin/src/world/time.rs b/pumpkin/src/world/time.rs index 1d358c93c..11e09d192 100644 --- a/pumpkin/src/world/time.rs +++ b/pumpkin/src/world/time.rs @@ -35,7 +35,7 @@ impl LevelTime { pub async fn send_time(&self, world: &World) { let current_players = world.players.read().await; for player in current_players.values() { - match &player.client { + match player.client.as_ref() { ClientPlatform::Java(java_client) => { java_client .enqueue_packet(&CUpdateTime::new(self.world_age, self.time_of_day, true))