entity: Arc<RwLock<Arc<World>> to Arc<World>
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
This commit is contained in:
parent
36d6356532
commit
314547eb5f
@ -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,
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 => {
|
||||
|
||||
@ -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.",
|
||||
))));
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
_ => {
|
||||
|
||||
@ -100,11 +100,11 @@ impl CommandSender {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub async fn world(&self) -> Option<Arc<World>> {
|
||||
pub fn world(&self) -> Option<Arc<World>> {
|
||||
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()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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?
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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<dyn EntityBase>) -> 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;
|
||||
|
||||
@ -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<RwLock<Arc<World>>>,
|
||||
pub world: Arc<World>,
|
||||
/// The entity's current position in the world
|
||||
pub pos: AtomicCell<Vector3<f64>>,
|
||||
/// 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;
|
||||
}
|
||||
|
||||
@ -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<ClientPlatform>,
|
||||
/// The player's inventory.
|
||||
pub inventory: Arc<PlayerInventory>,
|
||||
/// 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<ClientPlatform>,
|
||||
gameprofile: GameProfile,
|
||||
config: PlayerConfig,
|
||||
world: Arc<World>,
|
||||
@ -397,9 +397,8 @@ impl Player {
|
||||
}
|
||||
|
||||
/// Removes the [`Player`] out of the current [`World`].
|
||||
#[allow(unused_variables)]
|
||||
pub async fn remove(self: &Arc<Self>) {
|
||||
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<dyn EntityBase>) {
|
||||
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<f64>, 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<World> {
|
||||
self.living_entity.entity.world.read().await.clone()
|
||||
pub fn world(&self) -> &Arc<World> {
|
||||
&self.living_entity.entity.world
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Vector3<f64> {
|
||||
@ -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<f32>,
|
||||
pitch: Option<f32>,
|
||||
) {
|
||||
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<f32>,
|
||||
world: Arc<World>,
|
||||
) {
|
||||
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,
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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<World>| {
|
||||
@ -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<World>| {
|
||||
let state_id = world_inner.get_block_state_id(pos).await;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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<World>| {
|
||||
let state_id = world_inner.get_block_state_id(pos).await;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -24,26 +24,26 @@ impl Ignition {
|
||||
F: FnOnce(Arc<World>, BlockPos, u16) -> Fut,
|
||||
Fut: Future<Output = ()>,
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
@ -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<Player>, 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::<f32>() * 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;
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -33,7 +33,7 @@ pub async fn update_position(player: &Arc<Player>) {
|
||||
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<Player>) {
|
||||
|
||||
// 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<Player>) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Player>, 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,
|
||||
|
||||
@ -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))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user