kojacoord_protocol/versions/v1_6_4/login/
mod.rs1use crate::codec::{Decode, Encode, PacketId};
2use crate::error::ProtocolError;
3use bytes::{Bytes, BytesMut};
4
5fn decode_legacy_string(src: &mut Bytes) -> Result<String, ProtocolError> {
6 if src.len() < 2 {
7 return Err(ProtocolError::UnexpectedEof);
8 }
9 let len = u16::from_be_bytes([src[0], src[1]]) as usize;
10 src.advance(2);
11 let byte_len = len * 2;
12 if src.len() < byte_len {
13 return Err(ProtocolError::UnexpectedEof);
14 }
15 let raw = src.copy_to_bytes(byte_len);
16 let chars: Vec<u16> = raw
17 .chunks(2)
18 .map(|c| u16::from_be_bytes([c[0], c[1]]))
19 .collect();
20 String::from_utf16(&chars).map_err(|_| ProtocolError::UnexpectedEof)
21}
22
23fn encode_legacy_string(s: &str, dst: &mut BytesMut) {
24 let utf16: Vec<u16> = s.encode_utf16().collect();
25 dst.extend_from_slice(&(utf16.len() as u16).to_be_bytes());
26 for ch in &utf16 {
27 dst.extend_from_slice(&ch.to_be_bytes());
28 }
29}
30
31use bytes::Buf;
32
33#[derive(Debug, Clone)]
34pub struct HandshakeC2S {
35 pub protocol_version: u8,
36 pub username: String,
37 pub host: String,
38 pub port: i32,
39}
40
41impl PacketId for HandshakeC2S {
42 fn packet_id(_ver: u32) -> u8 {
43 0x02
44 }
45}
46
47impl Encode for HandshakeC2S {
48 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
49 dst.extend_from_slice(&[self.protocol_version]);
50 encode_legacy_string(&self.username, dst);
51 encode_legacy_string(&self.host, dst);
52 dst.extend_from_slice(&self.port.to_be_bytes());
53 Ok(())
54 }
55}
56
57impl Decode for HandshakeC2S {
58 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
59 if src.is_empty() {
60 return Err(ProtocolError::UnexpectedEof);
61 }
62 let protocol_version = src.get_u8();
63 let username = decode_legacy_string(src)?;
64 let host = decode_legacy_string(src)?;
65 if src.remaining() < 4 {
66 return Err(ProtocolError::UnexpectedEof);
67 }
68 let port = src.get_i32();
69 Ok(Self {
70 protocol_version,
71 username,
72 host,
73 port,
74 })
75 }
76}
77
78#[derive(Debug, Clone)]
79pub struct EncryptionKeyRequestS2C {
80 pub server_id: String,
81 pub public_key: Vec<u8>,
82 pub verify_token: Vec<u8>,
83}
84
85impl PacketId for EncryptionKeyRequestS2C {
86 fn packet_id(_ver: u32) -> u8 {
87 0xFD
88 }
89}
90
91impl Encode for EncryptionKeyRequestS2C {
92 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
93 encode_legacy_string(&self.server_id, dst);
94 dst.extend_from_slice(&(self.public_key.len() as i16).to_be_bytes());
95 dst.extend_from_slice(&self.public_key);
96 dst.extend_from_slice(&(self.verify_token.len() as i16).to_be_bytes());
97 dst.extend_from_slice(&self.verify_token);
98 Ok(())
99 }
100}
101
102impl Decode for EncryptionKeyRequestS2C {
103 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
104 let server_id = decode_legacy_string(src)?;
105 if src.remaining() < 2 {
106 return Err(ProtocolError::UnexpectedEof);
107 }
108 let key_len = i16::from_be_bytes([src[0], src[1]]) as usize;
109 src.advance(2);
110 if src.remaining() < key_len {
111 return Err(ProtocolError::UnexpectedEof);
112 }
113 let public_key = src.copy_to_bytes(key_len).to_vec();
114 if src.remaining() < 2 {
115 return Err(ProtocolError::UnexpectedEof);
116 }
117 let tok_len = i16::from_be_bytes([src[0], src[1]]) as usize;
118 src.advance(2);
119 if src.remaining() < tok_len {
120 return Err(ProtocolError::UnexpectedEof);
121 }
122 let verify_token = src.copy_to_bytes(tok_len).to_vec();
123 Ok(Self {
124 server_id,
125 public_key,
126 verify_token,
127 })
128 }
129}
130
131#[derive(Debug, Clone)]
132pub struct EncryptionKeyResponseC2S {
133 pub shared_secret: Vec<u8>,
134 pub verify_token: Vec<u8>,
135}
136
137impl PacketId for EncryptionKeyResponseC2S {
138 fn packet_id(_ver: u32) -> u8 {
139 0xFC
140 }
141}
142
143impl Encode for EncryptionKeyResponseC2S {
144 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
145 dst.extend_from_slice(&(self.shared_secret.len() as i16).to_be_bytes());
146 dst.extend_from_slice(&self.shared_secret);
147 dst.extend_from_slice(&(self.verify_token.len() as i16).to_be_bytes());
148 dst.extend_from_slice(&self.verify_token);
149 Ok(())
150 }
151}
152
153impl Decode for EncryptionKeyResponseC2S {
154 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
155 if src.remaining() < 2 {
156 return Err(ProtocolError::UnexpectedEof);
157 }
158 let ss_len = i16::from_be_bytes([src[0], src[1]]) as usize;
159 src.advance(2);
160 if src.remaining() < ss_len {
161 return Err(ProtocolError::UnexpectedEof);
162 }
163 let shared_secret = src.copy_to_bytes(ss_len).to_vec();
164 if src.remaining() < 2 {
165 return Err(ProtocolError::UnexpectedEof);
166 }
167 let vt_len = i16::from_be_bytes([src[0], src[1]]) as usize;
168 src.advance(2);
169 if src.remaining() < vt_len {
170 return Err(ProtocolError::UnexpectedEof);
171 }
172 let verify_token = src.copy_to_bytes(vt_len).to_vec();
173 Ok(Self {
174 shared_secret,
175 verify_token,
176 })
177 }
178}
179
180#[derive(Debug, Clone)]
181pub struct LoginRequestS2C {
182 pub entity_id: i32,
183 pub level_type: String,
184 pub game_mode: u8,
185 pub dimension: i8,
186 pub difficulty: u8,
187 pub world_height: u8,
188 pub max_players: u8,
189}
190
191impl PacketId for LoginRequestS2C {
192 fn packet_id(_ver: u32) -> u8 {
193 0x01
194 }
195}
196
197impl Encode for LoginRequestS2C {
198 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
199 dst.extend_from_slice(&self.entity_id.to_be_bytes());
200 encode_legacy_string(&self.level_type, dst);
201 dst.extend_from_slice(&[
202 self.game_mode,
203 self.dimension as u8,
204 self.difficulty,
205 self.world_height,
206 self.max_players,
207 ]);
208 Ok(())
209 }
210}
211
212impl Decode for LoginRequestS2C {
213 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
214 if src.remaining() < 4 {
215 return Err(ProtocolError::UnexpectedEof);
216 }
217 let entity_id = src.get_i32();
218 let level_type = decode_legacy_string(src)?;
219 if src.remaining() < 5 {
220 return Err(ProtocolError::UnexpectedEof);
221 }
222 let game_mode = src.get_u8();
223 let dimension = src.get_i8();
224 let difficulty = src.get_u8();
225 let world_height = src.get_u8();
226 let max_players = src.get_u8();
227 Ok(Self {
228 entity_id,
229 level_type,
230 game_mode,
231 dimension,
232 difficulty,
233 world_height,
234 max_players,
235 })
236 }
237}
238
239#[derive(Debug, Clone)]
240pub struct ClientboundLoginDisconnect {
241 pub reason: String,
242}
243
244impl PacketId for ClientboundLoginDisconnect {
245 fn packet_id(_ver: u32) -> u8 {
246 0x00
247 }
248}
249
250impl Encode for ClientboundLoginDisconnect {
251 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
252 encode_legacy_string(&self.reason, dst);
253 Ok(())
254 }
255}
256
257impl Decode for ClientboundLoginDisconnect {
258 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
259 Ok(Self {
260 reason: decode_legacy_string(src)?,
261 })
262 }
263}