diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2025-04-17 16:16:51 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-17 16:16:51 -0500 |
| commit | 3f60bdadac1a02e1109148bbbe5a8a3545f13849 (patch) | |
| tree | 6c0460be61e715c1b789f81b16ce4c0fb986c3b4 /azalea-client/src/plugins/packet/game | |
| parent | 1989f4ec979c138f8f466ccebadca335eb2917d6 (diff) | |
| download | azalea-drasl-3f60bdadac1a02e1109148bbbe5a8a3545f13849.tar.xz | |
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
Diffstat (limited to 'azalea-client/src/plugins/packet/game')
| -rw-r--r-- | azalea-client/src/plugins/packet/game/events.rs | 87 | ||||
| -rw-r--r-- | azalea-client/src/plugins/packet/game/mod.rs | 315 |
2 files changed, 161 insertions, 241 deletions
diff --git a/azalea-client/src/plugins/packet/game/events.rs b/azalea-client/src/plugins/packet/game/events.rs index ad81f9bd..68bfb4b3 100644 --- a/azalea-client/src/plugins/packet/game/events.rs +++ b/azalea-client/src/plugins/packet/game/events.rs @@ -1,33 +1,27 @@ -use std::{ - io::Cursor, - sync::{Arc, Weak}, -}; +use std::sync::{Arc, Weak}; use azalea_chat::FormattedText; use azalea_core::resource_location::ResourceLocation; -use azalea_protocol::{ - packets::{ - Packet, - game::{ClientboundGamePacket, ClientboundPlayerCombatKill, ServerboundGamePacket}, - }, - read::deserialize_packet, +use azalea_protocol::packets::{ + Packet, + game::{ClientboundGamePacket, ClientboundPlayerCombatKill, ServerboundGamePacket}, }; use azalea_world::Instance; use bevy_ecs::prelude::*; use parking_lot::RwLock; -use tracing::{debug, error}; +use tracing::error; use uuid::Uuid; -use crate::{PlayerInfo, client::InGameState, raw_connection::RawConnection}; +use crate::{PlayerInfo, client::InGameState, connection::RawConnection}; /// An event that's sent when we receive a packet. /// ``` -/// # use azalea_client::packet::game::ReceivePacketEvent; +/// # use azalea_client::packet::game::ReceiveGamePacketEvent; /// # use azalea_protocol::packets::game::ClientboundGamePacket; /// # use bevy_ecs::event::EventReader; /// -/// fn handle_packets(mut events: EventReader<ReceivePacketEvent>) { -/// for ReceivePacketEvent { +/// fn handle_packets(mut events: EventReader<ReceiveGamePacketEvent>) { +/// for ReceiveGamePacketEvent { /// entity, /// packet, /// } in events.read() { @@ -41,7 +35,7 @@ use crate::{PlayerInfo, client::InGameState, raw_connection::RawConnection}; /// } /// ``` #[derive(Event, Debug, Clone)] -pub struct ReceivePacketEvent { +pub struct ReceiveGamePacketEvent { /// The client entity that received the packet. pub entity: Entity, /// The packet that was actually received. @@ -67,7 +61,7 @@ pub fn handle_outgoing_packets_observer( ) { let event = trigger.event(); - if let Ok((raw_connection, in_game_state)) = query.get_mut(event.sent_by) { + if let Ok((mut raw_connection, in_game_state)) = query.get_mut(event.sent_by) { if in_game_state.is_none() { error!( "Tried to send a game packet {:?} while not in game state", @@ -76,8 +70,8 @@ pub fn handle_outgoing_packets_observer( return; } - // debug!("Sending packet: {:?}", event.packet); - if let Err(e) = raw_connection.write_packet(event.packet.clone()) { + // debug!("Sending game packet: {:?}", event.packet); + if let Err(e) = raw_connection.write(event.packet.clone()) { error!("Failed to send packet: {e}"); } } @@ -91,61 +85,6 @@ pub fn handle_outgoing_packets(mut commands: Commands, mut events: EventReader<S } } -pub fn emit_receive_packet_events( - query: Query<(Entity, &RawConnection), With<InGameState>>, - mut packet_events: ResMut<Events<ReceivePacketEvent>>, -) { - // we manually clear and send the events at the beginning of each update - // since otherwise it'd cause issues with events in process_packet_events - // running twice - packet_events.clear(); - for (player_entity, raw_connection) in &query { - let packets_lock = raw_connection.incoming_packet_queue(); - let mut packets = packets_lock.lock(); - if !packets.is_empty() { - let mut packets_read = 0; - for raw_packet in packets.iter() { - packets_read += 1; - let packet = - match deserialize_packet::<ClientboundGamePacket>(&mut Cursor::new(raw_packet)) - { - Ok(packet) => packet, - Err(err) => { - error!("failed to read packet: {err:?}"); - debug!("packet bytes: {raw_packet:?}"); - continue; - } - }; - - let should_interrupt = packet_interrupts(&packet); - - packet_events.send(ReceivePacketEvent { - entity: player_entity, - packet: Arc::new(packet), - }); - - if should_interrupt { - break; - } - } - packets.drain(0..packets_read); - } - } -} - -/// Whether the given packet should make us stop deserializing the received -/// packets until next update. -/// -/// This is used for packets that can switch the client state. -fn packet_interrupts(packet: &ClientboundGamePacket) -> bool { - matches!( - packet, - ClientboundGamePacket::StartConfiguration(_) - | ClientboundGamePacket::Disconnect(_) - | ClientboundGamePacket::Transfer(_) - ) -} - /// A player joined the game (or more specifically, was added to the tab /// list of a local player). #[derive(Event, Debug, Clone)] diff --git a/azalea-client/src/plugins/packet/game/mod.rs b/azalea-client/src/plugins/packet/game/mod.rs index 8d896e65..60531d3b 100644 --- a/azalea-client/src/plugins/packet/game/mod.rs +++ b/azalea-client/src/plugins/packet/game/mod.rs @@ -32,171 +32,150 @@ use crate::{ }, movement::{KnockbackEvent, KnockbackType}, packet::as_system, - raw_connection::RawConnection, }; -pub fn process_packet_events(ecs: &mut World) { - let mut events_owned = Vec::<(Entity, Arc<ClientboundGamePacket>)>::new(); - - { - let mut system_state = SystemState::<EventReader<ReceivePacketEvent>>::new(ecs); - let mut events = system_state.get_mut(ecs); - for ReceivePacketEvent { - entity: player_entity, - packet, - } in events.read() - { - // we do this so `ecs` isn't borrowed for the whole loop - events_owned.push((*player_entity, packet.clone())); - } - } - - for (player_entity, packet) in events_owned { - let mut handler = GamePacketHandler { - player: player_entity, - ecs, - }; - - // the order of these doesn't matter, that's decided by the protocol library - declare_packet_handlers!( - ClientboundGamePacket, - packet.as_ref(), - handler, - [ - login, - set_chunk_cache_radius, - chunk_batch_start, - chunk_batch_finished, - custom_payload, - change_difficulty, - commands, - player_abilities, - set_cursor_item, - update_tags, - disconnect, - update_recipes, - entity_event, - player_position, - player_info_update, - player_info_remove, - set_chunk_cache_center, - chunks_biomes, - light_update, - level_chunk_with_light, - add_entity, - set_entity_data, - update_attributes, - set_entity_motion, - set_entity_link, - initialize_border, - set_time, - set_default_spawn_position, - set_health, - set_experience, - teleport_entity, - update_advancements, - rotate_head, - move_entity_pos, - move_entity_pos_rot, - move_entity_rot, - keep_alive, - remove_entities, - player_chat, - system_chat, - disguised_chat, - sound, - level_event, - block_update, - animate, - section_blocks_update, - game_event, - level_particles, - server_data, - set_equipment, - update_mob_effect, - award_stats, - block_changed_ack, - block_destruction, - block_entity_data, - block_event, - boss_event, - command_suggestions, - container_set_content, - container_set_data, - container_set_slot, - container_close, - cooldown, - custom_chat_completions, - delete_chat, - explode, - forget_level_chunk, - horse_screen_open, - map_item_data, - merchant_offers, - move_vehicle, - open_book, - open_screen, - open_sign_editor, - ping, - place_ghost_recipe, - player_combat_end, - player_combat_enter, - player_combat_kill, - player_look_at, - remove_mob_effect, - resource_pack_push, - resource_pack_pop, - respawn, - start_configuration, - entity_position_sync, - select_advancements_tab, - set_action_bar_text, - set_border_center, - set_border_lerp_size, - set_border_size, - set_border_warning_delay, - set_border_warning_distance, - set_camera, - set_display_objective, - set_objective, - set_passengers, - set_player_team, - set_score, - set_simulation_distance, - set_subtitle_text, - set_title_text, - set_titles_animation, - clear_titles, - sound_entity, - stop_sound, - tab_list, - tag_query, - take_item_entity, - bundle_delimiter, - damage_event, - hurt_animation, - ticking_state, - ticking_step, - reset_score, - cookie_request, - debug_sample, - pong_response, - store_cookie, - transfer, - move_minecart_along_track, - set_held_slot, - set_player_inventory, - projectile_power, - custom_report_details, - server_links, - player_rotation, - recipe_book_add, - recipe_book_remove, - recipe_book_settings, - test_instance_block_status, - ] - ); - } +pub fn process_packet(ecs: &mut World, player: Entity, packet: &ClientboundGamePacket) { + let mut handler = GamePacketHandler { player, ecs }; + + // the order of these doesn't matter, that's decided by the protocol library + declare_packet_handlers!( + ClientboundGamePacket, + packet, + handler, + [ + login, + set_chunk_cache_radius, + chunk_batch_start, + chunk_batch_finished, + custom_payload, + change_difficulty, + commands, + player_abilities, + set_cursor_item, + update_tags, + disconnect, + update_recipes, + entity_event, + player_position, + player_info_update, + player_info_remove, + set_chunk_cache_center, + chunks_biomes, + light_update, + level_chunk_with_light, + add_entity, + set_entity_data, + update_attributes, + set_entity_motion, + set_entity_link, + initialize_border, + set_time, + set_default_spawn_position, + set_health, + set_experience, + teleport_entity, + update_advancements, + rotate_head, + move_entity_pos, + move_entity_pos_rot, + move_entity_rot, + keep_alive, + remove_entities, + player_chat, + system_chat, + disguised_chat, + sound, + level_event, + block_update, + animate, + section_blocks_update, + game_event, + level_particles, + server_data, + set_equipment, + update_mob_effect, + award_stats, + block_changed_ack, + block_destruction, + block_entity_data, + block_event, + boss_event, + command_suggestions, + container_set_content, + container_set_data, + container_set_slot, + container_close, + cooldown, + custom_chat_completions, + delete_chat, + explode, + forget_level_chunk, + horse_screen_open, + map_item_data, + merchant_offers, + move_vehicle, + open_book, + open_screen, + open_sign_editor, + ping, + place_ghost_recipe, + player_combat_end, + player_combat_enter, + player_combat_kill, + player_look_at, + remove_mob_effect, + resource_pack_push, + resource_pack_pop, + respawn, + start_configuration, + entity_position_sync, + select_advancements_tab, + set_action_bar_text, + set_border_center, + set_border_lerp_size, + set_border_size, + set_border_warning_delay, + set_border_warning_distance, + set_camera, + set_display_objective, + set_objective, + set_passengers, + set_player_team, + set_score, + set_simulation_distance, + set_subtitle_text, + set_title_text, + set_titles_animation, + clear_titles, + sound_entity, + stop_sound, + tab_list, + tag_query, + take_item_entity, + bundle_delimiter, + damage_event, + hurt_animation, + ticking_state, + ticking_step, + reset_score, + cookie_request, + debug_sample, + pong_response, + store_cookie, + transfer, + move_minecart_along_track, + set_held_slot, + set_player_inventory, + projectile_power, + custom_report_details, + server_links, + player_rotation, + recipe_book_add, + recipe_book_remove, + recipe_book_settings, + test_instance_block_status, + ] + ); } pub struct GamePacketHandler<'a> { @@ -342,7 +321,7 @@ impl GamePacketHandler<'_> { client_information ); commands.trigger(SendPacketEvent::new(self.player, - azalea_protocol::packets::game::s_client_information::ServerboundClientInformation { information: client_information.clone() }, + azalea_protocol::packets::game::s_client_information::ServerboundClientInformation { client_information: client_information.clone() }, )); }, ); @@ -1506,9 +1485,11 @@ impl GamePacketHandler<'_> { pub fn start_configuration(&mut self, _p: &ClientboundStartConfiguration) { debug!("Got start configuration packet"); - as_system::<(Query<&RawConnection>, Commands)>(self.ecs, |(query, mut commands)| { - let raw_conn = query.get(self.player).unwrap(); - let _ = raw_conn.write_packet(ServerboundConfigurationAcknowledged); + as_system::<Commands>(self.ecs, |mut commands| { + commands.trigger(SendPacketEvent::new( + self.player, + ServerboundConfigurationAcknowledged, + )); commands .entity(self.player) |
