kojacoord_protocol/versions/v1_20_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: 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 = uuid::Uuid::decode(src)?;
31 Ok(Self { username, uuid })
32 }
33}
34
35#[derive(Debug, Clone, PartialEq)]
36pub struct ServerboundEncryptionResponse {
37 pub shared_secret: Vec<u8>,
38
39 pub verify_token: Vec<u8>,
40}
41
42impl PacketId for ServerboundEncryptionResponse {
43 fn packet_id(_ver: u32) -> u8 {
44 0x01
45 }
46}
47
48impl Encode for ServerboundEncryptionResponse {
49 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
50 encode_byte_array(&self.shared_secret, dst)?;
51 encode_byte_array(&self.verify_token, dst)
52 }
53}
54
55impl Decode for ServerboundEncryptionResponse {
56 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
57 let shared_secret = decode_byte_array(src)?;
58 let verify_token = decode_byte_array(src)?;
59 Ok(Self {
60 shared_secret,
61 verify_token,
62 })
63 }
64}
65
66#[derive(Debug, Clone, PartialEq)]
67pub struct ServerboundLoginPluginResponse {
68 pub message_id: VarInt,
69
70 pub data: Option<Vec<u8>>,
71}
72
73impl PacketId for ServerboundLoginPluginResponse {
74 fn packet_id(_ver: u32) -> u8 {
75 0x02
76 }
77}
78
79impl Encode for ServerboundLoginPluginResponse {
80 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
81 self.message_id.encode(dst)?;
82 match &self.data {
83 Some(payload) => {
84 true.encode(dst)?;
85 dst.extend_from_slice(payload);
86 },
87 None => false.encode(dst)?,
88 }
89 Ok(())
90 }
91}
92
93impl Decode for ServerboundLoginPluginResponse {
94 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
95 let message_id = VarInt::decode(src)?;
96 let understood = bool::decode(src)?;
97 let data = if understood {
98 Some(src.split_to(src.len()).to_vec())
99 } else {
100 None
101 };
102 Ok(Self { message_id, data })
103 }
104}
105
106#[derive(Debug, Clone, PartialEq)]
107pub struct ServerboundLoginAcknowledged;
108
109impl PacketId for ServerboundLoginAcknowledged {
110 fn packet_id(_ver: u32) -> u8 {
111 0x03
112 }
113}
114
115impl Encode for ServerboundLoginAcknowledged {
116 fn encode(&self, _dst: &mut BytesMut) -> Result<(), ProtocolError> {
117 Ok(())
118 }
119}
120
121impl Decode for ServerboundLoginAcknowledged {
122 fn decode(_src: &mut Bytes) -> Result<Self, ProtocolError> {
123 Ok(Self)
124 }
125}
126
127#[derive(Debug, Clone, PartialEq)]
128pub struct ClientboundLoginDisconnect {
129 pub reason: String,
130}
131
132impl PacketId for ClientboundLoginDisconnect {
133 fn packet_id(_ver: u32) -> u8 {
134 0x00
135 }
136}
137
138impl Encode for ClientboundLoginDisconnect {
139 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
140 self.reason.encode(dst)
141 }
142}
143
144impl Decode for ClientboundLoginDisconnect {
145 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
146 Ok(Self {
147 reason: String::decode(src)?,
148 })
149 }
150}
151
152#[derive(Debug, Clone, PartialEq)]
153pub struct ClientboundEncryptionRequest {
154 pub server_id: String,
155
156 pub public_key: Vec<u8>,
157
158 pub verify_token: Vec<u8>,
159
160 pub should_authenticate: bool,
161}
162
163impl PacketId for ClientboundEncryptionRequest {
164 fn packet_id(_ver: u32) -> u8 {
165 0x01
166 }
167}
168
169impl Encode for ClientboundEncryptionRequest {
170 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
171 self.server_id.encode(dst)?;
172 encode_byte_array(&self.public_key, dst)?;
173 encode_byte_array(&self.verify_token, dst)?;
174 self.should_authenticate.encode(dst)
175 }
176}
177
178impl Decode for ClientboundEncryptionRequest {
179 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
180 let server_id = String::decode(src)?;
181 let public_key = decode_byte_array(src)?;
182 let verify_token = decode_byte_array(src)?;
183 let should_authenticate = bool::decode(src)?;
184 Ok(Self {
185 server_id,
186 public_key,
187 verify_token,
188 should_authenticate,
189 })
190 }
191}
192
193#[derive(Debug, Clone, PartialEq)]
194pub struct ProfileProperty {
195 pub name: String,
196
197 pub value: String,
198
199 pub signature: Option<String>,
200}
201
202impl Encode for ProfileProperty {
203 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
204 self.name.encode(dst)?;
205 self.value.encode(dst)?;
206 self.signature.encode(dst)
207 }
208}
209
210impl Decode for ProfileProperty {
211 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
212 let name = String::decode(src)?;
213 let value = String::decode(src)?;
214 let signature = Option::<String>::decode(src)?;
215 Ok(Self {
216 name,
217 value,
218 signature,
219 })
220 }
221}
222
223#[derive(Debug, Clone, PartialEq)]
224pub struct ClientboundLoginSuccess {
225 pub uuid: uuid::Uuid,
226
227 pub username: String,
228
229 pub properties: Vec<ProfileProperty>,
230
231 pub strict_error_handling: bool,
232}
233
234impl PacketId for ClientboundLoginSuccess {
235 fn packet_id(_ver: u32) -> u8 {
236 0x02
237 }
238}
239
240impl Encode for ClientboundLoginSuccess {
241 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
242 let (hi, lo) = self.uuid.as_u64_pair();
243 (hi as i64).encode(dst)?;
244 (lo as i64).encode(dst)?;
245 self.username.encode(dst)?;
246 self.properties.encode(dst)?;
247 self.strict_error_handling.encode(dst)
248 }
249}
250
251impl Decode for ClientboundLoginSuccess {
252 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
253 let hi = i64::decode(src)? as u64;
254 let lo = i64::decode(src)? as u64;
255 let uuid = uuid::Uuid::from_u64_pair(hi, lo);
256 let username = String::decode(src)?;
257 let properties = Vec::<ProfileProperty>::decode(src)?;
258 let strict_error_handling = bool::decode(src)?;
259 Ok(Self {
260 uuid,
261 username,
262 properties,
263 strict_error_handling,
264 })
265 }
266}
267
268#[derive(Debug, Clone, PartialEq)]
269pub struct ClientboundSetCompression {
270 pub threshold: VarInt,
271}
272
273impl PacketId for ClientboundSetCompression {
274 fn packet_id(_ver: u32) -> u8 {
275 0x03
276 }
277}
278
279impl Encode for ClientboundSetCompression {
280 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
281 self.threshold.encode(dst)
282 }
283}
284
285impl Decode for ClientboundSetCompression {
286 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
287 Ok(Self {
288 threshold: VarInt::decode(src)?,
289 })
290 }
291}
292
293#[derive(Debug, Clone, PartialEq)]
294pub struct ClientboundLoginPluginRequest {
295 pub message_id: VarInt,
296
297 pub channel: String,
298
299 pub data: Vec<u8>,
300}
301
302impl PacketId for ClientboundLoginPluginRequest {
303 fn packet_id(_ver: u32) -> u8 {
304 0x04
305 }
306}
307
308impl Encode for ClientboundLoginPluginRequest {
309 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
310 self.message_id.encode(dst)?;
311 self.channel.encode(dst)?;
312 dst.extend_from_slice(&self.data);
313 Ok(())
314 }
315}
316
317impl Decode for ClientboundLoginPluginRequest {
318 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
319 let message_id = VarInt::decode(src)?;
320 let channel = String::decode(src)?;
321 let data = src.split_to(src.len()).to_vec();
322 Ok(Self {
323 message_id,
324 channel,
325 data,
326 })
327 }
328}
329
330#[cfg(test)]
331mod tests {
332 use super::*;
333
334 #[test]
335 fn login_start_roundtrip() {
336 let p = ServerboundLoginStart {
337 username: "Player".to_string(),
338 uuid: uuid::Uuid::new_v4(),
339 };
340 let mut buf = BytesMut::new();
341 p.encode(&mut buf).unwrap();
342 assert_eq!(ServerboundLoginStart::decode(&mut buf.freeze()).unwrap(), p);
343 }
344
345 #[test]
346 fn encryption_response_roundtrip() {
347 let p = ServerboundEncryptionResponse {
348 shared_secret: vec![0xAA; 16],
349 verify_token: vec![0xBB; 4],
350 };
351 let mut buf = BytesMut::new();
352 p.encode(&mut buf).unwrap();
353 assert_eq!(
354 ServerboundEncryptionResponse::decode(&mut buf.freeze()).unwrap(),
355 p
356 );
357 }
358
359 #[test]
360 fn login_plugin_response_understood() {
361 let p = ServerboundLoginPluginResponse {
362 message_id: VarInt(1),
363 data: Some(vec![0x01, 0x02]),
364 };
365 let mut buf = BytesMut::new();
366 p.encode(&mut buf).unwrap();
367 assert_eq!(
368 ServerboundLoginPluginResponse::decode(&mut buf.freeze()).unwrap(),
369 p
370 );
371 }
372
373 #[test]
374 fn login_plugin_response_not_understood() {
375 let p = ServerboundLoginPluginResponse {
376 message_id: VarInt(1),
377 data: None,
378 };
379 let mut buf = BytesMut::new();
380 p.encode(&mut buf).unwrap();
381 assert_eq!(
382 ServerboundLoginPluginResponse::decode(&mut buf.freeze()).unwrap(),
383 p
384 );
385 }
386
387 #[test]
388 fn login_acknowledged_roundtrip() {
389 let p = ServerboundLoginAcknowledged;
390 let mut buf = BytesMut::new();
391 p.encode(&mut buf).unwrap();
392 assert_eq!(
393 ServerboundLoginAcknowledged::decode(&mut buf.freeze()).unwrap(),
394 p
395 );
396 }
397
398 #[test]
399 fn login_disconnect_roundtrip() {
400 let p = ClientboundLoginDisconnect {
401 reason: r#"{"text":"banned"}"#.to_string(),
402 };
403 let mut buf = BytesMut::new();
404 p.encode(&mut buf).unwrap();
405 assert_eq!(
406 ClientboundLoginDisconnect::decode(&mut buf.freeze()).unwrap(),
407 p
408 );
409 }
410
411 #[test]
412 fn encryption_request_roundtrip() {
413 let p = ClientboundEncryptionRequest {
414 server_id: String::new(),
415 public_key: vec![0x01, 0x02],
416 verify_token: vec![0x03, 0x04, 0x05, 0x06],
417 should_authenticate: false,
418 };
419 let mut buf = BytesMut::new();
420 p.encode(&mut buf).unwrap();
421 assert_eq!(
422 ClientboundEncryptionRequest::decode(&mut buf.freeze()).unwrap(),
423 p
424 );
425 }
426
427 #[test]
428 fn login_success_with_strict_error_handling() {
429 let p = ClientboundLoginSuccess {
430 uuid: uuid::Uuid::new_v4(),
431 username: "Player".to_string(),
432 properties: vec![ProfileProperty {
433 name: "textures".to_string(),
434 value: "data".to_string(),
435 signature: None,
436 }],
437 strict_error_handling: true,
438 };
439 let mut buf = BytesMut::new();
440 p.encode(&mut buf).unwrap();
441 let d = ClientboundLoginSuccess::decode(&mut buf.freeze()).unwrap();
442 assert_eq!(d.uuid, p.uuid);
443 assert!(d.strict_error_handling);
444 assert_eq!(d.properties.len(), 1);
445 }
446
447 #[test]
448 fn set_compression_roundtrip() {
449 let p = ClientboundSetCompression {
450 threshold: VarInt(256),
451 };
452 let mut buf = BytesMut::new();
453 p.encode(&mut buf).unwrap();
454 assert_eq!(
455 ClientboundSetCompression::decode(&mut buf.freeze()).unwrap(),
456 p
457 );
458 }
459
460 #[test]
461 fn login_plugin_request_roundtrip() {
462 let p = ClientboundLoginPluginRequest {
463 message_id: VarInt(42),
464 channel: "forge:handshake".to_string(),
465 data: vec![0xDE, 0xAD, 0xBE, 0xEF],
466 };
467 let mut buf = BytesMut::new();
468 p.encode(&mut buf).unwrap();
469 assert_eq!(
470 ClientboundLoginPluginRequest::decode(&mut buf.freeze()).unwrap(),
471 p
472 );
473 }
474
475 #[test]
476 fn packet_ids() {
477 assert_eq!(ServerboundLoginStart::packet_id(765), 0x00);
478 assert_eq!(ServerboundEncryptionResponse::packet_id(765), 0x01);
479 assert_eq!(ServerboundLoginPluginResponse::packet_id(765), 0x02);
480 assert_eq!(ServerboundLoginAcknowledged::packet_id(765), 0x03);
481 assert_eq!(ClientboundLoginDisconnect::packet_id(765), 0x00);
482 assert_eq!(ClientboundEncryptionRequest::packet_id(765), 0x01);
483 assert_eq!(ClientboundLoginSuccess::packet_id(765), 0x02);
484 assert_eq!(ClientboundSetCompression::packet_id(765), 0x03);
485 assert_eq!(ClientboundLoginPluginRequest::packet_id(765), 0x04);
486 }
487}