Skip to main content

kojacoord_protocol/versions/v1_19_4/login/
mod.rs

1use 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}