From c23fae6e5dc2832f3649838f514eafb9dfa3e598 Mon Sep 17 00:00:00 2001 From: EightFactorial Date: Wed, 8 Feb 2023 10:05:14 -0800 Subject: [PATCH] Add KeepAliveEvent and Fix Error Messages (#65) * Add KeepAliveEvent * Fix error messages * Panic instead of log error * Do not panic on closed connections * change some wording and fixes * fmt --------- Co-authored-by: Ubuntu --- azalea-client/src/client.rs | 5 ++- azalea-client/src/events.rs | 22 +++++++++-- azalea-client/src/packet_handling.rs | 56 +++++++++++++++++++++------- azalea-world/src/entity/info.rs | 1 - 4 files changed, 65 insertions(+), 19 deletions(-) diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 87079af4..8b6932e5 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -42,7 +42,10 @@ use azalea_protocol::{ }, resolver, ServerAddress, }; -use azalea_world::{entity::{WorldName, EntityPlugin, Local}, PartialWorld, World, WorldContainer}; +use azalea_world::{ + entity::{EntityPlugin, Local, WorldName}, + PartialWorld, World, WorldContainer, +}; use log::{debug, error}; use parking_lot::{Mutex, RwLock}; use std::{collections::HashMap, fmt::Debug, io, net::SocketAddr, sync::Arc}; diff --git a/azalea-client/src/events.rs b/azalea-client/src/events.rs index f8b9f434..3594911f 100644 --- a/azalea-client/src/events.rs +++ b/azalea-client/src/events.rs @@ -20,8 +20,8 @@ use tokio::sync::mpsc; use crate::{ packet_handling::{ - AddPlayerEvent, ChatReceivedEvent, DeathEvent, PacketReceiver, RemovePlayerEvent, - UpdatePlayerEvent, + AddPlayerEvent, ChatReceivedEvent, DeathEvent, KeepAliveEvent, PacketReceiver, + RemovePlayerEvent, UpdatePlayerEvent, }, ChatPacket, PlayerInfo, }; @@ -73,6 +73,8 @@ pub enum Event { UpdatePlayer(PlayerInfo), /// The client player died in-game. Death(Option>), + /// A `KeepAlive` packet was sent by the server. + KeepAlive(u64), } /// A component that contains an event sender for events that are only @@ -94,6 +96,7 @@ impl Plugin for EventPlugin { .add_system(update_player_listener) .add_system(remove_player_listener) .add_system(death_listener) + .add_system(keepalive_listener) .add_tick_system(tick_listener); } } @@ -157,7 +160,7 @@ fn update_player_listener( for event in events.iter() { let local_player_events = query .get(event.entity) - .expect("Non-localplayer entities shouldn't be able to receive add player events"); + .expect("Non-localplayer entities shouldn't be able to receive update player events"); local_player_events .send(Event::UpdatePlayer(event.info.clone())) .unwrap(); @@ -171,7 +174,7 @@ fn remove_player_listener( for event in events.iter() { let local_player_events = query .get(event.entity) - .expect("Non-localplayer entities shouldn't be able to receive add player events"); + .expect("Non-localplayer entities shouldn't be able to receive remove player events"); local_player_events .send(Event::RemovePlayer(event.info.clone())) .unwrap(); @@ -187,3 +190,14 @@ fn death_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader, mut events: EventReader) { + for event in events.iter() { + let local_player_events = query + .get(event.entity) + .expect("Non-localplayer entities shouldn't be able to receive keepalive events"); + local_player_events + .send(Event::KeepAlive(event.id)) + .unwrap(); + } +} diff --git a/azalea-client/src/packet_handling.rs b/azalea-client/src/packet_handling.rs index 0e03b37c..7f49a30d 100644 --- a/azalea-client/src/packet_handling.rs +++ b/azalea-client/src/packet_handling.rs @@ -21,6 +21,7 @@ use azalea_protocol::{ serverbound_move_player_pos_rot_packet::ServerboundMovePlayerPosRotPacket, ClientboundGamePacket, ServerboundGamePacket, }, + read::ReadPacketError, }; use azalea_world::{ entity::{ @@ -51,13 +52,14 @@ impl Plugin for PacketHandlerPlugin { .add_event::() .add_event::() .add_event::() - .add_event::(); + .add_event::() + .add_event::(); } } /// A player joined the game (or more specifically, was added to the tab /// list of a local player). -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AddPlayerEvent { /// The local player entity that received this event. pub entity: Entity, @@ -65,7 +67,7 @@ pub struct AddPlayerEvent { } /// A player left the game (or maybe is still in the game and was just /// removed from the tab list of a local player). -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct RemovePlayerEvent { /// The local player entity that received this event. pub entity: Entity, @@ -73,7 +75,7 @@ pub struct RemovePlayerEvent { } /// A player was updated in the tab list of a local player (gamemode, display /// name, or latency changed). -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct UpdatePlayerEvent { /// The local player entity that received this event. pub entity: Entity, @@ -81,7 +83,7 @@ pub struct UpdatePlayerEvent { } /// A client received a chat message packet. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ChatReceivedEvent { pub entity: Entity, pub packet: ChatPacket, @@ -90,11 +92,22 @@ pub struct ChatReceivedEvent { /// Event for when an entity dies. dies. If it's a local player and there's a /// reason in the death screen, the [`ClientboundPlayerCombatKillPacket`] will /// be included. +#[derive(Debug, Clone)] pub struct DeathEvent { pub entity: Entity, pub packet: Option, } +/// A KeepAlive packet is sent from the server to verify that the client is +/// still connected. +#[derive(Debug, Clone)] +pub struct KeepAliveEvent { + pub entity: Entity, + /// The ID of the keepalive. This is an arbitrary number, but vanilla + /// servers use the time to generate this. + pub id: u64, +} + /// Something that receives packets from the server. #[derive(Component, Clone)] pub struct PacketReceiver { @@ -743,11 +756,18 @@ fn handle_packets(ecs: &mut Ecs) { ClientboundGamePacket::KeepAlive(p) => { debug!("Got keep alive packet {p:?} for {player_entity:?}"); - let mut system_state: SystemState> = - SystemState::new(ecs); - let mut query = system_state.get_mut(ecs); - let mut local_player = query.get_mut(player_entity).unwrap(); + let mut system_state: SystemState<( + Query<&mut LocalPlayer>, + EventWriter, + )> = SystemState::new(ecs); + let (mut query, mut keepalive_events) = system_state.get_mut(ecs); + keepalive_events.send(KeepAliveEvent { + entity: player_entity, + id: p.id, + }); + + let mut local_player = query.get_mut(player_entity).unwrap(); local_player.write_packet(ServerboundKeepAlivePacket { id: p.id }.get()); debug!("Sent keep alive packet {p:?} for {player_entity:?}"); } @@ -925,10 +945,20 @@ impl PacketReceiver { /// Loop that reads from the connection and adds the packets to the queue + /// runs the schedule. pub async fn read_task(self, mut read_conn: ReadConnection) { - while let Ok(packet) = read_conn.read().await { - self.packets.lock().push(packet); - // tell the client to run all the systems - self.run_schedule_sender.send(()).await.unwrap(); + loop { + match read_conn.read().await { + Ok(packet) => { + self.packets.lock().push(packet); + // tell the client to run all the systems + self.run_schedule_sender.send(()).await.unwrap(); + } + Err(error) => { + if !matches!(*error, ReadPacketError::ConnectionClosed) { + error!("Error reading packet from Client: {error:?}"); + } + return; + } + } } } diff --git a/azalea-world/src/entity/info.rs b/azalea-world/src/entity/info.rs index bf7e0051..48636c5b 100644 --- a/azalea-world/src/entity/info.rs +++ b/azalea-world/src/entity/info.rs @@ -268,7 +268,6 @@ pub fn add_updates_received( } } - /// The [`UpdatesReceived`] component should never be on [`Local`] entities. /// This warns if an entity has both components. fn debug_detect_updates_received_on_local_entities(