aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--azalea-client/src/plugins/disconnect.rs6
-rw-r--r--azalea-client/src/plugins/loading.rs8
-rw-r--r--azalea-client/src/plugins/movement.rs12
-rw-r--r--azalea-client/src/plugins/packet/game/mod.rs21
-rw-r--r--azalea-client/src/test_utils/simulation.rs6
-rw-r--r--azalea-client/tests/packet_order.rs23
-rw-r--r--azalea-client/tests/teleport_movement.rs180
-rw-r--r--azalea-entity/src/plugin/mod.rs6
-rw-r--r--azalea-physics/src/collision/mod.rs6
-rw-r--r--azalea-physics/src/fluids.rs10
-rw-r--r--azalea-physics/src/lib.rs6
-rw-r--r--azalea-physics/src/travel.rs4
-rw-r--r--azalea-physics/tests/physics.rs10
-rw-r--r--azalea-protocol/src/common/movements.rs2
-rw-r--r--azalea-protocol/src/packets/game/s_move_player_pos.rs2
-rw-r--r--azalea-protocol/src/packets/game/s_move_player_pos_rot.rs2
-rw-r--r--azalea/src/pathfinder/simulation.rs1
17 files changed, 247 insertions, 58 deletions
diff --git a/azalea-client/src/plugins/disconnect.rs b/azalea-client/src/plugins/disconnect.rs
index ab39ba5e..3cb9e82a 100644
--- a/azalea-client/src/plugins/disconnect.rs
+++ b/azalea-client/src/plugins/disconnect.rs
@@ -1,7 +1,9 @@
//! Disconnect a client from the server.
use azalea_chat::FormattedText;
-use azalea_entity::{EntityBundle, InLoadedChunk, LocalEntity, metadata::PlayerMetadataBundle};
+use azalea_entity::{
+ EntityBundle, HasClientLoaded, InLoadedChunk, LocalEntity, metadata::PlayerMetadataBundle,
+};
use azalea_world::MinecraftEntityId;
use bevy_app::{App, Plugin, PostUpdate};
use bevy_ecs::prelude::*;
@@ -10,7 +12,7 @@ use tracing::info;
use super::login::IsAuthenticated;
use crate::{
- chat_signing, client::JoinedClientBundle, connection::RawConnection, loading::HasClientLoaded,
+ chat_signing, client::JoinedClientBundle, connection::RawConnection,
local_player::InstanceHolder, tick_counter::TicksConnected,
};
diff --git a/azalea-client/src/plugins/loading.rs b/azalea-client/src/plugins/loading.rs
index 4e993a4b..86c2b2de 100644
--- a/azalea-client/src/plugins/loading.rs
+++ b/azalea-client/src/plugins/loading.rs
@@ -1,5 +1,5 @@
use azalea_core::tick::GameTick;
-use azalea_entity::{InLoadedChunk, LocalEntity};
+use azalea_entity::{HasClientLoaded, InLoadedChunk, LocalEntity, update_in_loaded_chunk};
use azalea_physics::PhysicsSet;
use azalea_protocol::packets::game::ServerboundPlayerLoaded;
use bevy_app::{App, Plugin};
@@ -12,8 +12,10 @@ impl Plugin for PlayerLoadedPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
GameTick,
+ // vanilla runs this on gameMode.tick()
player_loaded_packet
- .after(PhysicsSet)
+ .after(update_in_loaded_chunk)
+ .before(PhysicsSet)
.before(MiningSet)
.before(crate::movement::send_position),
);
@@ -27,8 +29,6 @@ impl Plugin for PlayerLoadedPlugin {
// i prefer the client one because it makes it clear that the component is only
// present on our own clients
-#[derive(Component)]
-pub struct HasClientLoaded;
#[allow(clippy::type_complexity)]
pub fn player_loaded_packet(
mut commands: Commands,
diff --git a/azalea-client/src/plugins/movement.rs b/azalea-client/src/plugins/movement.rs
index 675796f6..c9b3b070 100644
--- a/azalea-client/src/plugins/movement.rs
+++ b/azalea-client/src/plugins/movement.rs
@@ -5,7 +5,7 @@ use azalea_core::{
tick::GameTick,
};
use azalea_entity::{
- Attributes, InLoadedChunk, Jumping, LastSentPosition, LookDirection, Physics, Position,
+ Attributes, HasClientLoaded, Jumping, LastSentPosition, LookDirection, Physics, Position,
metadata::Sprinting,
};
use azalea_physics::{PhysicsSet, ai_step};
@@ -155,7 +155,7 @@ pub fn send_position(
&mut Physics,
&mut LastSentLookDirection,
),
- With<InLoadedChunk>,
+ With<HasClientLoaded>,
>,
mut commands: Commands,
) {
@@ -183,9 +183,9 @@ pub fn send_position(
// boolean sendingPosition = Mth.lengthSquared(xDelta, yDelta, zDelta) >
// Mth.square(2.0E-4D) || this.positionReminder >= 20;
- let sending_position = ((x_delta.powi(2) + y_delta.powi(2) + z_delta.powi(2))
- > 2.0e-4f64.powi(2))
- || physics_state.position_remainder >= 20;
+ let is_delta_large_enough =
+ (x_delta.powi(2) + y_delta.powi(2) + z_delta.powi(2)) > 2.0e-4f64.powi(2);
+ let sending_position = is_delta_large_enough || physics_state.position_remainder >= 20;
let sending_direction = y_rot_delta != 0.0 || x_rot_delta != 0.0;
// if self.is_passenger() {
@@ -348,7 +348,7 @@ pub(crate) fn tick_controls(mut query: Query<&mut PhysicsState>) {
pub fn local_player_ai_step(
mut query: Query<
(&PhysicsState, &mut Physics, &mut Sprinting, &mut Attributes),
- With<InLoadedChunk>,
+ With<HasClientLoaded>,
>,
) {
for (physics_state, mut physics, mut sprinting, mut attributes) in query.iter_mut() {
diff --git a/azalea-client/src/plugins/packet/game/mod.rs b/azalea-client/src/plugins/packet/game/mod.rs
index fe294ad0..26d83195 100644
--- a/azalea-client/src/plugins/packet/game/mod.rs
+++ b/azalea-client/src/plugins/packet/game/mod.rs
@@ -7,8 +7,8 @@ use azalea_core::{
position::{ChunkPos, Vec3},
};
use azalea_entity::{
- Dead, EntityBundle, EntityKindComponent, LastSentPosition, LoadedBy, LocalEntity,
- LookDirection, Physics, Position, RelativeEntityUpdate,
+ Dead, EntityBundle, EntityKindComponent, HasClientLoaded, LoadedBy, LocalEntity, LookDirection,
+ Physics, Position, RelativeEntityUpdate,
indexing::{EntityIdIndex, EntityUuidIndex},
metadata::{Health, apply_metadata},
};
@@ -33,7 +33,6 @@ use crate::{
inventory::{
ClientSideCloseContainerEvent, Inventory, MenuOpenedEvent, SetContainerContentEvent,
},
- loading::HasClientLoaded,
local_player::{Hunger, InstanceHolder, LocalGameMode, PlayerAbilities, TabList},
movement::{KnockbackEvent, KnockbackType},
packet::as_system,
@@ -409,22 +408,13 @@ impl GamePacketHandler<'_> {
debug!("Got player position packet {p:?}");
as_system::<(
- Query<(
- &mut Physics,
- &mut LookDirection,
- &mut Position,
- &mut LastSentPosition,
- )>,
+ Query<(&mut Physics, &mut LookDirection, &mut Position)>,
Commands,
)>(self.ecs, |(mut query, mut commands)| {
- let Ok((mut physics, mut direction, mut position, mut last_sent_position)) =
- query.get_mut(self.player)
- else {
+ let Ok((mut physics, mut direction, mut position)) = query.get_mut(self.player) else {
return;
};
- **last_sent_position = **position;
-
p.relative
.apply(&p.change, &mut position, &mut direction, &mut physics);
// old_pos is set to the current position when we're teleported
@@ -1500,9 +1490,6 @@ impl GamePacketHandler<'_> {
physics.set_on_ground(new_on_ground);
- let mut last_sent_position =
- entity_mut.get_mut::<LastSentPosition>().unwrap();
- **last_sent_position = new_position;
let mut position = entity_mut.get_mut::<Position>().unwrap();
**position = new_position;
diff --git a/azalea-client/src/test_utils/simulation.rs b/azalea-client/src/test_utils/simulation.rs
index d898293c..a763962b 100644
--- a/azalea-client/src/test_utils/simulation.rs
+++ b/azalea-client/src/test_utils/simulation.rs
@@ -206,6 +206,12 @@ impl SentPackets {
matches!(p, ServerboundGamePacket::ClientTickEnd(_))
});
}
+ pub fn expect_pong(&self, id: u32) {
+ self.expect(
+ &format!("Ping {{ id: {id} }}"),
+ |p| matches!(p, ServerboundGamePacket::Pong(pong) if pong.id == id),
+ );
+ }
pub fn expect_empty(&self) {
let sent_packet = self.next();
if sent_packet.is_some() {
diff --git a/azalea-client/tests/packet_order.rs b/azalea-client/tests/packet_order.rs
index 014d9f46..f9e3f43b 100644
--- a/azalea-client/tests/packet_order.rs
+++ b/azalea-client/tests/packet_order.rs
@@ -11,8 +11,7 @@ use azalea_protocol::{
config::{ClientboundFinishConfiguration, ClientboundRegistryData},
game::{
ClientboundBlockUpdate, ClientboundPlayerPosition, ServerboundAcceptTeleportation,
- ServerboundGamePacket, ServerboundMovePlayerPos, ServerboundMovePlayerPosRot,
- ServerboundMovePlayerStatusOnly,
+ ServerboundGamePacket, ServerboundMovePlayerPosRot, ServerboundMovePlayerStatusOnly,
},
},
};
@@ -80,13 +79,15 @@ fn test_packet_order() {
sent_packets.expect("MovePlayerPosRot", |p| {
matches!(
p,
- ServerboundGamePacket::MovePlayerPosRot(ServerboundMovePlayerPosRot {
+ ServerboundGamePacket::MovePlayerPosRot(p)
+ if p == &ServerboundMovePlayerPosRot {
flags: MoveFlags {
on_ground: false,
horizontal_collision: false
},
- ..
- })
+ pos: Vec3::new(1.5, 2., 3.5),
+ look_direction: LookDirection::default(),
+ }
)
});
@@ -99,13 +100,11 @@ fn test_packet_order() {
sent_packets.expect("MovePlayerPos", |p| {
matches!(
p,
- ServerboundGamePacket::MovePlayerPos(ServerboundMovePlayerPos {
- flags: MoveFlags {
- on_ground: false,
- horizontal_collision: false
- },
- ..
- })
+ ServerboundGamePacket::MovePlayerPos(p)
+ if p.flags == MoveFlags {
+ on_ground: false,
+ horizontal_collision: false
+ }
)
});
diff --git a/azalea-client/tests/teleport_movement.rs b/azalea-client/tests/teleport_movement.rs
new file mode 100644
index 00000000..a03e730c
--- /dev/null
+++ b/azalea-client/tests/teleport_movement.rs
@@ -0,0 +1,180 @@
+use azalea_client::test_utils::prelude::*;
+use azalea_core::{
+ delta::PositionDelta8,
+ position::{BlockPos, ChunkPos, Vec3},
+ resource_location::ResourceLocation,
+};
+use azalea_entity::LookDirection;
+use azalea_protocol::{
+ common::movements::{MoveFlags, PositionMoveRotation, RelativeMovements},
+ packets::{
+ ConnectionProtocol,
+ config::{ClientboundFinishConfiguration, ClientboundRegistryData},
+ game::{
+ ClientboundBlockUpdate, ClientboundForgetLevelChunk, ClientboundPing,
+ ClientboundPlayerPosition, ClientboundSetChunkCacheCenter, ClientboundSetEntityMotion,
+ ServerboundGamePacket, ServerboundMovePlayerPos, ServerboundMovePlayerPosRot,
+ },
+ },
+};
+use azalea_registry::{Block, DataRegistry, DimensionType};
+use azalea_world::MinecraftEntityId;
+use simdnbt::owned::{NbtCompound, NbtTag};
+
+#[test]
+fn test_teleport_movement() {
+ init_tracing();
+
+ let mut simulation = Simulation::new(ConnectionProtocol::Configuration);
+ let sent_packets = SentPackets::new(&mut simulation);
+
+ simulation.receive_packet(ClientboundRegistryData {
+ registry_id: ResourceLocation::new("minecraft:dimension_type"),
+ entries: vec![(
+ ResourceLocation::new("minecraft:overworld"),
+ Some(NbtCompound::from_values(vec![
+ ("height".into(), NbtTag::Int(384)),
+ ("min_y".into(), NbtTag::Int(-64)),
+ ])),
+ )]
+ .into_iter()
+ .collect(),
+ });
+ simulation.tick();
+ simulation.receive_packet(ClientboundFinishConfiguration);
+ simulation.tick();
+
+ simulation.receive_packet(make_basic_login_packet(
+ DimensionType::new_raw(0), // overworld
+ ResourceLocation::new("minecraft:overworld"),
+ ));
+ simulation.tick();
+
+ sent_packets.expect_tick_end();
+ sent_packets.expect_empty();
+
+ // receive a chunk so the player is "loaded" now
+ simulation.receive_packet(ClientboundSetChunkCacheCenter { x: 1, z: 23 });
+ simulation.receive_packet(make_basic_empty_chunk(
+ ChunkPos::new(1, 23),
+ (384 + 64) / 16,
+ ));
+ simulation.receive_packet(ClientboundBlockUpdate {
+ pos: BlockPos::new(31, 63, 370),
+ block_state: Block::Stone.into(),
+ });
+ simulation.receive_packet(ClientboundPlayerPosition {
+ id: 1,
+ change: PositionMoveRotation {
+ pos: Vec3::new(31.5, 64., 370.5),
+ delta: Vec3::ZERO,
+ look_direction: LookDirection::default(),
+ },
+ relative: RelativeMovements::all_absolute(),
+ });
+ simulation.tick();
+ simulation.tick();
+ sent_packets.clear();
+
+ // now teleport to a far-away location
+ tracing::info!("meow!");
+ simulation.receive_packet(ClientboundPing { id: 1 });
+ simulation.receive_packet(ClientboundPlayerPosition {
+ id: 2,
+ change: PositionMoveRotation {
+ pos: Vec3::new(10000.5, 70.0, 0.5),
+ delta: Vec3::ZERO,
+ look_direction: LookDirection::default(),
+ },
+ relative: RelativeMovements::all_absolute(),
+ });
+ simulation.receive_packet(ClientboundPing { id: 2 });
+ simulation.tick();
+ sent_packets.expect_pong(1);
+ sent_packets.expect("AcceptTeleportation", |p| {
+ matches!(p, ServerboundGamePacket::AcceptTeleportation(_))
+ });
+ sent_packets.expect("MovePlayerPosRot", |p| {
+ matches!(
+ p,
+ ServerboundGamePacket::MovePlayerPosRot(p)
+ if p == &ServerboundMovePlayerPosRot {
+ pos: Vec3::new(10000.5, 70.0, 0.5),
+ flags: MoveFlags::default(),
+ look_direction: LookDirection::default(),
+ }
+ )
+ });
+ sent_packets.expect_pong(2);
+ sent_packets.expect("MovePlayerPos", |p| {
+ matches!(
+ p,
+ ServerboundGamePacket::MovePlayerPos(p)
+ if p == &ServerboundMovePlayerPos {
+ pos: Vec3::new(10000.5, 70.0, 0.5),
+ flags: MoveFlags::default()
+ }
+ )
+ });
+
+ sent_packets.expect_tick_end();
+ sent_packets.expect_empty();
+
+ //
+
+ simulation.receive_packet(ClientboundForgetLevelChunk {
+ pos: ChunkPos { x: 1, z: 23 },
+ });
+ simulation.receive_packet(ClientboundSetChunkCacheCenter { x: 625, z: 0 });
+ simulation.receive_packet(ClientboundPing { id: 3 });
+ simulation.receive_packet(ClientboundPlayerPosition {
+ id: 3,
+ change: PositionMoveRotation {
+ pos: Vec3::new(10000.5, 70.0000001, 0.5),
+ delta: Vec3::ZERO,
+ look_direction: LookDirection::default(),
+ },
+ relative: RelativeMovements::all_absolute(),
+ });
+ simulation.receive_packet(ClientboundPing { id: 4 });
+ simulation.receive_packet(ClientboundSetEntityMotion {
+ id: MinecraftEntityId(0),
+ delta: PositionDelta8 {
+ xa: 0,
+ ya: -627,
+ za: 0,
+ },
+ });
+ simulation.receive_packet(ClientboundPing { id: 5 });
+ simulation.tick();
+
+ sent_packets.expect_pong(3);
+ sent_packets.expect("AcceptTeleportation", |p| {
+ matches!(p, ServerboundGamePacket::AcceptTeleportation(_))
+ });
+ sent_packets.expect("MovePlayerPosRot", |p| {
+ matches!(
+ p,
+ ServerboundGamePacket::MovePlayerPosRot(p)
+ if p == &ServerboundMovePlayerPosRot {
+ pos: Vec3::new(10000.5, 70.0000001, 0.5),
+ flags: MoveFlags::default(),
+ look_direction: LookDirection::default(),
+ })
+ });
+ sent_packets.expect_pong(4);
+ sent_packets.expect_pong(5);
+ sent_packets.expect("MovePlayerPos", |p| {
+ matches!(
+ p,
+ ServerboundGamePacket::MovePlayerPos(p)
+ if p == &ServerboundMovePlayerPos {
+ pos: Vec3::new(10000.5, 69.9216251, 0.5),
+ flags: MoveFlags::default()
+ }
+ )
+ });
+
+ sent_packets.expect_tick_end();
+ sent_packets.expect_empty();
+}
diff --git a/azalea-entity/src/plugin/mod.rs b/azalea-entity/src/plugin/mod.rs
index 924a6f53..ee6bca61 100644
--- a/azalea-entity/src/plugin/mod.rs
+++ b/azalea-entity/src/plugin/mod.rs
@@ -238,6 +238,12 @@ pub fn update_in_loaded_chunk(
}
}
+/// A component that indicates whether the client has loaded.
+///
+/// This is updated by a system in `azalea-client`.
+#[derive(Component)]
+pub struct HasClientLoaded;
+
#[cfg(test)]
mod tests {
use azalea_block::{
diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs
index 41fc6c85..dc439f7b 100644
--- a/azalea-physics/src/collision/mod.rs
+++ b/azalea-physics/src/collision/mod.rs
@@ -171,11 +171,11 @@ pub fn move_colliding(
let x_collision = movement.x != collide_result.x;
let z_collision = movement.z != collide_result.z;
let horizontal_collision = x_collision || z_collision;
- let vertical_collision = movement.y != collide_result.y;
- let on_ground = vertical_collision && movement.y < 0.;
-
physics.horizontal_collision = horizontal_collision;
+
+ let vertical_collision = movement.y != collide_result.y;
physics.vertical_collision = vertical_collision;
+ let on_ground = vertical_collision && movement.y < 0.;
physics.set_on_ground(on_ground);
// TODO: minecraft checks for a "minor" horizontal collision here
diff --git a/azalea-physics/src/fluids.rs b/azalea-physics/src/fluids.rs
index ea0f12e2..c37a9917 100644
--- a/azalea-physics/src/fluids.rs
+++ b/azalea-physics/src/fluids.rs
@@ -7,7 +7,7 @@ use azalea_core::{
position::{BlockPos, Vec3},
resource_location::ResourceLocation,
};
-use azalea_entity::{InLoadedChunk, LocalEntity, Physics, Position};
+use azalea_entity::{HasClientLoaded, LocalEntity, Physics, Position};
use azalea_world::{Instance, InstanceContainer, InstanceName};
use bevy_ecs::prelude::*;
@@ -17,14 +17,14 @@ use crate::collision::legacy_blocks_motion;
pub fn update_in_water_state_and_do_fluid_pushing(
mut query: Query<
(&mut Physics, &Position, &InstanceName),
- (With<LocalEntity>, With<InLoadedChunk>),
+ (With<LocalEntity>, With<HasClientLoaded>),
>,
instance_container: Res<InstanceContainer>,
) {
for (mut physics, position, instance_name) in &mut query {
- let world_lock = instance_container
- .get(instance_name)
- .expect("All entities with InLoadedChunk should be in a valid world");
+ let Some(world_lock) = instance_container.get(instance_name) else {
+ continue;
+ };
let world = world_lock.read();
// reset the heights since they're going to be set in
diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs
index 2063f0f0..27250f61 100644
--- a/azalea-physics/src/lib.rs
+++ b/azalea-physics/src/lib.rs
@@ -15,7 +15,7 @@ use azalea_core::{
tick::GameTick,
};
use azalea_entity::{
- Attributes, EntityKindComponent, InLoadedChunk, Jumping, LocalEntity, LookDirection,
+ Attributes, EntityKindComponent, HasClientLoaded, Jumping, LocalEntity, LookDirection,
OnClimbable, Physics, Pose, Position, metadata::Sprinting, move_relative,
};
use azalea_registry::{Block, EntityKind};
@@ -68,7 +68,7 @@ pub fn ai_step(
&InstanceName,
&EntityKindComponent,
),
- (With<LocalEntity>, With<InLoadedChunk>),
+ (With<LocalEntity>, With<HasClientLoaded>),
>,
instance_container: Res<InstanceContainer>,
) {
@@ -162,7 +162,7 @@ fn jump_in_liquid(physics: &mut Physics) {
pub fn apply_effects_from_blocks(
mut query: Query<
(&mut Physics, &Position, &InstanceName),
- (With<LocalEntity>, With<InLoadedChunk>),
+ (With<LocalEntity>, With<HasClientLoaded>),
>,
instance_container: Res<InstanceContainer>,
) {
diff --git a/azalea-physics/src/travel.rs b/azalea-physics/src/travel.rs
index 9af3ed27..80c289d9 100644
--- a/azalea-physics/src/travel.rs
+++ b/azalea-physics/src/travel.rs
@@ -4,7 +4,7 @@ use azalea_core::{
position::{BlockPos, Vec3},
};
use azalea_entity::{
- Attributes, InLoadedChunk, Jumping, LocalEntity, LookDirection, OnClimbable, Physics, Pose,
+ Attributes, HasClientLoaded, Jumping, LocalEntity, LookDirection, OnClimbable, Physics, Pose,
Position, metadata::Sprinting, move_relative,
};
use azalea_world::{Instance, InstanceContainer, InstanceName};
@@ -37,7 +37,7 @@ pub fn travel(
&OnClimbable,
&Jumping,
),
- (With<LocalEntity>, With<InLoadedChunk>),
+ (With<LocalEntity>, With<HasClientLoaded>),
>,
instance_container: Res<InstanceContainer>,
physics_query: PhysicsQuery,
diff --git a/azalea-physics/tests/physics.rs b/azalea-physics/tests/physics.rs
index 8150e5b0..b312b31e 100644
--- a/azalea-physics/tests/physics.rs
+++ b/azalea-physics/tests/physics.rs
@@ -10,7 +10,7 @@ use azalea_core::{
resource_location::ResourceLocation,
tick::GameTick,
};
-use azalea_entity::{EntityBundle, EntityPlugin, LocalEntity, Physics, Position};
+use azalea_entity::{EntityBundle, EntityPlugin, HasClientLoaded, LocalEntity, Physics, Position};
use azalea_physics::PhysicsPlugin;
use azalea_world::{Chunk, Instance, InstanceContainer, MinecraftEntityId, PartialInstance};
use bevy_app::App;
@@ -63,6 +63,7 @@ fn test_gravity() {
),
MinecraftEntityId(0),
LocalEntity,
+ HasClientLoaded,
))
.id();
{
@@ -118,6 +119,7 @@ fn test_collision() {
),
MinecraftEntityId(0),
LocalEntity,
+ HasClientLoaded,
))
.id();
let block_state = partial_world.chunks.set_block_state(
@@ -174,6 +176,7 @@ fn test_slab_collision() {
),
MinecraftEntityId(0),
LocalEntity,
+ HasClientLoaded,
))
.id();
let block_state = partial_world.chunks.set_block_state(
@@ -224,6 +227,7 @@ fn test_top_slab_collision() {
),
MinecraftEntityId(0),
LocalEntity,
+ HasClientLoaded,
))
.id();
let block_state = world_lock.write().chunks.set_block_state(
@@ -281,6 +285,7 @@ fn test_weird_wall_collision() {
),
MinecraftEntityId(0),
LocalEntity,
+ HasClientLoaded,
))
.id();
let block_state = world_lock.write().chunks.set_block_state(
@@ -343,6 +348,7 @@ fn test_negative_coordinates_weird_wall_collision() {
),
MinecraftEntityId(0),
LocalEntity,
+ HasClientLoaded,
))
.id();
let block_state = world_lock.write().chunks.set_block_state(
@@ -409,6 +415,7 @@ fn spawn_and_unload_world() {
),
MinecraftEntityId(0),
LocalEntity,
+ HasClientLoaded,
))
.id();
@@ -524,6 +531,7 @@ fn test_afk_pool() {
),
MinecraftEntityId(0),
LocalEntity,
+ HasClientLoaded,
))
.id();
diff --git a/azalea-protocol/src/common/movements.rs b/azalea-protocol/src/common/movements.rs
index 265b4b65..f6611fc6 100644
--- a/azalea-protocol/src/common/movements.rs
+++ b/azalea-protocol/src/common/movements.rs
@@ -133,7 +133,7 @@ impl AzaleaWrite for RelativeMovements {
}
}
-#[derive(Clone, Copy, Debug, Default)]
+#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct MoveFlags {
pub on_ground: bool,
pub horizontal_collision: bool,
diff --git a/azalea-protocol/src/packets/game/s_move_player_pos.rs b/azalea-protocol/src/packets/game/s_move_player_pos.rs
index fd1f4a9f..9f840f8e 100644
--- a/azalea-protocol/src/packets/game/s_move_player_pos.rs
+++ b/azalea-protocol/src/packets/game/s_move_player_pos.rs
@@ -4,7 +4,7 @@ use azalea_protocol_macros::ServerboundGamePacket;
use crate::common::movements::MoveFlags;
-#[derive(Clone, Debug, AzBuf, ServerboundGamePacket)]
+#[derive(Clone, Debug, AzBuf, ServerboundGamePacket, PartialEq)]
pub struct ServerboundMovePlayerPos {
pub pos: Vec3,
pub flags: MoveFlags,
diff --git a/azalea-protocol/src/packets/game/s_move_player_pos_rot.rs b/azalea-protocol/src/packets/game/s_move_player_pos_rot.rs
index feee0137..b8ea0b9b 100644
--- a/azalea-protocol/src/packets/game/s_move_player_pos_rot.rs
+++ b/azalea-protocol/src/packets/game/s_move_player_pos_rot.rs
@@ -5,7 +5,7 @@ use azalea_protocol_macros::ServerboundGamePacket;
use crate::common::movements::MoveFlags;
-#[derive(Clone, Debug, AzBuf, ServerboundGamePacket)]
+#[derive(Clone, Debug, AzBuf, ServerboundGamePacket, PartialEq)]
pub struct ServerboundMovePlayerPosRot {
pub pos: Vec3,
pub look_direction: LookDirection,
diff --git a/azalea/src/pathfinder/simulation.rs b/azalea/src/pathfinder/simulation.rs
index 7f93a671..8f198ce8 100644
--- a/azalea/src/pathfinder/simulation.rs
+++ b/azalea/src/pathfinder/simulation.rs
@@ -69,6 +69,7 @@ fn create_simulation_instance(chunks: ChunkStorage) -> (App, Arc<RwLock<Instance
azalea_client::inventory::InventoryPlugin,
azalea_client::mining::MiningPlugin,
azalea_client::interact::InteractPlugin,
+ azalea_client::loading::PlayerLoadedPlugin,
))
.insert_resource(InstanceContainer {
instances: [(instance_name.clone(), Arc::downgrade(&instance.clone()))]