aboutsummaryrefslogtreecommitdiff
path: root/azalea-client/src/plugins/packet/game
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2025-04-17 16:16:51 -0500
committerGitHub <noreply@github.com>2025-04-17 16:16:51 -0500
commit3f60bdadac1a02e1109148bbbe5a8a3545f13849 (patch)
tree6c0460be61e715c1b789f81b16ce4c0fb986c3b4 /azalea-client/src/plugins/packet/game
parent1989f4ec979c138f8f466ccebadca335eb2917d6 (diff)
downloadazalea-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.rs87
-rw-r--r--azalea-client/src/plugins/packet/game/mod.rs315
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)