1use std::sync::Arc;
5
6use azalea_chat::FormattedText;
7use azalea_core::tick::GameTick;
8use azalea_protocol::packets::game::{
9 c_player_combat_kill::ClientboundPlayerCombatKill, ClientboundGamePacket,
10};
11use azalea_world::{InstanceName, MinecraftEntityId};
12use bevy_app::{App, Plugin, PreUpdate, Update};
13use bevy_ecs::{
14 component::Component,
15 event::EventReader,
16 query::{Added, With},
17 schedule::IntoSystemConfigs,
18 system::Query,
19};
20use derive_more::{Deref, DerefMut};
21use tokio::sync::mpsc;
22
23use crate::{
24 chat::{ChatPacket, ChatReceivedEvent},
25 disconnect::DisconnectEvent,
26 packet_handling::game::{
27 AddPlayerEvent, DeathEvent, KeepAliveEvent, PacketEvent, RemovePlayerEvent,
28 UpdatePlayerEvent,
29 },
30 PlayerInfo,
31};
32
33#[derive(Debug, Clone)]
56pub enum Event {
57 Init,
65 Login,
67 Chat(ChatPacket),
69 Tick,
71 Packet(Arc<ClientboundGamePacket>),
89 AddPlayer(PlayerInfo),
92 RemovePlayer(PlayerInfo),
95 UpdatePlayer(PlayerInfo),
98 Death(Option<Arc<ClientboundPlayerCombatKill>>),
100 KeepAlive(u64),
102 Disconnect(Option<FormattedText>),
104}
105
106#[derive(Component, Deref, DerefMut)]
112pub struct LocalPlayerEvents(pub mpsc::UnboundedSender<Event>);
113
114pub struct EventPlugin;
115impl Plugin for EventPlugin {
116 fn build(&self, app: &mut App) {
117 app.add_systems(
118 Update,
119 (
120 chat_listener,
121 login_listener,
122 packet_listener,
123 add_player_listener,
124 update_player_listener,
125 remove_player_listener,
126 keepalive_listener,
127 death_listener,
128 disconnect_listener,
129 ),
130 )
131 .add_systems(
132 PreUpdate,
133 init_listener.before(crate::packet_handling::game::process_packet_events),
134 )
135 .add_systems(GameTick, tick_listener);
136 }
137}
138
139pub fn init_listener(query: Query<&LocalPlayerEvents, Added<LocalPlayerEvents>>) {
141 for local_player_events in &query {
142 let _ = local_player_events.send(Event::Init);
143 }
144}
145
146pub fn login_listener(query: Query<&LocalPlayerEvents, Added<MinecraftEntityId>>) {
148 for local_player_events in &query {
149 let _ = local_player_events.send(Event::Login);
150 }
151}
152
153pub fn chat_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<ChatReceivedEvent>) {
154 for event in events.read() {
155 let local_player_events = query
156 .get(event.entity)
157 .expect("Non-local entities shouldn't be able to receive chat events");
158 let _ = local_player_events.send(Event::Chat(event.packet.clone()));
159 }
160}
161
162pub fn tick_listener(query: Query<&LocalPlayerEvents, With<InstanceName>>) {
164 for local_player_events in &query {
165 let _ = local_player_events.send(Event::Tick);
166 }
167}
168
169pub fn packet_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<PacketEvent>) {
170 for event in events.read() {
171 let local_player_events = query
172 .get(event.entity)
173 .expect("Non-local entities shouldn't be able to receive packet events");
174 let _ = local_player_events.send(Event::Packet(event.packet.clone()));
175 }
176}
177
178pub fn add_player_listener(
179 query: Query<&LocalPlayerEvents>,
180 mut events: EventReader<AddPlayerEvent>,
181) {
182 for event in events.read() {
183 let local_player_events = query
184 .get(event.entity)
185 .expect("Non-local entities shouldn't be able to receive add player events");
186 let _ = local_player_events.send(Event::AddPlayer(event.info.clone()));
187 }
188}
189
190pub fn update_player_listener(
191 query: Query<&LocalPlayerEvents>,
192 mut events: EventReader<UpdatePlayerEvent>,
193) {
194 for event in events.read() {
195 let local_player_events = query
196 .get(event.entity)
197 .expect("Non-local entities shouldn't be able to receive update player events");
198 let _ = local_player_events.send(Event::UpdatePlayer(event.info.clone()));
199 }
200}
201
202pub fn remove_player_listener(
203 query: Query<&LocalPlayerEvents>,
204 mut events: EventReader<RemovePlayerEvent>,
205) {
206 for event in events.read() {
207 let local_player_events = query
208 .get(event.entity)
209 .expect("Non-local entities shouldn't be able to receive remove player events");
210 let _ = local_player_events.send(Event::RemovePlayer(event.info.clone()));
211 }
212}
213
214pub fn death_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<DeathEvent>) {
215 for event in events.read() {
216 if let Ok(local_player_events) = query.get(event.entity) {
217 let _ = local_player_events.send(Event::Death(event.packet.clone().map(|p| p.into())));
218 }
219 }
220}
221
222pub fn keepalive_listener(
223 query: Query<&LocalPlayerEvents>,
224 mut events: EventReader<KeepAliveEvent>,
225) {
226 for event in events.read() {
227 let local_player_events = query
228 .get(event.entity)
229 .expect("Non-local entities shouldn't be able to receive keepalive events");
230 let _ = local_player_events.send(Event::KeepAlive(event.id));
231 }
232}
233
234pub fn disconnect_listener(
235 query: Query<&LocalPlayerEvents>,
236 mut events: EventReader<DisconnectEvent>,
237) {
238 for event in events.read() {
239 if let Ok(local_player_events) = query.get(event.entity) {
240 let _ = local_player_events.send(Event::Disconnect(event.reason.clone()));
241 }
242 }
243}