aboutsummaryrefslogtreecommitdiff
path: root/azalea-client/src/disconnect.rs
blob: 3b8d133ef05003ce2af6a87e8e7da7b408d6d63e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! Disconnect a client from the server.

use bevy_app::{App, CoreSet, Plugin};
use bevy_ecs::{
    component::Component,
    entity::Entity,
    event::{EventReader, EventWriter},
    query::Changed,
    schedule::IntoSystemConfigs,
    system::{Commands, Query},
};
use derive_more::Deref;

use crate::{client::JoinedClientBundle, LocalPlayer};

pub struct DisconnectPlugin;
impl Plugin for DisconnectPlugin {
    fn build(&self, app: &mut App) {
        app.add_event::<DisconnectEvent>().add_systems(
            (
                update_read_packets_task_running_component,
                disconnect_on_read_packets_ended,
                remove_components_from_disconnected_players,
            )
                .in_base_set(CoreSet::PostUpdate)
                .chain(),
        );
    }
}

/// An event sent when a client is getting disconnected.
pub struct DisconnectEvent {
    pub entity: Entity,
}

/// System that removes the [`JoinedClientBundle`] from the entity when it
/// receives a [`DisconnectEvent`].
pub fn remove_components_from_disconnected_players(
    mut commands: Commands,
    mut events: EventReader<DisconnectEvent>,
) {
    for DisconnectEvent { entity } in events.iter() {
        commands.entity(*entity).remove::<JoinedClientBundle>();
    }
}

#[derive(Component, Clone, Copy, Debug, Deref)]
pub struct ReadPacketsTaskRunning(bool);

fn update_read_packets_task_running_component(
    mut commands: Commands,
    local_player: Query<(Entity, &LocalPlayer)>,
) {
    for (entity, local_player) in &local_player {
        let running = !local_player.read_packets_task.is_finished();
        commands
            .entity(entity)
            .insert(ReadPacketsTaskRunning(running));
    }
}
fn disconnect_on_read_packets_ended(
    local_player: Query<(Entity, &ReadPacketsTaskRunning), Changed<ReadPacketsTaskRunning>>,
    mut disconnect_events: EventWriter<DisconnectEvent>,
) {
    for (entity, &read_packets_task_running) in &local_player {
        if !*read_packets_task_running {
            disconnect_events.send(DisconnectEvent { entity });
        }
    }
}