kojacoord_protocol/versions/v1_19_4/login/
mod.rs1use bytes::{Bytes, BytesMut};
2
3use crate::codec::{decode_byte_array, encode_byte_array, Decode, Encode, PacketId};
4use crate::error::ProtocolError;
5use crate::types::VarInt;
6
7#[derive(Debug, Clone, PartialEq)]
8pub struct ServerboundLoginStart {
9 pub username: String,
10
11 pub uuid: Option<uuid::Uuid>,
12}
13
14impl PacketId for ServerboundLoginStart {
15 fn packet_id(_ver: u32) -> u8 {
16 0x00
17 }
18}
19
20impl Encode for ServerboundLoginStart {
21 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
22 self.username.encode(dst)?;
23 self.uuid.encode(dst)
24 }
25}
26
27impl Decode for ServerboundLoginStart {
28 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
29 let username = String::decode(src)?;
30 let uuid = Option::<uuid::Uuid>::decode(src)?;
31 Ok(Self { username, uuid })
32 }
33}
34
35#[derive(Debug, Clone, PartialEq)]
36pub struct ClientboundLoginDisconnect {
37 pub reason: String,
38}
39
40impl PacketId for ClientboundLoginDisconnect {
41 fn packet_id(_ver: u32) -> u8 {
42 0x00
43 }
44}
45
46impl Encode for ClientboundLoginDisconnect {
47 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
48 self.reason.encode(dst)
49 }
50}
51
52impl Decode for ClientboundLoginDisconnect {
53 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
54 Ok(Self {
55 reason: String::decode(src)?,
56 })
57 }
58}
59
60#[derive(Debug, Clone, PartialEq)]
61pub struct ClientboundEncryptionRequest {
62 pub server_id: String,
63
64 pub public_key: Vec<u8>,
65
66 pub verify_token: Vec<u8>,
67
68 pub should_authenticate: bool,
69}
70
71impl PacketId for ClientboundEncryptionRequest {
72 fn packet_id(_ver: u32) -> u8 {
73 0x01
74 }
75}
76
77impl Encode for ClientboundEncryptionRequest {
78 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
79 self.server_id.encode(dst)?;
80 encode_byte_array(&self.public_key, dst)?;
81 encode_byte_array(&self.verify_token, dst)?;
82 self.should_authenticate.encode(dst)
83 }
84}
85
86impl Decode for ClientboundEncryptionRequest {
87 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
88 let server_id = String::decode(src)?;
89 let public_key = decode_byte_array(src)?;
90 let verify_token = decode_byte_array(src)?;
91 let should_authenticate = bool::decode(src)?;
92 Ok(Self {
93 server_id,
94 public_key,
95 verify_token,
96 should_authenticate,
97 })
98 }
99}
100
101#[derive(Debug, Clone, PartialEq)]
102pub struct ProfileProperty {
103 pub name: String,
104
105 pub value: String,
106
107 pub signature: Option<String>,
108}
109
110impl Encode for ProfileProperty {
111 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
112 self.name.encode(dst)?;
113 self.value.encode(dst)?;
114 self.signature.encode(dst)
115 }
116}
117
118impl Decode for ProfileProperty {
119 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
120 let name = String::decode(src)?;
121 let value = String::decode(src)?;
122 let signature = Option::<String>::decode(src)?;
123 Ok(Self {
124 name,
125 value,
126 signature,
127 })
128 }
129}
130
131#[derive(Debug, Clone, PartialEq)]
132pub struct ClientboundLoginSuccess {
133 pub uuid: uuid::Uuid,
134
135 pub username: String,
136
137 pub properties: Vec<ProfileProperty>,
138}
139
140impl PacketId for ClientboundLoginSuccess {
141 fn packet_id(_ver: u32) -> u8 {
142 0x02
143 }
144}
145
146impl Encode for ClientboundLoginSuccess {
147 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
148 let (hi, lo) = self.uuid.as_u64_pair();
149 (hi as i64).encode(dst)?;
150 (lo as i64).encode(dst)?;
151 self.username.encode(dst)?;
152 self.properties.encode(dst)
153 }
154}
155
156impl Decode for ClientboundLoginSuccess {
157 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
158 let hi = i64::decode(src)? as u64;
159 let lo = i64::decode(src)? as u64;
160 let uuid = uuid::Uuid::from_u64_pair(hi, lo);
161 let username = String::decode(src)?;
162 let properties = Vec::<ProfileProperty>::decode(src)?;
163 Ok(Self {
164 uuid,
165 username,
166 properties,
167 })
168 }
169}
170
171#[derive(Debug, Clone, PartialEq)]
172pub struct ClientboundSetCompression {
173 pub threshold: VarInt,
174}
175
176impl PacketId for ClientboundSetCompression {
177 fn packet_id(_ver: u32) -> u8 {
178 0x03
179 }
180}
181
182impl Encode for ClientboundSetCompression {
183 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
184 self.threshold.encode(dst)
185 }
186}
187
188impl Decode for ClientboundSetCompression {
189 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
190 Ok(Self {
191 threshold: VarInt::decode(src)?,
192 })
193 }
194}
195
196#[derive(Debug, Clone, PartialEq)]
197pub struct ClientboundLoginPluginRequest {
198 pub message_id: VarInt,
199
200 pub channel: String,
201
202 pub data: Vec<u8>,
203}
204
205impl PacketId for ClientboundLoginPluginRequest {
206 fn packet_id(_ver: u32) -> u8 {
207 0x04
208 }
209}
210
211impl Encode for ClientboundLoginPluginRequest {
212 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
213 self.message_id.encode(dst)?;
214 self.channel.encode(dst)?;
215 dst.extend_from_slice(&self.data);
216 Ok(())
217 }
218}
219
220impl Decode for ClientboundLoginPluginRequest {
221 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
222 let message_id = VarInt::decode(src)?;
223 let channel = String::decode(src)?;
224
225 let data = src.split_to(src.len()).to_vec();
226 Ok(Self {
227 message_id,
228 channel,
229 data,
230 })
231 }
232}
233
234#[derive(Debug, Clone, PartialEq)]
235pub struct ServerboundEncryptionResponse {
236 pub shared_secret: Vec<u8>,
237
238 pub verify_token: Vec<u8>,
239}
240
241impl PacketId for ServerboundEncryptionResponse {
242 fn packet_id(_ver: u32) -> u8 {
243 0x01
244 }
245}
246
247impl Encode for ServerboundEncryptionResponse {
248 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
249 encode_byte_array(&self.shared_secret, dst)?;
250 encode_byte_array(&self.verify_token, dst)
251 }
252}
253
254impl Decode for ServerboundEncryptionResponse {
255 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
256 let shared_secret = decode_byte_array(src)?;
257 let verify_token = decode_byte_array(src)?;
258 Ok(Self {
259 shared_secret,
260 verify_token,
261 })
262 }
263}
264
265#[derive(Debug, Clone, PartialEq)]
266pub struct ServerboundLoginPluginResponse {
267 pub message_id: VarInt,
268
269 pub data: Option<Vec<u8>>,
270}
271
272impl PacketId for ServerboundLoginPluginResponse {
273 fn packet_id(_ver: u32) -> u8 {
274 0x02
275 }
276}
277
278impl Encode for ServerboundLoginPluginResponse {
279 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
280 self.message_id.encode(dst)?;
281 match &self.data {
282 Some(payload) => {
283 true.encode(dst)?;
284 dst.extend_from_slice(payload);
285 },
286 None => false.encode(dst)?,
287 }
288 Ok(())
289 }
290}
291
292impl Decode for ServerboundLoginPluginResponse {
293 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
294 let message_id = VarInt::decode(src)?;
295 let understood = bool::decode(src)?;
296 let data = if understood {
297 Some(src.split_to(src.len()).to_vec())
298 } else {
299 None
300 };
301 Ok(Self { message_id, data })
302 }
303}
304
305#[cfg(test)]
306mod tests {
307 use super::*;
308
309 #[test]
310 fn login_start_with_uuid() {
311 let p = ServerboundLoginStart {
312 username: "Player".to_string(),
313 uuid: Some(uuid::Uuid::new_v4()),
314 };
315 let mut buf = BytesMut::new();
316 p.encode(&mut buf).unwrap();
317 let mut b = buf.freeze();
318 assert_eq!(ServerboundLoginStart::decode(&mut b).unwrap(), p);
319 }
320
321 #[test]
322 fn login_start_no_uuid() {
323 let p = ServerboundLoginStart {
324 username: "Player".to_string(),
325 uuid: None,
326 };
327 let mut buf = BytesMut::new();
328 p.encode(&mut buf).unwrap();
329 let mut b = buf.freeze();
330 assert_eq!(ServerboundLoginStart::decode(&mut b).unwrap(), p);
331 }
332
333 #[test]
334 fn encryption_request_with_authenticate() {
335 let p = ClientboundEncryptionRequest {
336 server_id: String::new(),
337 public_key: vec![1, 2, 3],
338 verify_token: vec![4, 5, 6, 7],
339 should_authenticate: true,
340 };
341 let mut buf = BytesMut::new();
342 p.encode(&mut buf).unwrap();
343 let mut b = buf.freeze();
344 assert_eq!(ClientboundEncryptionRequest::decode(&mut b).unwrap(), p);
345 }
346
347 #[test]
348 fn login_success_with_properties() {
349 let p = ClientboundLoginSuccess {
350 uuid: uuid::Uuid::new_v4(),
351 username: "Player".to_string(),
352 properties: vec![ProfileProperty {
353 name: "textures".to_string(),
354 value: "base64data".to_string(),
355 signature: Some("sig".to_string()),
356 }],
357 };
358 let mut buf = BytesMut::new();
359 p.encode(&mut buf).unwrap();
360 let mut b = buf.freeze();
361 let d = ClientboundLoginSuccess::decode(&mut b).unwrap();
362 assert_eq!(d.uuid, p.uuid);
363 assert_eq!(d.username, p.username);
364 assert_eq!(d.properties.len(), 1);
365 assert_eq!(d.properties[0].name, "textures");
366 }
367
368 #[test]
369 fn set_compression_roundtrip() {
370 let p = ClientboundSetCompression {
371 threshold: VarInt(256),
372 };
373 let mut buf = BytesMut::new();
374 p.encode(&mut buf).unwrap();
375 let mut b = buf.freeze();
376 assert_eq!(ClientboundSetCompression::decode(&mut b).unwrap(), p);
377 }
378
379 #[test]
380 fn login_plugin_request_roundtrip() {
381 let p = ClientboundLoginPluginRequest {
382 message_id: VarInt(42),
383 channel: "forge:handshake".to_string(),
384 data: vec![0xDE, 0xAD, 0xBE, 0xEF],
385 };
386 let mut buf = BytesMut::new();
387 p.encode(&mut buf).unwrap();
388 let mut b = buf.freeze();
389 assert_eq!(ClientboundLoginPluginRequest::decode(&mut b).unwrap(), p);
390 }
391
392 #[test]
393 fn login_plugin_response_understood() {
394 let p = ServerboundLoginPluginResponse {
395 message_id: VarInt(42),
396 data: Some(vec![0x01, 0x02]),
397 };
398 let mut buf = BytesMut::new();
399 p.encode(&mut buf).unwrap();
400 let mut b = buf.freeze();
401 assert_eq!(ServerboundLoginPluginResponse::decode(&mut b).unwrap(), p);
402 }
403
404 #[test]
405 fn login_plugin_response_not_understood() {
406 let p = ServerboundLoginPluginResponse {
407 message_id: VarInt(42),
408 data: None,
409 };
410 let mut buf = BytesMut::new();
411 p.encode(&mut buf).unwrap();
412 let mut b = buf.freeze();
413 assert_eq!(ServerboundLoginPluginResponse::decode(&mut b).unwrap(), p);
414 }
415}