diff options
Diffstat (limited to 'azalea-client')
| -rw-r--r-- | azalea-client/src/test_simulation.rs | 77 | ||||
| -rw-r--r-- | azalea-client/tests/change_dimension_to_nether_and_back.rs | 21 | ||||
| -rw-r--r-- | azalea-client/tests/client_disconnect.rs | 21 | ||||
| -rw-r--r-- | azalea-client/tests/despawn_entities_when_changing_dimension.rs | 22 | ||||
| -rw-r--r-- | azalea-client/tests/move_despawned_entity.rs | 51 |
5 files changed, 156 insertions, 36 deletions
diff --git a/azalea-client/src/test_simulation.rs b/azalea-client/src/test_simulation.rs index 67dcb818..564db0cf 100644 --- a/azalea-client/src/test_simulation.rs +++ b/azalea-client/src/test_simulation.rs @@ -2,29 +2,32 @@ use std::{fmt::Debug, sync::Arc, time::Duration}; use azalea_auth::game_profile::GameProfile; use azalea_buf::AzaleaWrite; +use azalea_core::delta::PositionDelta8; use azalea_core::game_type::{GameMode, OptionalGameType}; -use azalea_core::position::ChunkPos; +use azalea_core::position::{ChunkPos, Vec3}; use azalea_core::resource_location::ResourceLocation; use azalea_core::tick::GameTick; use azalea_entity::metadata::PlayerMetadataBundle; use azalea_protocol::packets::common::CommonPlayerSpawnInfo; +use azalea_protocol::packets::config::{ClientboundFinishConfiguration, ClientboundRegistryData}; use azalea_protocol::packets::game::c_level_chunk_with_light::ClientboundLevelChunkPacketData; use azalea_protocol::packets::game::c_light_update::ClientboundLightUpdatePacketData; use azalea_protocol::packets::game::{ - ClientboundLevelChunkWithLight, ClientboundLogin, ClientboundRespawn, + ClientboundAddEntity, ClientboundLevelChunkWithLight, ClientboundLogin, ClientboundRespawn, }; use azalea_protocol::packets::{ConnectionProtocol, Packet, ProtocolPacket}; -use azalea_registry::DimensionType; +use azalea_registry::{DimensionType, EntityKind}; use azalea_world::palette::{PalettedContainer, PalettedContainerKind}; use azalea_world::{Chunk, Instance, MinecraftEntityId, Section}; use bevy_app::App; use bevy_ecs::{prelude::*, schedule::ExecutorKind}; use parking_lot::{Mutex, RwLock}; -use simdnbt::owned::Nbt; +use simdnbt::owned::{Nbt, NbtCompound, NbtTag}; use tokio::task::JoinHandle; use tokio::{sync::mpsc, time::sleep}; use uuid::Uuid; +use crate::disconnect::DisconnectEvent; use crate::{ ClientInformation, GameProfileComponent, InConfigState, InstanceHolder, LocalPlayerBundle, events::LocalPlayerEvents, @@ -48,29 +51,49 @@ impl Simulation { let mut app = create_simulation_app(); let mut entity = app.world_mut().spawn_empty(); let (player, clear_outgoing_packets_receiver_task, incoming_packet_queue, rt) = - create_local_player_bundle(entity.id(), initial_connection_protocol); + create_local_player_bundle(entity.id(), ConnectionProtocol::Configuration); entity.insert(player); let entity = entity.id(); tick_app(&mut app); - #[allow(clippy::single_match)] - match initial_connection_protocol { - ConnectionProtocol::Configuration => { - app.world_mut().entity_mut(entity).insert(InConfigState); - tick_app(&mut app); - } - _ => {} - } + // start in the config state + app.world_mut().entity_mut(entity).insert(InConfigState); + tick_app(&mut app); - Self { + let mut simulation = Self { app, entity, rt, incoming_packet_queue, clear_outgoing_packets_receiver_task, + }; + + #[allow(clippy::single_match)] + match initial_connection_protocol { + ConnectionProtocol::Configuration => {} + ConnectionProtocol::Game => { + 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.receive_packet(ClientboundFinishConfiguration); + simulation.tick(); + } + _ => unimplemented!("unsupported ConnectionProtocol {initial_connection_protocol:?}"), } + + simulation } pub fn receive_packet<P: ProtocolPacket + Debug>(&mut self, packet: impl Packet<P>) { @@ -98,6 +121,14 @@ impl Simulation { .chunks .get(&chunk_pos) } + + pub fn disconnect(&mut self) { + // send DisconnectEvent + self.app.world_mut().send_event(DisconnectEvent { + entity: self.entity, + reason: None, + }); + } } #[allow(clippy::type_complexity)] @@ -270,3 +301,21 @@ pub fn make_basic_empty_chunk( light_data: ClientboundLightUpdatePacketData::default(), } } + +pub fn make_basic_add_entity( + entity_type: EntityKind, + id: i32, + position: impl Into<Vec3>, +) -> ClientboundAddEntity { + ClientboundAddEntity { + id: id.into(), + uuid: Uuid::from_u128(1234), + entity_type, + position: position.into(), + x_rot: 0, + y_rot: 0, + y_head_rot: 0, + data: 0, + velocity: PositionDelta8::default(), + } +} diff --git a/azalea-client/tests/change_dimension_to_nether_and_back.rs b/azalea-client/tests/change_dimension_to_nether_and_back.rs index 748ea713..969c5053 100644 --- a/azalea-client/tests/change_dimension_to_nether_and_back.rs +++ b/azalea-client/tests/change_dimension_to_nether_and_back.rs @@ -2,7 +2,7 @@ use azalea_client::{InConfigState, InGameState, test_simulation::*}; use azalea_core::{position::ChunkPos, resource_location::ResourceLocation}; use azalea_entity::LocalEntity; use azalea_protocol::packets::{ - ConnectionProtocol, + ConnectionProtocol, Packet, config::{ClientboundFinishConfiguration, ClientboundRegistryData}, }; use azalea_registry::DimensionType; @@ -12,6 +12,21 @@ use simdnbt::owned::{NbtCompound, NbtTag}; #[test] fn test_change_dimension_to_nether_and_back() { + generic_test_change_dimension_to_nether_and_back(true); + generic_test_change_dimension_to_nether_and_back(false); +} + +fn generic_test_change_dimension_to_nether_and_back(using_respawn: bool) { + let make_basic_login_or_respawn_packet = if using_respawn { + |dimension: DimensionType, instance_name: ResourceLocation| { + make_basic_respawn_packet(dimension, instance_name).into_variant() + } + } else { + |dimension: DimensionType, instance_name: ResourceLocation| { + make_basic_login_packet(dimension, instance_name).into_variant() + } + }; + let _ = tracing_subscriber::fmt::try_init(); let mut simulation = Simulation::new(ConnectionProtocol::Configuration); @@ -83,7 +98,7 @@ fn test_change_dimension_to_nether_and_back() { // NETHER // - simulation.receive_packet(make_basic_respawn_packet( + simulation.receive_packet(make_basic_login_or_respawn_packet( DimensionType::new_raw(2), // nether ResourceLocation::new("azalea:b"), )); @@ -105,7 +120,7 @@ fn test_change_dimension_to_nether_and_back() { simulation .chunk(ChunkPos::new(0, 0)) .expect("chunk should exist"); - simulation.receive_packet(make_basic_respawn_packet( + simulation.receive_packet(make_basic_login_or_respawn_packet( DimensionType::new_raw(2), // nether ResourceLocation::new("minecraft:nether"), )); diff --git a/azalea-client/tests/client_disconnect.rs b/azalea-client/tests/client_disconnect.rs new file mode 100644 index 00000000..354ac788 --- /dev/null +++ b/azalea-client/tests/client_disconnect.rs @@ -0,0 +1,21 @@ +use azalea_client::test_simulation::*; +use azalea_protocol::packets::ConnectionProtocol; +use azalea_world::InstanceName; +use bevy_log::tracing_subscriber; + +#[test] +fn test_client_disconnect() { + let _ = tracing_subscriber::fmt::try_init(); + + let mut simulation = Simulation::new(ConnectionProtocol::Game); + + simulation.disconnect(); + simulation.tick(); + + // make sure we're disconnected + let is_connected = simulation.has_component::<InstanceName>(); + assert!(!is_connected); + + // tick again to make sure nothing goes wrong + simulation.tick(); +} diff --git a/azalea-client/tests/despawn_entities_when_changing_dimension.rs b/azalea-client/tests/despawn_entities_when_changing_dimension.rs index 133506c9..3d7f2cb4 100644 --- a/azalea-client/tests/despawn_entities_when_changing_dimension.rs +++ b/azalea-client/tests/despawn_entities_when_changing_dimension.rs @@ -1,20 +1,14 @@ use azalea_client::test_simulation::*; -use azalea_core::{ - delta::PositionDelta8, - position::{ChunkPos, Vec3}, - resource_location::ResourceLocation, -}; +use azalea_core::{position::ChunkPos, resource_location::ResourceLocation}; use azalea_entity::metadata::Cow; use azalea_protocol::packets::{ ConnectionProtocol, config::{ClientboundFinishConfiguration, ClientboundRegistryData}, - game::ClientboundAddEntity, }; -use azalea_registry::DimensionType; +use azalea_registry::{DimensionType, EntityKind}; use bevy_ecs::query::With; use bevy_log::tracing_subscriber; use simdnbt::owned::{NbtCompound, NbtTag}; -use uuid::Uuid; #[test] fn test_despawn_entities_when_changing_dimension() { @@ -59,17 +53,7 @@ fn test_despawn_entities_when_changing_dimension() { simulation.receive_packet(make_basic_empty_chunk(ChunkPos::new(0, 0), (384 + 64) / 16)); simulation.tick(); // spawn a cow - simulation.receive_packet(ClientboundAddEntity { - id: 123.into(), - uuid: Uuid::from_u128(1234), - entity_type: azalea_registry::EntityKind::Cow, - position: Vec3::new(0., 64., 0.), - x_rot: 0, - y_rot: 0, - y_head_rot: 0, - data: 0, - velocity: PositionDelta8::default(), - }); + simulation.receive_packet(make_basic_add_entity(EntityKind::Cow, 123, (0.5, 64., 0.5))); simulation.tick(); // make sure it's spawned let mut cow_query = simulation.app.world_mut().query_filtered::<(), With<Cow>>(); diff --git a/azalea-client/tests/move_despawned_entity.rs b/azalea-client/tests/move_despawned_entity.rs new file mode 100644 index 00000000..74f7e942 --- /dev/null +++ b/azalea-client/tests/move_despawned_entity.rs @@ -0,0 +1,51 @@ +use azalea_client::test_simulation::*; +use azalea_core::{position::ChunkPos, resource_location::ResourceLocation}; +use azalea_entity::metadata::Cow; +use azalea_protocol::packets::{ConnectionProtocol, game::ClientboundMoveEntityRot}; +use azalea_registry::{DimensionType, EntityKind}; +use azalea_world::MinecraftEntityId; +use bevy_ecs::query::With; +use bevy_log::tracing_subscriber; + +#[test] +fn test_move_despawned_entity() { + let _ = tracing_subscriber::fmt::try_init(); + + let mut simulation = Simulation::new(ConnectionProtocol::Game); + simulation.receive_packet(make_basic_login_packet( + DimensionType::new_raw(0), + ResourceLocation::new("azalea:overworld"), + )); + + simulation.receive_packet(make_basic_empty_chunk(ChunkPos::new(0, 0), (384 + 64) / 16)); + simulation.tick(); + // spawn a cow + simulation.receive_packet(make_basic_add_entity(EntityKind::Cow, 123, (0.5, 64., 0.5))); + simulation.tick(); + + // make sure it's spawned + let mut cow_query = simulation.app.world_mut().query_filtered::<(), With<Cow>>(); + let cow_iter = cow_query.iter(simulation.app.world()); + assert_eq!(cow_iter.count(), 1, "cow should be despawned"); + + // despawn the cow by receiving a login packet + simulation.receive_packet(make_basic_login_packet( + DimensionType::new_raw(0), + ResourceLocation::new("azalea:overworld"), + )); + simulation.tick(); + + // make sure it's despawned + let mut cow_query = simulation.app.world_mut().query_filtered::<(), With<Cow>>(); + let cow_iter = cow_query.iter(simulation.app.world()); + assert_eq!(cow_iter.count(), 0, "cow should be despawned"); + + // send a move_entity_rot + simulation.receive_packet(ClientboundMoveEntityRot { + entity_id: MinecraftEntityId(123), + y_rot: 0, + x_rot: 0, + on_ground: false, + }); + simulation.tick(); +} |
