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