aboutsummaryrefslogtreecommitdiff
path: root/azalea-client/src/packet_handling.rs
diff options
context:
space:
mode:
Diffstat (limited to 'azalea-client/src/packet_handling.rs')
-rw-r--r--azalea-client/src/packet_handling.rs56
1 files changed, 43 insertions, 13 deletions
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::<RemovePlayerEvent>()
.add_event::<UpdatePlayerEvent>()
.add_event::<ChatReceivedEvent>()
- .add_event::<DeathEvent>();
+ .add_event::<DeathEvent>()
+ .add_event::<KeepAliveEvent>();
}
}
/// 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<ClientboundPlayerCombatKillPacket>,
}
+/// 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<Query<&mut LocalPlayer>> =
- 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<KeepAliveEvent>,
+ )> = 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<ClientboundGamePacket>) {
- 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;
+ }
+ }
}
}