Skip to content

Commit 3f32878

Browse files
committed
implement EntityPositionSync
1 parent 2feef49 commit 3f32878

File tree

15 files changed

+215
-83
lines changed

15 files changed

+215
-83
lines changed

azalea-client/src/movement.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ pub fn send_position(
195195
pos: **position,
196196
x_rot: direction.x_rot,
197197
y_rot: direction.y_rot,
198-
on_ground: physics.on_ground,
198+
on_ground: physics.on_ground(),
199199
}
200200
.into_variant(),
201201
)
@@ -205,7 +205,7 @@ pub fn send_position(
205205
x: position.x,
206206
y: position.y,
207207
z: position.z,
208-
on_ground: physics.on_ground,
208+
on_ground: physics.on_ground(),
209209
}
210210
.into_variant(),
211211
)
@@ -214,14 +214,14 @@ pub fn send_position(
214214
ServerboundMovePlayerRot {
215215
x_rot: direction.x_rot,
216216
y_rot: direction.y_rot,
217-
on_ground: physics.on_ground,
217+
on_ground: physics.on_ground(),
218218
}
219219
.into_variant(),
220220
)
221-
} else if physics.last_on_ground != physics.on_ground {
221+
} else if physics.last_on_ground() != physics.on_ground() {
222222
Some(
223223
ServerboundMovePlayerStatusOnly {
224-
on_ground: physics.on_ground,
224+
on_ground: physics.on_ground(),
225225
}
226226
.into_variant(),
227227
)
@@ -238,7 +238,8 @@ pub fn send_position(
238238
last_direction.x_rot = direction.x_rot;
239239
}
240240

241-
physics.last_on_ground = physics.on_ground;
241+
let on_ground = physics.on_ground();
242+
physics.set_last_on_ground(on_ground);
242243
// minecraft checks for autojump here, but also autojump is bad so
243244

244245
packet

azalea-client/src/packet_handling/game.rs

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,16 @@ pub fn process_packet_events(ecs: &mut World) {
451451
let new_y = apply_change(position.y, p.relative.y, p.change.pos.y);
452452
let new_z = apply_change(position.z, p.relative.z, p.change.pos.z);
453453

454-
let new_y_rot = apply_change(direction.y_rot, p.relative.y_rot, p.change.y_rot);
455-
let new_x_rot = apply_change(direction.x_rot, p.relative.x_rot, p.change.x_rot);
454+
let new_y_rot = apply_change(
455+
direction.y_rot,
456+
p.relative.y_rot,
457+
p.change.look_direction.y_rot,
458+
);
459+
let new_x_rot = apply_change(
460+
direction.x_rot,
461+
p.relative.x_rot,
462+
p.change.look_direction.x_rot,
463+
);
456464

457465
let mut new_delta_from_rotations = physics.velocity;
458466
if p.relative.rotate_delta {
@@ -873,12 +881,21 @@ pub fn process_packet_events(ecs: &mut World) {
873881
let entity = entity_id_index.get(&MinecraftEntityId(p.entity_id));
874882

875883
if let Some(entity) = entity {
876-
let delta = p.delta.clone();
884+
let new_delta = p.delta.clone();
885+
let new_on_ground = p.on_ground;
877886
commands.entity(entity).queue(RelativeEntityUpdate {
878887
partial_world: instance_holder.partial_instance.clone(),
879888
update: Box::new(move |entity_mut| {
889+
let mut physics = entity_mut.get_mut::<Physics>().unwrap();
890+
let new_pos = physics.vec_delta_codec.decode(
891+
new_delta.xa as i64,
892+
new_delta.ya as i64,
893+
new_delta.za as i64,
894+
);
895+
physics.vec_delta_codec.set_base(new_pos);
896+
physics.set_on_ground(new_on_ground);
897+
880898
let mut position = entity_mut.get_mut::<Position>().unwrap();
881-
let new_pos = position.with_delta(&delta);
882899
if new_pos != **position {
883900
**position = new_pos;
884901
}
@@ -904,20 +921,31 @@ pub fn process_packet_events(ecs: &mut World) {
904921
let entity = entity_id_index.get(&MinecraftEntityId(p.entity_id));
905922

906923
if let Some(entity) = entity {
907-
let delta = p.delta.clone();
924+
let new_delta = p.delta.clone();
908925
let new_look_direction = LookDirection {
909926
x_rot: (p.x_rot as i32 * 360) as f32 / 256.,
910927
y_rot: (p.y_rot as i32 * 360) as f32 / 256.,
911928
};
912929

930+
let new_on_ground = p.on_ground;
931+
913932
commands.entity(entity).queue(RelativeEntityUpdate {
914933
partial_world: instance_holder.partial_instance.clone(),
915934
update: Box::new(move |entity_mut| {
935+
let mut physics = entity_mut.get_mut::<Physics>().unwrap();
936+
let new_pos = physics.vec_delta_codec.decode(
937+
new_delta.xa as i64,
938+
new_delta.ya as i64,
939+
new_delta.za as i64,
940+
);
941+
physics.vec_delta_codec.set_base(new_pos);
942+
physics.set_on_ground(new_on_ground);
943+
916944
let mut position = entity_mut.get_mut::<Position>().unwrap();
917-
let new_pos = position.with_delta(&delta);
918945
if new_pos != **position {
919946
**position = new_pos;
920947
}
948+
921949
let mut look_direction = entity_mut.get_mut::<LookDirection>().unwrap();
922950
if new_look_direction != *look_direction {
923951
*look_direction = new_look_direction;
@@ -949,10 +977,14 @@ pub fn process_packet_events(ecs: &mut World) {
949977
x_rot: (p.x_rot as i32 * 360) as f32 / 256.,
950978
y_rot: (p.y_rot as i32 * 360) as f32 / 256.,
951979
};
980+
let new_on_ground = p.on_ground;
952981

953982
commands.entity(entity).queue(RelativeEntityUpdate {
954983
partial_world: instance_holder.partial_instance.clone(),
955984
update: Box::new(move |entity_mut| {
985+
let mut physics = entity_mut.get_mut::<Physics>().unwrap();
986+
physics.set_on_ground(new_on_ground);
987+
956988
let mut look_direction = entity_mut.get_mut::<LookDirection>().unwrap();
957989
if new_look_direction != *look_direction {
958990
*look_direction = new_look_direction;
@@ -1416,7 +1448,7 @@ pub fn process_packet_events(ecs: &mut World) {
14161448
system_state.apply(ecs);
14171449
}
14181450

1419-
ClientboundGamePacket::StartConfiguration(_) => {
1451+
ClientboundGamePacket::StartConfiguration(_p) => {
14201452
let mut system_state: SystemState<(Commands, EventWriter<SendPacketEvent>)> =
14211453
SystemState::new(ecs);
14221454
let (mut commands, mut packet_events) = system_state.get_mut(ecs);
@@ -1434,6 +1466,55 @@ pub fn process_packet_events(ecs: &mut World) {
14341466
system_state.apply(ecs);
14351467
}
14361468

1469+
ClientboundGamePacket::EntityPositionSync(p) => {
1470+
debug!("Got entity position sync packet {p:?}");
1471+
1472+
let mut system_state: SystemState<(
1473+
Query<&EntityIdIndex>,
1474+
Query<(
1475+
&mut Physics,
1476+
&mut Position,
1477+
&mut LastSentPosition,
1478+
&mut LookDirection,
1479+
Option<&LocalEntity>,
1480+
)>,
1481+
)> = SystemState::new(ecs);
1482+
let (mut index_query, mut query) = system_state.get_mut(ecs);
1483+
let entity_id_index = index_query.get_mut(player_entity).unwrap();
1484+
let Some(entity) = entity_id_index.get(&MinecraftEntityId(p.id)) else {
1485+
warn!(
1486+
"Got entity position sync packet for unknown entity id {}",
1487+
p.id
1488+
);
1489+
continue;
1490+
};
1491+
1492+
let Ok((
1493+
mut physics,
1494+
mut position,
1495+
mut last_sent_position,
1496+
mut look_direction,
1497+
local_entity,
1498+
)) = query.get_mut(entity)
1499+
else {
1500+
continue;
1501+
};
1502+
1503+
physics.vec_delta_codec.set_base(**position);
1504+
1505+
if local_entity.is_some() {
1506+
debug!("Ignoring entity position sync packet for local player");
1507+
continue;
1508+
}
1509+
1510+
**last_sent_position = **position;
1511+
**position = p.values.pos;
1512+
1513+
*look_direction = p.values.look_direction;
1514+
1515+
physics.set_on_ground(p.on_ground);
1516+
}
1517+
14371518
ClientboundGamePacket::SelectAdvancementsTab(_) => {}
14381519
ClientboundGamePacket::SetActionBarText(_) => {}
14391520
ClientboundGamePacket::SetBorderCenter(_) => {}
@@ -1476,7 +1557,6 @@ pub fn process_packet_events(ecs: &mut World) {
14761557
ClientboundGamePacket::ProjectilePower(_) => {}
14771558
ClientboundGamePacket::CustomReportDetails(_) => {}
14781559
ClientboundGamePacket::ServerLinks(_) => {}
1479-
ClientboundGamePacket::EntityPositionSync(_) => {}
14801560
ClientboundGamePacket::PlayerRotation(_) => {}
14811561
ClientboundGamePacket::RecipeBookAdd(_) => {}
14821562
ClientboundGamePacket::RecipeBookRemove(_) => {}

azalea-core/src/position.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ macro_rules! vec3_impl {
2020
($name:ident, $type:ty) => {
2121
impl $name {
2222
#[inline]
23-
pub fn new(x: $type, y: $type, z: $type) -> Self {
23+
pub const fn new(x: $type, y: $type, z: $type) -> Self {
2424
Self { x, y, z }
2525
}
2626

@@ -223,6 +223,8 @@ pub struct Vec3 {
223223
vec3_impl!(Vec3, f64);
224224

225225
impl Vec3 {
226+
pub const ZERO: Vec3 = Vec3::new(0.0, 0.0, 0.0);
227+
226228
/// Get the distance of this vector to the origin by doing
227229
/// `sqrt(x^2 + y^2 + z^2)`.
228230
pub fn length(&self) -> f64 {

azalea-entity/src/dimensions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub struct EntityDimensions {
77
}
88

99
impl EntityDimensions {
10-
pub fn make_bounding_box(&self, pos: &Vec3) -> AABB {
10+
pub fn make_bounding_box(&self, pos: Vec3) -> AABB {
1111
let radius = (self.width / 2.0) as f64;
1212
let height = self.height as f64;
1313
AABB {

azalea-entity/src/lib.rs

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod metadata;
99
pub mod mining;
1010
pub mod particle;
1111
mod plugin;
12+
pub mod vec_delta_codec;
1213

1314
use std::{
1415
fmt::Debug,
@@ -17,6 +18,7 @@ use std::{
1718

1819
pub use attributes::Attributes;
1920
use azalea_block::BlockState;
21+
use azalea_buf::AzBuf;
2022
use azalea_core::{
2123
aabb::AABB,
2224
math,
@@ -30,6 +32,7 @@ use derive_more::{Deref, DerefMut};
3032
pub use dimensions::EntityDimensions;
3133
use plugin::indexing::EntityChunkPos;
3234
use uuid::Uuid;
35+
use vec_delta_codec::VecDeltaCodec;
3336

3437
use self::attributes::AttributeInstance;
3538
pub use crate::plugin::*;
@@ -210,7 +213,7 @@ impl From<&LastSentPosition> for BlockPos {
210213
pub struct Jumping(bool);
211214

212215
/// A component that contains the direction an entity is looking.
213-
#[derive(Debug, Component, Copy, Clone, Default, PartialEq)]
216+
#[derive(Debug, Component, Copy, Clone, Default, PartialEq, AzBuf)]
214217
pub struct LookDirection {
215218
/// Left and right. Aka yaw.
216219
pub y_rot: f32,
@@ -245,7 +248,7 @@ impl Eq for LookDirection {}
245248

246249
/// The physics data relating to the entity, such as position, velocity, and
247250
/// bounding box.
248-
#[derive(Debug, Component, Clone)]
251+
#[derive(Debug, Component, Clone, Default)]
249252
pub struct Physics {
250253
/// How fast the entity is moving.
251254
pub velocity: Vec3,
@@ -257,8 +260,10 @@ pub struct Physics {
257260
/// Z acceleration.
258261
pub zza: f32,
259262

260-
pub on_ground: bool,
261-
pub last_on_ground: bool,
263+
on_ground: bool,
264+
last_on_ground: bool,
265+
266+
pub vec_delta_codec: VecDeltaCodec,
262267

263268
/// The width and height of the entity.
264269
pub dimensions: EntityDimensions,
@@ -274,7 +279,7 @@ pub struct Physics {
274279
}
275280

276281
impl Physics {
277-
pub fn new(dimensions: EntityDimensions, pos: &Vec3) -> Self {
282+
pub fn new(dimensions: EntityDimensions, pos: Vec3) -> Self {
278283
Self {
279284
velocity: Vec3::default(),
280285

@@ -292,8 +297,30 @@ impl Physics {
292297

293298
horizontal_collision: false,
294299
vertical_collision: false,
300+
301+
vec_delta_codec: VecDeltaCodec::new(pos),
295302
}
296303
}
304+
305+
pub fn on_ground(&self) -> bool {
306+
self.on_ground
307+
}
308+
/// Updates [`Self::on_ground`] and [`Self::last_on_ground`].
309+
pub fn set_on_ground(&mut self, on_ground: bool) {
310+
self.last_on_ground = self.on_ground;
311+
self.on_ground = on_ground;
312+
}
313+
314+
/// The last value of the on_ground value.
315+
///
316+
/// This is used by Azalea internally for physics, it might not work as you
317+
/// expect since it can be influenced by packets sent by the server.
318+
pub fn last_on_ground(&self) -> bool {
319+
self.last_on_ground
320+
}
321+
pub fn set_last_on_ground(&mut self, last_on_ground: bool) {
322+
self.last_on_ground = last_on_ground;
323+
}
297324
}
298325

299326
/// Marker component for entities that are dead.
@@ -384,7 +411,7 @@ impl EntityBundle {
384411
position: Position(pos),
385412
chunk_pos: EntityChunkPos(ChunkPos::from(&pos)),
386413
last_sent_position: LastSentPosition(pos),
387-
physics: Physics::new(dimensions, &pos),
414+
physics: Physics::new(dimensions, pos),
388415
eye_height: EyeHeight(eye_height),
389416
direction: LookDirection::default(),
390417

@@ -427,25 +454,3 @@ impl FluidOnEyes {
427454

428455
#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)]
429456
pub struct OnClimbable(bool);
430-
431-
// #[cfg(test)]
432-
// mod tests {
433-
// use super::*;
434-
// use crate::PartialWorld;
435-
436-
// #[test]
437-
// fn from_mut_entity_to_ref_entity() {
438-
// let mut world = PartialWorld::default();
439-
// let uuid = Uuid::from_u128(100);
440-
// world.add_entity(
441-
// 0,
442-
// EntityData::new(
443-
// uuid,
444-
// Vec3::default(),
445-
// EntityMetadata::Player(metadata::Player::default()),
446-
// ),
447-
// );
448-
// let entity: Entity = world.entity_mut(0).unwrap();
449-
// assert_eq!(entity.uuid, uuid);
450-
// }
451-
// }

azalea-entity/src/plugin/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ pub fn clamp_look_direction(mut query: Query<&mut LookDirection>) {
198198
/// Cached position in the world must be updated.
199199
pub fn update_bounding_box(mut query: Query<(&Position, &mut Physics), Changed<Position>>) {
200200
for (position, mut physics) in query.iter_mut() {
201-
let bounding_box = physics.dimensions.make_bounding_box(position);
201+
let bounding_box = physics.dimensions.make_bounding_box(**position);
202202
physics.bounding_box = bounding_box;
203203
}
204204
}

0 commit comments

Comments
 (0)