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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
|
mod events;
use std::io::Cursor;
use azalea_entity::LocalEntity;
use azalea_protocol::{
packets::{ConnectionProtocol, config::*},
read::{ReadPacketError, deserialize_packet},
};
use bevy_ecs::prelude::*;
pub use events::*;
use tracing::{debug, warn};
use super::{as_system, declare_packet_handlers};
use crate::{
client::InConfigState,
connection::RawConnection,
cookies::{RequestCookieEvent, StoreCookieEvent},
disconnect::DisconnectEvent,
local_player::WorldHolder,
packet::game::{KeepAliveEvent, ResourcePackEvent},
};
pub fn process_raw_packet(
ecs: &mut World,
player: Entity,
raw_packet: &[u8],
) -> Result<(), Box<ReadPacketError>> {
let packet = deserialize_packet(&mut Cursor::new(raw_packet))?;
process_packet(ecs, player, &packet);
Ok(())
}
pub fn process_packet(ecs: &mut World, player: Entity, packet: &ClientboundConfigPacket) {
let mut handler = ConfigPacketHandler { player, ecs };
declare_packet_handlers!(
ClientboundConfigPacket,
packet,
handler,
[
cookie_request,
custom_payload,
disconnect,
finish_configuration,
keep_alive,
ping,
reset_chat,
registry_data,
resource_pack_pop,
resource_pack_push,
store_cookie,
transfer,
update_enabled_features,
update_tags,
select_known_packs,
custom_report_details,
server_links,
clear_dialog,
show_dialog,
code_of_conduct,
]
);
}
pub struct ConfigPacketHandler<'a> {
pub ecs: &'a mut World,
pub player: Entity,
}
impl ConfigPacketHandler<'_> {
pub fn registry_data(&mut self, p: &ClientboundRegistryData) {
as_system::<Query<&WorldHolder>>(self.ecs, |mut query| {
let world_holder = query.get_mut(self.player).unwrap();
let mut world = world_holder.shared.write();
// add the new registry data
world
.registries
.append(p.registry_id.clone(), p.entries.clone());
});
}
pub fn custom_payload(&mut self, p: &ClientboundCustomPayload) {
debug!("Got custom payload packet {p:?}");
}
pub fn disconnect(&mut self, p: &ClientboundDisconnect) {
warn!("Got disconnect packet {p:?}");
as_system::<MessageWriter<_>>(self.ecs, |mut events| {
events.write(DisconnectEvent {
entity: self.player,
reason: Some(p.reason.clone()),
});
});
}
pub fn finish_configuration(&mut self, _p: &ClientboundFinishConfiguration) {
debug!("got FinishConfiguration packet");
as_system::<(Commands, Query<&mut RawConnection>)>(
self.ecs,
|(mut commands, mut query)| {
let mut raw_conn = query.get_mut(self.player).unwrap();
raw_conn.state = ConnectionProtocol::Game;
commands.trigger(SendConfigPacketEvent::new(
self.player,
ServerboundFinishConfiguration,
));
// these components are added now that we're going to be in the Game state
commands
.entity(self.player)
.remove::<InConfigState>()
.insert((
crate::JoinedClientBundle::default(),
// localentity should already be added, but in case the user forgot or
// something we also add it here
LocalEntity,
));
},
);
}
pub fn keep_alive(&mut self, p: &ClientboundKeepAlive) {
debug!(
"Got keep alive packet (in configuration) {p:?} for {:?}",
self.player
);
as_system::<Commands>(self.ecs, |mut commands| {
commands.trigger(KeepAliveEvent {
entity: self.player,
id: p.id,
});
commands.trigger(SendConfigPacketEvent::new(
self.player,
ServerboundKeepAlive { id: p.id },
));
});
}
pub fn ping(&mut self, p: &ClientboundPing) {
debug!("Got ping packet (in configuration) {p:?}");
as_system::<Commands>(self.ecs, |mut commands| {
commands.trigger(ConfigPingEvent {
entity: self.player,
packet: p.clone(),
});
});
}
pub fn resource_pack_push(&mut self, p: &ClientboundResourcePackPush) {
debug!("Got resource pack push packet {p:?}");
as_system::<MessageWriter<_>>(self.ecs, |mut events| {
events.write(ResourcePackEvent {
entity: self.player,
id: p.id,
url: p.url.to_owned(),
hash: p.hash.to_owned(),
required: p.required,
prompt: p.prompt.to_owned(),
});
});
}
pub fn resource_pack_pop(&mut self, p: &ClientboundResourcePackPop) {
debug!("Got resource pack pop packet {p:?}");
}
pub fn update_enabled_features(&mut self, p: &ClientboundUpdateEnabledFeatures) {
debug!("Got update enabled features packet {p:?}");
}
pub fn update_tags(&mut self, _p: &ClientboundUpdateTags) {
debug!("Got update tags packet");
}
pub fn cookie_request(&mut self, p: &ClientboundCookieRequest) {
debug!("Got cookie request packet {p:?}");
as_system::<Commands>(self.ecs, |mut commands| {
commands.trigger(RequestCookieEvent {
entity: self.player,
key: p.key.clone(),
});
});
}
pub fn store_cookie(&mut self, p: &ClientboundStoreCookie) {
debug!("Got store cookie packet {p:?}");
as_system::<Commands>(self.ecs, |mut commands| {
commands.trigger(StoreCookieEvent {
entity: self.player,
key: p.key.clone(),
payload: p.payload.clone(),
});
});
}
pub fn reset_chat(&mut self, p: &ClientboundResetChat) {
debug!("Got reset chat packet {p:?}");
}
pub fn transfer(&mut self, p: &ClientboundTransfer) {
debug!("Got transfer packet {p:?}");
}
pub fn select_known_packs(&mut self, p: &ClientboundSelectKnownPacks) {
debug!("Got select known packs packet {p:?}");
as_system::<Commands>(self.ecs, |mut commands| {
// resource pack management isn't implemented
commands.trigger(SendConfigPacketEvent::new(
self.player,
ServerboundSelectKnownPacks {
known_packs: vec![],
},
));
});
}
pub fn server_links(&mut self, p: &ClientboundServerLinks) {
debug!("Got server links packet {p:?}");
}
pub fn custom_report_details(&mut self, p: &ClientboundCustomReportDetails) {
debug!("Got custom report details packet {p:?}");
}
pub fn clear_dialog(&mut self, p: &ClientboundClearDialog) {
debug!("Got clear dialog packet {p:?}");
}
pub fn show_dialog(&mut self, p: &ClientboundShowDialog) {
debug!("Got show dialog packet {p:?}");
}
pub fn code_of_conduct(&mut self, p: &ClientboundCodeOfConduct) {
debug!("Got code of conduct packet {p:?}");
}
}
|