From 3f60bdadac1a02e1109148bbbe5a8a3545f13849 Mon Sep 17 00:00:00 2001 From: mat <27899617+mat-1@users.noreply.github.com> Date: Thu, 17 Apr 2025 16:16:51 -0500 Subject: Move login state to the ECS (#213) * use packet handlers code for login custom_query * initial broken implementation for ecs-only login * fixes * run Update schedule 60 times per second and delete code related to run_schedule_sender * fix tests * fix online-mode * reply to query packets in a separate system and make it easier for plugins to disable individual replies * remove unused imports --- azalea-client/src/test_simulation.rs | 95 ++++++++++-------------------------- 1 file changed, 27 insertions(+), 68 deletions(-) (limited to 'azalea-client/src/test_simulation.rs') diff --git a/azalea-client/src/test_simulation.rs b/azalea-client/src/test_simulation.rs index a09e5dae..4dec01b4 100644 --- a/azalea-client/src/test_simulation.rs +++ b/azalea-client/src/test_simulation.rs @@ -1,4 +1,4 @@ -use std::{fmt::Debug, sync::Arc, time::Duration}; +use std::{fmt::Debug, sync::Arc}; use azalea_auth::game_profile::GameProfile; use azalea_buf::AzaleaWrite; @@ -21,16 +21,14 @@ 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 parking_lot::RwLock; use simdnbt::owned::{NbtCompound, NbtTag}; -use tokio::task::JoinHandle; -use tokio::{sync::mpsc, time::sleep}; use uuid::Uuid; +use crate::connection::RawConnection; use crate::disconnect::DisconnectEvent; use crate::{ ClientInformation, GameProfileComponent, InConfigState, InstanceHolder, LocalPlayerBundle, - raw_connection::{RawConnection, RawConnectionReader, RawConnectionWriter}, }; /// A way to simulate a client in a server, used for some internal tests. @@ -40,16 +38,13 @@ pub struct Simulation { // the runtime needs to be kept around for the tasks to be considered alive pub rt: tokio::runtime::Runtime, - - pub incoming_packet_queue: Arc>>>, - pub clear_outgoing_packets_receiver_task: JoinHandle, } impl Simulation { pub fn new(initial_connection_protocol: ConnectionProtocol) -> Self { 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) = + let (player, rt) = create_local_player_bundle(entity.id(), ConnectionProtocol::Configuration); entity.insert(player); @@ -58,16 +53,16 @@ impl Simulation { tick_app(&mut app); // start in the config state - app.world_mut().entity_mut(entity).insert(InConfigState); + app.world_mut().entity_mut(entity).insert(( + InConfigState, + GameProfileComponent(GameProfile::new( + Uuid::from_u128(1234), + "azalea".to_string(), + )), + )); tick_app(&mut app); - let mut simulation = Self { - app, - entity, - rt, - incoming_packet_queue, - clear_outgoing_packets_receiver_task, - }; + let mut simulation = Self { app, entity, rt }; #[allow(clippy::single_match)] match initial_connection_protocol { @@ -95,9 +90,11 @@ impl Simulation { simulation } - pub fn receive_packet(&self, packet: impl Packet

) { + pub fn receive_packet(&mut self, packet: impl Packet

) { let buf = azalea_protocol::write::serialize_packet(&packet.into_variant()).unwrap(); - self.incoming_packet_queue.lock().push(buf); + self.with_component_mut::(|raw_conn| { + raw_conn.injected_clientbound_packets.push(buf); + }); } pub fn tick(&mut self) { @@ -112,6 +109,14 @@ impl Simulation { pub fn has_component(&self) -> bool { self.app.world().get::(self.entity).is_some() } + pub fn with_component_mut(&mut self, f: impl FnOnce(&mut T)) { + f(&mut self + .app + .world_mut() + .entity_mut(self.entity) + .get_mut::() + .unwrap()); + } pub fn resource(&self) -> T { self.app.world().get_resource::().unwrap().clone() } @@ -143,70 +148,24 @@ impl Simulation { fn create_local_player_bundle( entity: Entity, connection_protocol: ConnectionProtocol, -) -> ( - LocalPlayerBundle, - JoinHandle, - Arc>>>, - tokio::runtime::Runtime, -) { +) -> (LocalPlayerBundle, tokio::runtime::Runtime) { // unused since we'll trigger ticks ourselves - let (run_schedule_sender, _run_schedule_receiver) = mpsc::channel(1); - - let (outgoing_packets_sender, mut outgoing_packets_receiver) = mpsc::unbounded_channel(); - let incoming_packet_queue = Arc::new(Mutex::new(Vec::new())); - let reader = RawConnectionReader { - incoming_packet_queue: incoming_packet_queue.clone(), - run_schedule_sender, - }; - let writer = RawConnectionWriter { - outgoing_packets_sender, - }; let rt = tokio::runtime::Runtime::new().unwrap(); - // the tasks can't die since that would make us send a DisconnectEvent - let read_packets_task = rt.spawn(async { - loop { - sleep(Duration::from_secs(60)).await; - } - }); - let write_packets_task = rt.spawn(async { - loop { - sleep(Duration::from_secs(60)).await; - } - }); - - let clear_outgoing_packets_receiver_task = rt.spawn(async move { - loop { - let _ = outgoing_packets_receiver.recv().await; - } - }); - - let raw_connection = RawConnection { - reader, - writer, - read_packets_task, - write_packets_task, - connection_protocol, - }; + let raw_connection = RawConnection::new_networkless(connection_protocol); let instance = Instance::default(); let instance_holder = InstanceHolder::new(entity, Arc::new(RwLock::new(instance))); let local_player_bundle = LocalPlayerBundle { raw_connection, - game_profile: GameProfileComponent(GameProfile::new(Uuid::nil(), "azalea".to_owned())), client_information: ClientInformation::default(), instance_holder, metadata: PlayerMetadataBundle::default(), }; - ( - local_player_bundle, - clear_outgoing_packets_receiver_task, - incoming_packet_queue, - rt, - ) + (local_player_bundle, rt) } fn create_simulation_app() -> App { -- cgit v1.2.3