basalt_mc_protocol/
registry.rs1use crate::error::Result;
2use crate::packets::configuration::{
3 ClientboundConfigurationPacket, ServerboundConfigurationPacket,
4};
5use crate::packets::handshake::ServerboundHandshakePacket;
6use crate::packets::login::{ClientboundLoginPacket, ServerboundLoginPacket};
7use crate::packets::play::{ClientboundPlayPacket, ServerboundPlayPacket};
8use crate::packets::status::{ClientboundStatusPacket, ServerboundStatusPacket};
9use crate::version::ProtocolVersion;
10
11#[derive(Debug)]
20pub struct PacketRegistry {
21 version: ProtocolVersion,
23}
24
25impl PacketRegistry {
26 pub fn for_version(version: ProtocolVersion) -> Self {
28 Self { version }
29 }
30
31 pub fn version(&self) -> ProtocolVersion {
33 self.version
34 }
35
36 pub fn decode_serverbound_handshake(
38 &self,
39 id: i32,
40 buf: &mut &[u8],
41 ) -> Result<ServerboundHandshakePacket> {
42 ServerboundHandshakePacket::decode_by_id(id, buf)
43 }
44
45 pub fn decode_serverbound_status(
47 &self,
48 id: i32,
49 buf: &mut &[u8],
50 ) -> Result<ServerboundStatusPacket> {
51 ServerboundStatusPacket::decode_by_id(id, buf)
52 }
53
54 pub fn decode_clientbound_status(
56 &self,
57 id: i32,
58 buf: &mut &[u8],
59 ) -> Result<ClientboundStatusPacket> {
60 ClientboundStatusPacket::decode_by_id(id, buf)
61 }
62
63 pub fn decode_serverbound_login(
65 &self,
66 id: i32,
67 buf: &mut &[u8],
68 ) -> Result<ServerboundLoginPacket> {
69 ServerboundLoginPacket::decode_by_id(id, buf)
70 }
71
72 pub fn decode_clientbound_login(
74 &self,
75 id: i32,
76 buf: &mut &[u8],
77 ) -> Result<ClientboundLoginPacket> {
78 ClientboundLoginPacket::decode_by_id(id, buf)
79 }
80
81 pub fn decode_serverbound_configuration(
83 &self,
84 id: i32,
85 buf: &mut &[u8],
86 ) -> Result<ServerboundConfigurationPacket> {
87 ServerboundConfigurationPacket::decode_by_id(id, buf)
88 }
89
90 pub fn decode_clientbound_configuration(
92 &self,
93 id: i32,
94 buf: &mut &[u8],
95 ) -> Result<ClientboundConfigurationPacket> {
96 ClientboundConfigurationPacket::decode_by_id(id, buf)
97 }
98
99 pub fn decode_serverbound_play(
101 &self,
102 id: i32,
103 buf: &mut &[u8],
104 ) -> Result<ServerboundPlayPacket> {
105 ServerboundPlayPacket::decode_by_id(id, buf)
106 }
107
108 pub fn decode_clientbound_play(
110 &self,
111 id: i32,
112 buf: &mut &[u8],
113 ) -> Result<ClientboundPlayPacket> {
114 ClientboundPlayPacket::decode_by_id(id, buf)
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121 use crate::packets::handshake::ServerboundHandshakeSetProtocol;
122 use crate::packets::status::{
123 ClientboundStatusPing, ClientboundStatusServerInfo, ServerboundStatusPing,
124 ServerboundStatusPingStart,
125 };
126 use basalt_types::{Encode, EncodedSize};
127
128 fn registry() -> PacketRegistry {
129 PacketRegistry::for_version(ProtocolVersion::V1_21)
130 }
131
132 #[test]
133 fn version() {
134 assert_eq!(registry().version(), ProtocolVersion::V1_21);
135 }
136
137 #[test]
138 fn decode_handshake() {
139 let packet = ServerboundHandshakeSetProtocol {
140 protocol_version: 767,
141 server_host: "localhost".into(),
142 server_port: 25565,
143 next_state: 1,
144 };
145 let mut buf = Vec::with_capacity(packet.encoded_size());
146 packet.encode(&mut buf).unwrap();
147
148 let mut cursor = buf.as_slice();
149 let result = registry()
150 .decode_serverbound_handshake(ServerboundHandshakeSetProtocol::PACKET_ID, &mut cursor)
151 .unwrap();
152 assert!(cursor.is_empty());
153 assert_eq!(result, ServerboundHandshakePacket::SetProtocol(packet));
154 }
155
156 #[test]
157 fn decode_status_request() {
158 let mut buf = Vec::new();
159 ServerboundStatusPingStart.encode(&mut buf).unwrap();
160
161 let mut cursor = buf.as_slice();
162 let result = registry()
163 .decode_serverbound_status(ServerboundStatusPingStart::PACKET_ID, &mut cursor)
164 .unwrap();
165 assert!(matches!(result, ServerboundStatusPacket::PingStart(_)));
166 }
167
168 #[test]
169 fn decode_ping_request() {
170 let packet = ServerboundStatusPing { time: 12345 };
171 let mut buf = Vec::new();
172 packet.encode(&mut buf).unwrap();
173
174 let mut cursor = buf.as_slice();
175 let result = registry()
176 .decode_serverbound_status(ServerboundStatusPing::PACKET_ID, &mut cursor)
177 .unwrap();
178 assert_eq!(
179 result,
180 ServerboundStatusPacket::Ping(ServerboundStatusPing { time: 12345 })
181 );
182 }
183
184 #[test]
185 fn decode_status_response() {
186 let packet = ClientboundStatusServerInfo {
187 response: "{}".into(),
188 };
189 let mut buf = Vec::new();
190 packet.encode(&mut buf).unwrap();
191
192 let mut cursor = buf.as_slice();
193 let result = registry()
194 .decode_clientbound_status(ClientboundStatusServerInfo::PACKET_ID, &mut cursor)
195 .unwrap();
196 assert_eq!(
197 result,
198 ClientboundStatusPacket::ServerInfo(ClientboundStatusServerInfo {
199 response: "{}".into()
200 })
201 );
202 }
203
204 #[test]
205 fn decode_ping_response() {
206 let packet = ClientboundStatusPing { time: 67890 };
207 let mut buf = Vec::new();
208 packet.encode(&mut buf).unwrap();
209
210 let mut cursor = buf.as_slice();
211 let result = registry()
212 .decode_clientbound_status(ClientboundStatusPing::PACKET_ID, &mut cursor)
213 .unwrap();
214 assert_eq!(
215 result,
216 ClientboundStatusPacket::Ping(ClientboundStatusPing { time: 67890 })
217 );
218 }
219
220 #[test]
221 fn unknown_handshake_packet() {
222 let mut cursor: &[u8] = &[];
223 assert!(
224 registry()
225 .decode_serverbound_handshake(0xFF, &mut cursor)
226 .is_err()
227 );
228 }
229
230 #[test]
231 fn unknown_status_serverbound() {
232 let mut cursor: &[u8] = &[];
233 assert!(
234 registry()
235 .decode_serverbound_status(0xFF, &mut cursor)
236 .is_err()
237 );
238 }
239
240 #[test]
241 fn unknown_status_clientbound() {
242 let mut cursor: &[u8] = &[];
243 assert!(
244 registry()
245 .decode_clientbound_status(0xFF, &mut cursor)
246 .is_err()
247 );
248 }
249}