1#![doc = include_str!("../README.md")]
2#![allow(deprecated)] #[doc(hidden)]
6pub mod __private {
7 pub use anyhow::{Context, Result, anyhow, bail, ensure};
8
9 pub use crate::Packet;
10}
11
12extern crate self as chunkedge_protocol;
13
14mod biome_pos;
15pub mod block_pos;
16pub mod chunk_pos;
17pub mod chunk_section_pos;
18pub mod decode;
19mod difficulty;
20mod direction;
21pub mod encode;
22pub mod game_mode;
23mod global_pos;
24mod hand;
25pub mod movement_flags;
26pub mod packets;
27pub mod profile;
28pub mod sound;
29mod velocity;
30
31use std::io::Write;
32
33pub use anyhow;
34use anyhow::Context;
35pub use biome_pos::BiomePos;
36pub use block::{BlockKind, BlockState};
37pub use block_pos::BlockPos;
38pub use bytes;
39pub use chunk_pos::ChunkPos;
40pub use chunk_section_pos::ChunkSectionPos;
41use chunkedge_binary::Encode;
42pub use chunkedge_binary::array::FixedArray;
43pub use chunkedge_binary::bit_set::{FixedBitSet, VariableBitSet};
44pub use chunkedge_binary::byte_angle::ByteAngle;
45pub use chunkedge_binary::{
46 IDSet, IdOr, IntoTextComponent, TextComponent, VarInt, VarIntDecodeError, VarLong,
47};
48pub use chunkedge_generated::registry_id::RegistryId;
49pub use chunkedge_generated::{block, packet_id, status_effects};
50pub use chunkedge_ident as ident;
51pub use chunkedge_ident::Ident;
52pub use chunkedge_item::{ItemKind, ItemStack};
53pub use chunkedge_math as math;
54pub use chunkedge_nbt as nbt;
55use chunkedge_protocol_macros::Packet;
56pub use chunkedge_text as text;
57pub use decode::PacketDecoder;
58use derive_more::{From, Into};
59pub use difficulty::Difficulty;
60pub use direction::Direction;
61pub use encode::{PacketEncoder, WritePacket};
62pub use game_mode::GameMode;
63pub use global_pos::GlobalPos;
64pub use hand::Hand;
65pub use ident::ident;
66pub use packets::play::level_particles_s2c::Particle;
67use serde::{Deserialize, Serialize};
68pub use sound::Sound;
69pub use text::{JsonText, Text};
70pub use uuid;
71pub use velocity::Velocity;
72
73pub const MAX_PACKET_SIZE: i32 = 2_i32.pow(21) - 1; pub const PROTOCOL_VERSION: i32 = 770;
78
79pub const MINECRAFT_VERSION: &str = "1.21.5";
82
83#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From, Into)]
89pub struct CompressionThreshold(pub i32);
90
91impl CompressionThreshold {
92 pub const DEFAULT: Self = Self(-1);
94}
95
96impl Default for CompressionThreshold {
98 fn default() -> Self {
99 Self::DEFAULT
100 }
101}
102
103pub trait Packet: std::fmt::Debug {
110 const ID: i32;
112 const NAME: &'static str;
114 const SIDE: PacketSide;
116 const STATE: PacketState;
118
119 fn encode_with_id(&self, mut w: impl Write) -> anyhow::Result<()>
121 where
122 Self: Encode,
123 {
124 VarInt(Self::ID)
125 .encode(&mut w)
126 .context("failed to encode packet ID")?;
127
128 self.encode(w)
129 }
130}
131
132#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
134pub enum PacketSide {
135 Clientbound,
137 Serverbound,
139}
140
141#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
143pub enum PacketState {
144 Handshake,
145 Status,
146 Login,
147 Configuration,
148 Play,
149}
150
151#[allow(dead_code)]
152#[cfg(test)]
153mod tests {
154 use std::borrow::Cow;
155
156 use bytes::BytesMut;
157 use chunkedge_binary::{Decode, Encode, VarInt, VarLong};
159 use chunkedge_item::{ItemKind, ItemStack};
160 use chunkedge_protocol_macros::Packet;
161
162 use super::*;
163 use crate::Ident;
164 use crate::block_pos::BlockPos;
165 use crate::decode::PacketDecoder;
166 use crate::encode::PacketEncoder;
167 use crate::hand::Hand;
168 use crate::text::{IntoText, Text};
169
170 #[derive(Encode, Decode, Packet, Debug)]
171 #[packet(id = 1, side = PacketSide::Clientbound)]
172 struct RegularStruct {
173 foo: i32,
174 bar: bool,
175 baz: f64,
176 }
177
178 #[derive(Encode, Decode, Packet, Debug)]
179 #[packet(id = 2, side = PacketSide::Clientbound)]
180 struct UnitStruct;
181
182 #[derive(Encode, Decode, Packet, Debug)]
183 #[packet(id = 3, side = PacketSide::Clientbound)]
184 struct EmptyStruct;
185
186 #[derive(Encode, Decode, Packet, Debug)]
187 #[packet(id = 4, side = PacketSide::Clientbound)]
188 struct TupleStruct(i32, bool, f64);
189
190 #[derive(Encode, Decode, Packet, Debug)]
191 #[packet(id = 5, side = PacketSide::Clientbound)]
192 struct StructWithGenerics<'z, T = ()> {
193 foo: &'z str,
194 bar: T,
195 }
196
197 #[derive(Encode, Decode, Packet, Debug)]
198 #[packet(id = 6, side = PacketSide::Clientbound)]
199 struct TupleStructWithGenerics<'z, T = ()>(&'z str, i32, T);
200
201 #[allow(unconditional_recursion, clippy::extra_unused_type_parameters)]
202 fn assert_has_impls<'a, T>()
203 where
204 T: Encode + Decode<'a> + Packet,
205 {
206 assert_has_impls::<RegularStruct>();
207 assert_has_impls::<UnitStruct>();
208 assert_has_impls::<EmptyStruct>();
209 assert_has_impls::<TupleStruct>();
210 assert_has_impls::<StructWithGenerics>();
211 assert_has_impls::<TupleStructWithGenerics>();
212 }
213
214 #[test]
215 fn packet_name() {
216 assert_eq!(RegularStruct::NAME, "RegularStruct");
217 assert_eq!(UnitStruct::NAME, "UnitStruct");
218 assert_eq!(StructWithGenerics::<()>::NAME, "StructWithGenerics");
219 }
220
221 #[cfg(feature = "encryption")]
222 const CRYPT_KEY: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
223
224 #[derive(PartialEq, Debug, Encode, Decode, Packet)]
225 #[packet(id = 42, side = PacketSide::Clientbound)]
226 struct TestPacket<'a> {
227 a: bool,
228 b: u8,
229 c: i32,
230 d: f32,
231 e: f64,
232 f: BlockPos,
233 g: Hand,
234 h: Ident<Cow<'a, str>>,
235 i: ItemStack,
236 j: Text,
237 k: VarInt,
238 l: VarLong,
239 m: &'a str,
240 n: &'a [u8; 10],
241 o: [u128; 3],
242 }
243
244 impl<'a> TestPacket<'a> {
245 fn new(string: &'a str) -> Self {
246 Self {
247 a: true,
248 b: 12,
249 c: -999,
250 d: 5.001,
251 e: 1e10,
252 f: BlockPos::new(1, 2, 3),
253 g: Hand::Off,
254 h: Ident::new("minecraft:whatever").unwrap(),
255 i: ItemStack::new(ItemKind::WoodenSword, 12),
256 j: "my ".into_text() + "fancy".italic() + " text",
257 k: VarInt(123),
258 l: VarLong(456),
259 m: string,
260 n: &[7; 10],
261 o: [123456789; 3],
262 }
263 }
264 }
265
266 fn check_test_packet(dec: &mut PacketDecoder, string: &str) {
267 let frame = dec.try_next_packet().unwrap().unwrap();
268
269 let pkt = frame.decode::<TestPacket>().unwrap();
270
271 assert_eq!(&pkt, &TestPacket::new(string));
272 }
273
274 #[test]
275 fn packets_round_trip() {
276 let mut buf = BytesMut::new();
277
278 let mut enc = PacketEncoder::new();
279
280 enc.append_packet(&TestPacket::new("first")).unwrap();
281 #[cfg(feature = "compression")]
282 enc.set_compression(0.into());
283 enc.append_packet(&TestPacket::new("second")).unwrap();
284 buf.unsplit(enc.take());
285 #[cfg(feature = "encryption")]
286 enc.enable_encryption(&CRYPT_KEY);
287 enc.append_packet(&TestPacket::new("third")).unwrap();
288 enc.prepend_packet(&TestPacket::new("fourth")).unwrap();
289
290 buf.unsplit(enc.take());
291
292 let mut dec = PacketDecoder::new();
293
294 dec.queue_bytes(buf);
295
296 check_test_packet(&mut dec, "first");
297
298 #[cfg(feature = "compression")]
299 dec.set_compression(0.into());
300
301 check_test_packet(&mut dec, "second");
302
303 #[cfg(feature = "encryption")]
304 dec.enable_encryption(&CRYPT_KEY);
305
306 check_test_packet(&mut dec, "fourth");
307 check_test_packet(&mut dec, "third");
308 }
309}