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,
62 Login,
64 Chat(ChatPacket),
66 Tick,
68 Packet(Arc<ClientboundGamePacket>),
86 AddPlayer(PlayerInfo),
89 RemovePlayer(PlayerInfo),
92 UpdatePlayer(PlayerInfo),
95 Death(Option<Arc<ClientboundPlayerCombatKill>>),
97 KeepAlive(u64),
99 Disconnect(Option<FormattedText>),
101}
102
103#[derive(Component, Deref, DerefMut)]
109pub struct LocalPlayerEvents(pub mpsc::UnboundedSender<Event>);
110
111pub struct EventPlugin;
112impl Plugin for EventPlugin {
113 fn build(&self, app: &mut App) {
114 app.add_systems(
115 Update,
116 (
117 chat_listener,
118 login_listener,
119 packet_listener,
120 add_player_listener,
121 update_player_listener,
122 remove_player_listener,
123 keepalive_listener,
124 death_listener,
125 disconnect_listener,
126 ),
127 )
128 .add_systems(
129 PreUpdate,
130 init_listener.before(crate::packet_handling::game::process_packet_events),
131 )
132 .add_systems(GameTick, tick_listener);
133 }
134}
135
136pub fn init_listener(query: Query<&LocalPlayerEvents, Added<LocalPlayerEvents>>) {
138 for local_player_events in &query {
139 let _ = local_player_events.send(Event::Init);
140 }
141}
142
143pub fn login_listener(query: Query<&LocalPlayerEvents, Added<MinecraftEntityId>>) {
145 for local_player_events in &query {
146 let _ = local_player_events.send(Event::Login);
147 }
148}
149
150pub fn chat_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<ChatReceivedEvent>) {
151 for event in events.read() {
152 let local_player_events = query
153 .get(event.entity)
154 .expect("Non-local entities shouldn't be able to receive chat events");
155 let _ = local_player_events.send(Event::Chat(event.packet.clone()));
156 }
157}
158
159pub fn tick_listener(query: Query<&LocalPlayerEvents, With<InstanceName>>) {
161 for local_player_events in &query {
162 let _ = local_player_events.send(Event::Tick);
163 }
164}
165
166pub fn packet_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<PacketEvent>) {
167 for event in events.read() {
168 let local_player_events = query
169 .get(event.entity)
170 .expect("Non-local entities shouldn't be able to receive packet events");
171 let _ = local_player_events.send(Event::Packet(event.packet.clone()));
172 }
173}
174
175pub fn add_player_listener(
176 query: Query<&LocalPlayerEvents>,
177 mut events: EventReader<AddPlayerEvent>,
178) {
179 for event in events.read() {
180 let local_player_events = query
181 .get(event.entity)
182 .expect("Non-local entities shouldn't be able to receive add player events");
183 let _ = local_player_events.send(Event::AddPlayer(event.info.clone()));
184 }
185}
186
187pub fn update_player_listener(
188 query: Query<&LocalPlayerEvents>,
189 mut events: EventReader<UpdatePlayerEvent>,
190) {
191 for event in events.read() {
192 let local_player_events = query
193 .get(event.entity)
194 .expect("Non-local entities shouldn't be able to receive update player events");
195 let _ = local_player_events.send(Event::UpdatePlayer(event.info.clone()));
196 }
197}
198
199pub fn remove_player_listener(
200 query: Query<&LocalPlayerEvents>,
201 mut events: EventReader<RemovePlayerEvent>,
202) {
203 for event in events.read() {
204 let local_player_events = query
205 .get(event.entity)
206 .expect("Non-local entities shouldn't be able to receive remove player events");
207 let _ = local_player_events.send(Event::RemovePlayer(event.info.clone()));
208 }
209}
210
211pub fn death_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<DeathEvent>) {
212 for event in events.read() {
213 if let Ok(local_player_events) = query.get(event.entity) {
214 let _ = local_player_events.send(Event::Death(event.packet.clone().map(|p| p.into())));
215 }
216 }
217}
218
219pub fn keepalive_listener(
220 query: Query<&LocalPlayerEvents>,
221 mut events: EventReader<KeepAliveEvent>,
222) {
223 for event in events.read() {
224 let local_player_events = query
225 .get(event.entity)
226 .expect("Non-local entities shouldn't be able to receive keepalive events");
227 let _ = local_player_events.send(Event::KeepAlive(event.id));
228 }
229}
230
231pub fn disconnect_listener(
232 query: Query<&LocalPlayerEvents>,
233 mut events: EventReader<DisconnectEvent>,
234) {
235 for event in events.read() {
236 if let Ok(local_player_events) = query.get(event.entity) {
237 let _ = local_player_events.send(Event::Disconnect(event.reason.clone()));
238 }
239 }
240}