From 3f32878d63426b958ee34cfea53d103c49c0312f Mon Sep 17 00:00:00 2001 From: mat Date: Wed, 11 Dec 2024 02:40:52 +0000 Subject: [PATCH 1/2] implement EntityPositionSync --- azalea-client/src/movement.rs | 13 +-- azalea-client/src/packet_handling/game.rs | 96 +++++++++++++++++-- azalea-core/src/position.rs | 4 +- azalea-entity/src/dimensions.rs | 2 +- azalea-entity/src/lib.rs | 61 ++++++------ azalea-entity/src/plugin/mod.rs | 2 +- azalea-entity/src/vec_delta_codec.rs | 60 ++++++++++++ azalea-physics/src/collision/mod.rs | 4 +- azalea-physics/src/lib.rs | 6 +- .../packets/game/c_entity_position_sync.rs | 11 +-- .../src/packets/game/c_player_position.rs | 8 +- azalea-world/src/world.rs | 5 +- azalea/src/auto_tool.rs | 22 +---- azalea/src/pathfinder/mod.rs | 2 +- azalea/src/pathfinder/simulation.rs | 2 +- 15 files changed, 215 insertions(+), 83 deletions(-) create mode 100644 azalea-entity/src/vec_delta_codec.rs diff --git a/azalea-client/src/movement.rs b/azalea-client/src/movement.rs index 03183e244..bdc29f2fb 100644 --- a/azalea-client/src/movement.rs +++ b/azalea-client/src/movement.rs @@ -195,7 +195,7 @@ pub fn send_position( pos: **position, x_rot: direction.x_rot, y_rot: direction.y_rot, - on_ground: physics.on_ground, + on_ground: physics.on_ground(), } .into_variant(), ) @@ -205,7 +205,7 @@ pub fn send_position( x: position.x, y: position.y, z: position.z, - on_ground: physics.on_ground, + on_ground: physics.on_ground(), } .into_variant(), ) @@ -214,14 +214,14 @@ pub fn send_position( ServerboundMovePlayerRot { x_rot: direction.x_rot, y_rot: direction.y_rot, - on_ground: physics.on_ground, + on_ground: physics.on_ground(), } .into_variant(), ) - } else if physics.last_on_ground != physics.on_ground { + } else if physics.last_on_ground() != physics.on_ground() { Some( ServerboundMovePlayerStatusOnly { - on_ground: physics.on_ground, + on_ground: physics.on_ground(), } .into_variant(), ) @@ -238,7 +238,8 @@ pub fn send_position( last_direction.x_rot = direction.x_rot; } - physics.last_on_ground = physics.on_ground; + let on_ground = physics.on_ground(); + physics.set_last_on_ground(on_ground); // minecraft checks for autojump here, but also autojump is bad so packet diff --git a/azalea-client/src/packet_handling/game.rs b/azalea-client/src/packet_handling/game.rs index d4d84f758..275a9b72a 100644 --- a/azalea-client/src/packet_handling/game.rs +++ b/azalea-client/src/packet_handling/game.rs @@ -451,8 +451,16 @@ pub fn process_packet_events(ecs: &mut World) { let new_y = apply_change(position.y, p.relative.y, p.change.pos.y); let new_z = apply_change(position.z, p.relative.z, p.change.pos.z); - let new_y_rot = apply_change(direction.y_rot, p.relative.y_rot, p.change.y_rot); - let new_x_rot = apply_change(direction.x_rot, p.relative.x_rot, p.change.x_rot); + let new_y_rot = apply_change( + direction.y_rot, + p.relative.y_rot, + p.change.look_direction.y_rot, + ); + let new_x_rot = apply_change( + direction.x_rot, + p.relative.x_rot, + p.change.look_direction.x_rot, + ); let mut new_delta_from_rotations = physics.velocity; if p.relative.rotate_delta { @@ -873,12 +881,21 @@ pub fn process_packet_events(ecs: &mut World) { let entity = entity_id_index.get(&MinecraftEntityId(p.entity_id)); if let Some(entity) = entity { - let delta = p.delta.clone(); + let new_delta = p.delta.clone(); + let new_on_ground = p.on_ground; commands.entity(entity).queue(RelativeEntityUpdate { partial_world: instance_holder.partial_instance.clone(), update: Box::new(move |entity_mut| { + let mut physics = entity_mut.get_mut::().unwrap(); + let new_pos = physics.vec_delta_codec.decode( + new_delta.xa as i64, + new_delta.ya as i64, + new_delta.za as i64, + ); + physics.vec_delta_codec.set_base(new_pos); + physics.set_on_ground(new_on_ground); + let mut position = entity_mut.get_mut::().unwrap(); - let new_pos = position.with_delta(&delta); if new_pos != **position { **position = new_pos; } @@ -904,20 +921,31 @@ pub fn process_packet_events(ecs: &mut World) { let entity = entity_id_index.get(&MinecraftEntityId(p.entity_id)); if let Some(entity) = entity { - let delta = p.delta.clone(); + let new_delta = p.delta.clone(); let new_look_direction = LookDirection { x_rot: (p.x_rot as i32 * 360) as f32 / 256., y_rot: (p.y_rot as i32 * 360) as f32 / 256., }; + let new_on_ground = p.on_ground; + commands.entity(entity).queue(RelativeEntityUpdate { partial_world: instance_holder.partial_instance.clone(), update: Box::new(move |entity_mut| { + let mut physics = entity_mut.get_mut::().unwrap(); + let new_pos = physics.vec_delta_codec.decode( + new_delta.xa as i64, + new_delta.ya as i64, + new_delta.za as i64, + ); + physics.vec_delta_codec.set_base(new_pos); + physics.set_on_ground(new_on_ground); + let mut position = entity_mut.get_mut::().unwrap(); - let new_pos = position.with_delta(&delta); if new_pos != **position { **position = new_pos; } + let mut look_direction = entity_mut.get_mut::().unwrap(); if new_look_direction != *look_direction { *look_direction = new_look_direction; @@ -949,10 +977,14 @@ pub fn process_packet_events(ecs: &mut World) { x_rot: (p.x_rot as i32 * 360) as f32 / 256., y_rot: (p.y_rot as i32 * 360) as f32 / 256., }; + let new_on_ground = p.on_ground; commands.entity(entity).queue(RelativeEntityUpdate { partial_world: instance_holder.partial_instance.clone(), update: Box::new(move |entity_mut| { + let mut physics = entity_mut.get_mut::().unwrap(); + physics.set_on_ground(new_on_ground); + let mut look_direction = entity_mut.get_mut::().unwrap(); if new_look_direction != *look_direction { *look_direction = new_look_direction; @@ -1416,7 +1448,7 @@ pub fn process_packet_events(ecs: &mut World) { system_state.apply(ecs); } - ClientboundGamePacket::StartConfiguration(_) => { + ClientboundGamePacket::StartConfiguration(_p) => { let mut system_state: SystemState<(Commands, EventWriter)> = SystemState::new(ecs); let (mut commands, mut packet_events) = system_state.get_mut(ecs); @@ -1434,6 +1466,55 @@ pub fn process_packet_events(ecs: &mut World) { system_state.apply(ecs); } + ClientboundGamePacket::EntityPositionSync(p) => { + debug!("Got entity position sync packet {p:?}"); + + let mut system_state: SystemState<( + Query<&EntityIdIndex>, + Query<( + &mut Physics, + &mut Position, + &mut LastSentPosition, + &mut LookDirection, + Option<&LocalEntity>, + )>, + )> = SystemState::new(ecs); + let (mut index_query, mut query) = system_state.get_mut(ecs); + let entity_id_index = index_query.get_mut(player_entity).unwrap(); + let Some(entity) = entity_id_index.get(&MinecraftEntityId(p.id)) else { + warn!( + "Got entity position sync packet for unknown entity id {}", + p.id + ); + continue; + }; + + let Ok(( + mut physics, + mut position, + mut last_sent_position, + mut look_direction, + local_entity, + )) = query.get_mut(entity) + else { + continue; + }; + + physics.vec_delta_codec.set_base(**position); + + if local_entity.is_some() { + debug!("Ignoring entity position sync packet for local player"); + continue; + } + + **last_sent_position = **position; + **position = p.values.pos; + + *look_direction = p.values.look_direction; + + physics.set_on_ground(p.on_ground); + } + ClientboundGamePacket::SelectAdvancementsTab(_) => {} ClientboundGamePacket::SetActionBarText(_) => {} ClientboundGamePacket::SetBorderCenter(_) => {} @@ -1476,7 +1557,6 @@ pub fn process_packet_events(ecs: &mut World) { ClientboundGamePacket::ProjectilePower(_) => {} ClientboundGamePacket::CustomReportDetails(_) => {} ClientboundGamePacket::ServerLinks(_) => {} - ClientboundGamePacket::EntityPositionSync(_) => {} ClientboundGamePacket::PlayerRotation(_) => {} ClientboundGamePacket::RecipeBookAdd(_) => {} ClientboundGamePacket::RecipeBookRemove(_) => {} diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs index 9b800e288..14ecfcc10 100755 --- a/azalea-core/src/position.rs +++ b/azalea-core/src/position.rs @@ -20,7 +20,7 @@ macro_rules! vec3_impl { ($name:ident, $type:ty) => { impl $name { #[inline] - pub fn new(x: $type, y: $type, z: $type) -> Self { + pub const fn new(x: $type, y: $type, z: $type) -> Self { Self { x, y, z } } @@ -223,6 +223,8 @@ pub struct Vec3 { vec3_impl!(Vec3, f64); impl Vec3 { + pub const ZERO: Vec3 = Vec3::new(0.0, 0.0, 0.0); + /// Get the distance of this vector to the origin by doing /// `sqrt(x^2 + y^2 + z^2)`. pub fn length(&self) -> f64 { diff --git a/azalea-entity/src/dimensions.rs b/azalea-entity/src/dimensions.rs index b5a3f3103..5236b80f4 100755 --- a/azalea-entity/src/dimensions.rs +++ b/azalea-entity/src/dimensions.rs @@ -7,7 +7,7 @@ pub struct EntityDimensions { } impl EntityDimensions { - pub fn make_bounding_box(&self, pos: &Vec3) -> AABB { + pub fn make_bounding_box(&self, pos: Vec3) -> AABB { let radius = (self.width / 2.0) as f64; let height = self.height as f64; AABB { diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index 1334ee0fd..95a2ed3c1 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -9,6 +9,7 @@ pub mod metadata; pub mod mining; pub mod particle; mod plugin; +pub mod vec_delta_codec; use std::{ fmt::Debug, @@ -17,6 +18,7 @@ use std::{ pub use attributes::Attributes; use azalea_block::BlockState; +use azalea_buf::AzBuf; use azalea_core::{ aabb::AABB, math, @@ -30,6 +32,7 @@ use derive_more::{Deref, DerefMut}; pub use dimensions::EntityDimensions; use plugin::indexing::EntityChunkPos; use uuid::Uuid; +use vec_delta_codec::VecDeltaCodec; use self::attributes::AttributeInstance; pub use crate::plugin::*; @@ -210,7 +213,7 @@ impl From<&LastSentPosition> for BlockPos { pub struct Jumping(bool); /// A component that contains the direction an entity is looking. -#[derive(Debug, Component, Copy, Clone, Default, PartialEq)] +#[derive(Debug, Component, Copy, Clone, Default, PartialEq, AzBuf)] pub struct LookDirection { /// Left and right. Aka yaw. pub y_rot: f32, @@ -245,7 +248,7 @@ impl Eq for LookDirection {} /// The physics data relating to the entity, such as position, velocity, and /// bounding box. -#[derive(Debug, Component, Clone)] +#[derive(Debug, Component, Clone, Default)] pub struct Physics { /// How fast the entity is moving. pub velocity: Vec3, @@ -257,8 +260,10 @@ pub struct Physics { /// Z acceleration. pub zza: f32, - pub on_ground: bool, - pub last_on_ground: bool, + on_ground: bool, + last_on_ground: bool, + + pub vec_delta_codec: VecDeltaCodec, /// The width and height of the entity. pub dimensions: EntityDimensions, @@ -274,7 +279,7 @@ pub struct Physics { } impl Physics { - pub fn new(dimensions: EntityDimensions, pos: &Vec3) -> Self { + pub fn new(dimensions: EntityDimensions, pos: Vec3) -> Self { Self { velocity: Vec3::default(), @@ -292,8 +297,30 @@ impl Physics { horizontal_collision: false, vertical_collision: false, + + vec_delta_codec: VecDeltaCodec::new(pos), } } + + pub fn on_ground(&self) -> bool { + self.on_ground + } + /// Updates [`Self::on_ground`] and [`Self::last_on_ground`]. + pub fn set_on_ground(&mut self, on_ground: bool) { + self.last_on_ground = self.on_ground; + self.on_ground = on_ground; + } + + /// The last value of the on_ground value. + /// + /// This is used by Azalea internally for physics, it might not work as you + /// expect since it can be influenced by packets sent by the server. + pub fn last_on_ground(&self) -> bool { + self.last_on_ground + } + pub fn set_last_on_ground(&mut self, last_on_ground: bool) { + self.last_on_ground = last_on_ground; + } } /// Marker component for entities that are dead. @@ -384,7 +411,7 @@ impl EntityBundle { position: Position(pos), chunk_pos: EntityChunkPos(ChunkPos::from(&pos)), last_sent_position: LastSentPosition(pos), - physics: Physics::new(dimensions, &pos), + physics: Physics::new(dimensions, pos), eye_height: EyeHeight(eye_height), direction: LookDirection::default(), @@ -427,25 +454,3 @@ impl FluidOnEyes { #[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)] pub struct OnClimbable(bool); - -// #[cfg(test)] -// mod tests { -// use super::*; -// use crate::PartialWorld; - -// #[test] -// fn from_mut_entity_to_ref_entity() { -// let mut world = PartialWorld::default(); -// let uuid = Uuid::from_u128(100); -// world.add_entity( -// 0, -// EntityData::new( -// uuid, -// Vec3::default(), -// EntityMetadata::Player(metadata::Player::default()), -// ), -// ); -// let entity: Entity = world.entity_mut(0).unwrap(); -// assert_eq!(entity.uuid, uuid); -// } -// } diff --git a/azalea-entity/src/plugin/mod.rs b/azalea-entity/src/plugin/mod.rs index 67763484b..90d7f1c57 100644 --- a/azalea-entity/src/plugin/mod.rs +++ b/azalea-entity/src/plugin/mod.rs @@ -198,7 +198,7 @@ pub fn clamp_look_direction(mut query: Query<&mut LookDirection>) { /// Cached position in the world must be updated. pub fn update_bounding_box(mut query: Query<(&Position, &mut Physics), Changed>) { for (position, mut physics) in query.iter_mut() { - let bounding_box = physics.dimensions.make_bounding_box(position); + let bounding_box = physics.dimensions.make_bounding_box(**position); physics.bounding_box = bounding_box; } } diff --git a/azalea-entity/src/vec_delta_codec.rs b/azalea-entity/src/vec_delta_codec.rs new file mode 100644 index 000000000..51aa7cea7 --- /dev/null +++ b/azalea-entity/src/vec_delta_codec.rs @@ -0,0 +1,60 @@ +use azalea_core::position::Vec3; + +#[derive(Debug, Clone, Default)] +pub struct VecDeltaCodec { + base: Vec3, +} + +impl VecDeltaCodec { + pub fn new(base: Vec3) -> Self { + Self { base } + } + + pub fn decode(&self, x: i64, y: i64, z: i64) -> Vec3 { + if x == 0 && y == 0 && z == 0 { + return self.base; + } + + let new_x = if x == 0 { + self.base.x + } else { + decode(encode(self.base.x) + x) + }; + let new_y = if y == 0 { + self.base.y + } else { + decode(encode(self.base.y) + y) + }; + let new_z = if z == 0 { + self.base.z + } else { + decode(encode(self.base.z) + z) + }; + + Vec3::new(new_x, new_y, new_z) + } + + pub fn encode_x(&self, pos: Vec3) -> i64 { + encode(pos.x) - encode(self.base.x) + } + pub fn encode_y(&self, pos: Vec3) -> i64 { + encode(pos.y) - encode(self.base.y) + } + pub fn encode_z(&self, pos: Vec3) -> i64 { + encode(pos.z) - encode(self.base.z) + } + + pub fn set_base(&mut self, pos: Vec3) { + self.base = pos; + } + pub fn base(&self) -> Vec3 { + self.base + } +} + +fn encode(value: f64) -> i64 { + (value * 4096.).round() as i64 +} +fn decode(value: i64) -> f64 { + (value as f64) / 4096. +} diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs index 7d7ddc5e4..913cedacd 100644 --- a/azalea-physics/src/collision/mod.rs +++ b/azalea-physics/src/collision/mod.rs @@ -73,7 +73,7 @@ fn collide(movement: &Vec3, world: &Instance, physics: &azalea_entity::Physics) let y_collision = movement.y != collided_delta.y; let z_collision = movement.z != collided_delta.z; - let on_ground = physics.on_ground || y_collision && movement.y < 0.; + let on_ground = physics.on_ground() || y_collision && movement.y < 0.; let max_up_step = 0.6; if max_up_step > 0. && on_ground && (x_collision || z_collision) { @@ -192,7 +192,7 @@ pub fn move_colliding( physics.horizontal_collision = horizontal_collision; physics.vertical_collision = vertical_collision; - physics.on_ground = on_ground; + physics.set_on_ground(on_ground); // TODO: minecraft checks for a "minor" horizontal collision here diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index c50095e41..2ca64b1f2 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -100,7 +100,7 @@ fn travel( let block_below: Box = block_state_below.into(); let block_friction = block_below.behavior().friction; - let inertia = if physics.on_ground { + let inertia = if physics.on_ground() { block_friction * 0.91 } else { 0.91 @@ -178,7 +178,7 @@ pub fn ai_step( if **jumping { // TODO: jumping in liquids and jump delay - if physics.on_ground { + if physics.on_ground() { jump_from_ground( &mut physics, position, @@ -358,7 +358,7 @@ fn get_friction_influenced_speed( is_sprinting: bool, ) -> f32 { // TODO: have speed & flying_speed fields in entity - if physics.on_ground { + if physics.on_ground() { let speed: f32 = attributes.speed.calculate() as f32; speed * (0.216f32 / (friction * friction * friction)) } else { diff --git a/azalea-protocol/src/packets/game/c_entity_position_sync.rs b/azalea-protocol/src/packets/game/c_entity_position_sync.rs index c5cde3229..6347ec5ed 100755 --- a/azalea-protocol/src/packets/game/c_entity_position_sync.rs +++ b/azalea-protocol/src/packets/game/c_entity_position_sync.rs @@ -1,7 +1,8 @@ use azalea_buf::AzBuf; -use azalea_core::position::Vec3; use azalea_protocol_macros::ClientboundGamePacket; +use super::c_player_position::PositionMoveRotation; + #[derive(Clone, Debug, AzBuf, ClientboundGamePacket)] pub struct ClientboundEntityPositionSync { #[var] @@ -9,11 +10,3 @@ pub struct ClientboundEntityPositionSync { pub values: PositionMoveRotation, pub on_ground: bool, } - -#[derive(AzBuf, Clone, Debug)] -pub struct PositionMoveRotation { - pub position: Vec3, - pub delta_movement: Vec3, - pub y_rot: f32, - pub x_rot: f32, -} diff --git a/azalea-protocol/src/packets/game/c_player_position.rs b/azalea-protocol/src/packets/game/c_player_position.rs index e742df225..d75c7b782 100755 --- a/azalea-protocol/src/packets/game/c_player_position.rs +++ b/azalea-protocol/src/packets/game/c_player_position.rs @@ -2,6 +2,7 @@ use std::io::{Cursor, Write}; use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; use azalea_core::{bitset::FixedBitSet, position::Vec3}; +use azalea_entity::LookDirection; use azalea_protocol_macros::ClientboundGamePacket; #[derive(Clone, Debug, AzBuf, ClientboundGamePacket)] @@ -18,9 +19,12 @@ pub struct ClientboundPlayerPosition { pub struct PositionMoveRotation { pub pos: Vec3, /// The updated delta movement (velocity). + /// + /// This is unused when included in a [`ClientboundEntityPositionSync`]. + /// + /// [`ClientboundEntityPositionSync`]: super::c_entity_position_sync::ClientboundEntityPositionSync pub delta: Vec3, - pub y_rot: f32, - pub x_rot: f32, + pub look_direction: LookDirection, } #[derive(Debug, Clone)] diff --git a/azalea-world/src/world.rs b/azalea-world/src/world.rs index 066981e56..0a09d387b 100644 --- a/azalea-world/src/world.rs +++ b/azalea-world/src/world.rs @@ -1,4 +1,5 @@ use std::fmt::Formatter; +use std::hash::{Hash, Hasher}; use std::{ collections::{HashMap, HashSet}, fmt::Debug, @@ -44,8 +45,8 @@ impl PartialInstance { #[derive(Component, Copy, Clone, Debug, PartialEq, Eq, Deref, DerefMut)] pub struct MinecraftEntityId(pub u32); -impl std::hash::Hash for MinecraftEntityId { - fn hash(&self, hasher: &mut H) { +impl Hash for MinecraftEntityId { + fn hash(&self, hasher: &mut H) { hasher.write_u32(self.0); } } diff --git a/azalea/src/auto_tool.rs b/azalea/src/auto_tool.rs index 5fcb8037a..768d30899 100644 --- a/azalea/src/auto_tool.rs +++ b/azalea/src/auto_tool.rs @@ -31,24 +31,10 @@ impl AutoToolClientExt for Client { /// or in water, use [`accurate_best_tool_in_hotbar_for_block`] instead if you /// care about those things. pub fn best_tool_in_hotbar_for_block(block: BlockState, menu: &Menu) -> BestToolResult { - accurate_best_tool_in_hotbar_for_block( - block, - menu, - &Physics { - on_ground: true, - velocity: Default::default(), - xxa: Default::default(), - yya: Default::default(), - zza: Default::default(), - last_on_ground: Default::default(), - dimensions: Default::default(), - bounding_box: Default::default(), - has_impulse: Default::default(), - horizontal_collision: Default::default(), - vertical_collision: Default::default(), - }, - &FluidOnEyes::new(Fluid::Empty), - ) + let mut physics = Physics::default(); + physics.set_on_ground(true); + + accurate_best_tool_in_hotbar_for_block(block, menu, &physics, &FluidOnEyes::new(Fluid::Empty)) } pub fn accurate_best_tool_in_hotbar_for_block( diff --git a/azalea/src/pathfinder/mod.rs b/azalea/src/pathfinder/mod.rs index eab073481..78aafc2f8 100644 --- a/azalea/src/pathfinder/mod.rs +++ b/azalea/src/pathfinder/mod.rs @@ -516,7 +516,7 @@ pub fn check_node_reached( let x_difference_from_center = position.x - (movement.target.x as f64 + 0.5); let z_difference_from_center = position.z - (movement.target.z as f64 + 0.5); // this is to make sure we don't fall off immediately after finishing the path - physics.on_ground + physics.on_ground() && BlockPos::from(position) == movement.target // adding the delta like this isn't a perfect solution but it helps to make // sure we don't keep going if our delta is high diff --git a/azalea/src/pathfinder/simulation.rs b/azalea/src/pathfinder/simulation.rs index ca15fb7a4..630dd5917 100644 --- a/azalea/src/pathfinder/simulation.rs +++ b/azalea/src/pathfinder/simulation.rs @@ -32,7 +32,7 @@ impl SimulatedPlayerBundle { SimulatedPlayerBundle { position: Position::new(position), - physics: Physics::new(dimensions, &position), + physics: Physics::new(dimensions, position), physics_state: PhysicsState::default(), look_direction: LookDirection::new(0.0, 0.0), attributes: Attributes { From efd31682c6a53454d2df9cbbfd04d7035efe25a5 Mon Sep 17 00:00:00 2001 From: mat Date: Wed, 11 Dec 2024 03:45:51 +0000 Subject: [PATCH 2/2] fix EntityPositionSync setting the wrong vec_delta_codec and also move into a RelativeEntityUpdate --- azalea-client/src/packet_handling/game.rs | 116 +++++++++++----------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/azalea-client/src/packet_handling/game.rs b/azalea-client/src/packet_handling/game.rs index 275a9b72a..0c505d07f 100644 --- a/azalea-client/src/packet_handling/game.rs +++ b/azalea-client/src/packet_handling/game.rs @@ -837,30 +837,29 @@ pub fn process_packet_events(ecs: &mut World) { let (mut commands, mut query) = system_state.get_mut(ecs); let (entity_id_index, instance_holder) = query.get_mut(player_entity).unwrap(); - let entity = entity_id_index.get(&MinecraftEntityId(p.id)); - - if let Some(entity) = entity { - let new_pos = p.position; - let new_look_direction = LookDirection { - x_rot: (p.x_rot as i32 * 360) as f32 / 256., - y_rot: (p.y_rot as i32 * 360) as f32 / 256., - }; - commands.entity(entity).queue(RelativeEntityUpdate { - partial_world: instance_holder.partial_instance.clone(), - update: Box::new(move |entity| { - let mut position = entity.get_mut::().unwrap(); - if new_pos != **position { - **position = new_pos; - } - let mut look_direction = entity.get_mut::().unwrap(); - if new_look_direction != *look_direction { - *look_direction = new_look_direction; - } - }), - }); - } else { + let Some(entity) = entity_id_index.get(&MinecraftEntityId(p.id)) else { warn!("Got teleport entity packet for unknown entity id {}", p.id); - } + continue; + }; + + let new_pos = p.position; + let new_look_direction = LookDirection { + x_rot: (p.x_rot as i32 * 360) as f32 / 256., + y_rot: (p.y_rot as i32 * 360) as f32 / 256., + }; + commands.entity(entity).queue(RelativeEntityUpdate { + partial_world: instance_holder.partial_instance.clone(), + update: Box::new(move |entity| { + let mut position = entity.get_mut::().unwrap(); + if new_pos != **position { + **position = new_pos; + } + let mut look_direction = entity.get_mut::().unwrap(); + if new_look_direction != *look_direction { + *look_direction = new_look_direction; + } + }), + }); system_state.apply(ecs); } @@ -878,6 +877,8 @@ pub fn process_packet_events(ecs: &mut World) { let (mut commands, mut query) = system_state.get_mut(ecs); let (entity_id_index, instance_holder) = query.get_mut(player_entity).unwrap(); + debug!("Got move entity pos packet {p:?}"); + let entity = entity_id_index.get(&MinecraftEntityId(p.entity_id)); if let Some(entity) = entity { @@ -918,6 +919,8 @@ pub fn process_packet_events(ecs: &mut World) { let (mut commands, mut query) = system_state.get_mut(ecs); let (entity_id_index, instance_holder) = query.get_mut(player_entity).unwrap(); + debug!("Got move entity pos rot packet {p:?}"); + let entity = entity_id_index.get(&MinecraftEntityId(p.entity_id)); if let Some(entity) = entity { @@ -1467,52 +1470,49 @@ pub fn process_packet_events(ecs: &mut World) { } ClientboundGamePacket::EntityPositionSync(p) => { - debug!("Got entity position sync packet {p:?}"); - let mut system_state: SystemState<( - Query<&EntityIdIndex>, - Query<( - &mut Physics, - &mut Position, - &mut LastSentPosition, - &mut LookDirection, - Option<&LocalEntity>, - )>, + Commands, + Query<(&EntityIdIndex, &InstanceHolder)>, )> = SystemState::new(ecs); - let (mut index_query, mut query) = system_state.get_mut(ecs); - let entity_id_index = index_query.get_mut(player_entity).unwrap(); + let (mut commands, mut query) = system_state.get_mut(ecs); + let (entity_id_index, instance_holder) = query.get_mut(player_entity).unwrap(); + let Some(entity) = entity_id_index.get(&MinecraftEntityId(p.id)) else { - warn!( - "Got entity position sync packet for unknown entity id {}", - p.id - ); + warn!("Got teleport entity packet for unknown entity id {}", p.id); continue; }; - let Ok(( - mut physics, - mut position, - mut last_sent_position, - mut look_direction, - local_entity, - )) = query.get_mut(entity) - else { - continue; - }; + let new_position = p.values.pos; + let new_on_ground = p.on_ground; + let new_look_direction = p.values.look_direction; - physics.vec_delta_codec.set_base(**position); + commands.entity(entity).queue(RelativeEntityUpdate { + partial_world: instance_holder.partial_instance.clone(), + update: Box::new(move |entity_mut| { + let is_local_entity = entity_mut.get::().is_some(); + let mut physics = entity_mut.get_mut::().unwrap(); - if local_entity.is_some() { - debug!("Ignoring entity position sync packet for local player"); - continue; - } + physics.vec_delta_codec.set_base(new_position); - **last_sent_position = **position; - **position = p.values.pos; + if is_local_entity { + debug!("Ignoring entity position sync packet for local player"); + return; + } + + physics.set_on_ground(new_on_ground); - *look_direction = p.values.look_direction; + let mut last_sent_position = + entity_mut.get_mut::().unwrap(); + **last_sent_position = new_position; + let mut position = entity_mut.get_mut::().unwrap(); + **position = new_position; - physics.set_on_ground(p.on_ground); + let mut look_direction = entity_mut.get_mut::().unwrap(); + *look_direction = new_look_direction; + }), + }); + + system_state.apply(ecs); } ClientboundGamePacket::SelectAdvancementsTab(_) => {}