valence_protocol/
lib.rs

1#![doc = include_str!("../README.md")]
2
3/// Used only by macros. Not public API.
4#[doc(hidden)]
5pub mod __private {
6    pub use anyhow::{anyhow, bail, ensure, Context, Result};
7
8    pub use crate::var_int::VarInt;
9    pub use crate::{Decode, Encode, Packet};
10}
11
12// This allows us to use our own proc macros internally.
13extern crate self as valence_protocol;
14
15mod array;
16mod biome_pos;
17mod bit_set;
18pub mod block_pos;
19mod bounded;
20mod byte_angle;
21pub mod chunk_pos;
22pub mod chunk_section_pos;
23pub mod decode;
24mod difficulty;
25mod direction;
26pub mod encode;
27pub mod game_mode;
28mod global_pos;
29mod hand;
30mod impls;
31pub mod item;
32pub mod packets;
33pub mod profile;
34mod raw;
35pub mod sound;
36pub mod var_int;
37mod var_long;
38mod velocity;
39
40use std::io::Write;
41
42use anyhow::Context;
43pub use array::FixedArray;
44pub use biome_pos::BiomePos;
45pub use bit_set::FixedBitSet;
46pub use block::{BlockKind, BlockState};
47pub use block_pos::BlockPos;
48pub use bounded::Bounded;
49pub use byte_angle::ByteAngle;
50pub use chunk_pos::ChunkPos;
51pub use chunk_section_pos::ChunkSectionPos;
52pub use decode::PacketDecoder;
53use derive_more::{From, Into};
54pub use difficulty::Difficulty;
55pub use direction::Direction;
56pub use encode::{PacketEncoder, WritePacket};
57pub use game_mode::GameMode;
58pub use global_pos::GlobalPos;
59pub use hand::Hand;
60pub use ident::ident;
61pub use item::{ItemKind, ItemStack};
62pub use packets::play::particle_s2c::Particle;
63pub use raw::RawBytes;
64use serde::{Deserialize, Serialize};
65pub use sound::Sound;
66pub use text::Text;
67pub use valence_generated::{block, packet_id, status_effects};
68pub use valence_ident::Ident;
69pub use valence_protocol_macros::{Decode, Encode, Packet};
70pub use var_int::VarInt;
71pub use var_long::VarLong;
72pub use velocity::Velocity;
73pub use {
74    anyhow, bytes, uuid, valence_ident as ident, valence_math as math, valence_nbt as nbt,
75    valence_text as text,
76};
77
78/// The maximum number of bytes in a single Minecraft packet.
79pub const MAX_PACKET_SIZE: i32 = 2097152;
80
81/// The Minecraft protocol version this library currently targets.
82pub const PROTOCOL_VERSION: i32 = 763;
83
84/// The stringified name of the Minecraft version this library currently
85/// targets.
86pub const MINECRAFT_VERSION: &str = "1.20.1";
87
88/// How large a packet should be before it is compressed by the packet encoder.
89///
90/// If the inner value is >= 0, then packets with encoded lengths >= to this
91/// value will be compressed. If the value is negative, then compression is
92/// disabled and no packets are compressed.
93#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From, Into)]
94pub struct CompressionThreshold(pub i32);
95
96impl CompressionThreshold {
97    /// No compression.
98    pub const DEFAULT: Self = Self(-1);
99}
100
101/// No compression.
102impl Default for CompressionThreshold {
103    fn default() -> Self {
104        Self::DEFAULT
105    }
106}
107
108/// The `Encode` trait allows objects to be written to the Minecraft protocol.
109/// It is the inverse of [`Decode`].
110///
111/// # Deriving
112///
113/// This trait can be implemented automatically for structs and enums by using
114/// the [`Encode`][macro] derive macro. All components of the type must
115/// implement `Encode`. Components are encoded in the order they appear in the
116/// type definition.
117///
118/// For enums, the variant to encode is marked by a leading [`VarInt`]
119/// discriminant (tag). The discriminant value can be changed using the
120/// `#[packet(tag = ...)]` attribute on the variant in question. Discriminant
121/// values are assigned to variants using rules similar to regular enum
122/// discriminants.
123///
124/// ```
125/// use valence_protocol::Encode;
126///
127/// #[derive(Encode)]
128/// struct MyStruct<'a> {
129///     first: i32,
130///     second: &'a str,
131///     third: [f64; 3],
132/// }
133///
134/// #[derive(Encode)]
135/// enum MyEnum {
136///     First,  // tag = 0
137///     Second, // tag = 1
138///     #[packet(tag = 25)]
139///     Third, // tag = 25
140///     Fourth, // tag = 26
141/// }
142///
143/// let value = MyStruct {
144///     first: 10,
145///     second: "hello",
146///     third: [1.5, 3.14, 2.718],
147/// };
148///
149/// let mut buf = vec![];
150/// value.encode(&mut buf).unwrap();
151///
152/// println!("{buf:?}");
153/// ```
154///
155/// [macro]: valence_protocol_macros::Encode
156/// [`VarInt`]: var_int::VarInt
157pub trait Encode {
158    /// Writes this object to the provided writer.
159    ///
160    /// If this type also implements [`Decode`] then successful calls to this
161    /// function returning `Ok(())` must always successfully [`decode`] using
162    /// the data that was written to the writer. The exact number of bytes
163    /// that were originally written must be consumed during the decoding.
164    ///
165    /// [`decode`]: Decode::decode
166    fn encode(&self, w: impl Write) -> anyhow::Result<()>;
167
168    /// Like [`Encode::encode`], except that a whole slice of values is encoded.
169    ///
170    /// This method must be semantically equivalent to encoding every element of
171    /// the slice in sequence with no leading length prefix (which is exactly
172    /// what the default implementation does), but a more efficient
173    /// implementation may be used.
174    ///
175    /// This method is important for some types like `u8` where the entire slice
176    /// can be encoded in a single call to [`write_all`]. Because impl
177    /// specialization is unavailable in stable Rust at the time of writing,
178    /// we must make the slice specialization part of this trait.
179    ///
180    /// [`write_all`]: Write::write_all
181    fn encode_slice(slice: &[Self], mut w: impl Write) -> anyhow::Result<()>
182    where
183        Self: Sized,
184    {
185        for value in slice {
186            value.encode(&mut w)?;
187        }
188
189        Ok(())
190    }
191}
192
193/// The `Decode` trait allows objects to be read from the Minecraft protocol. It
194/// is the inverse of [`Encode`].
195///
196/// `Decode` is parameterized by a lifetime. This allows the decoded value to
197/// borrow data from the byte slice it was read from.
198///
199/// # Deriving
200///
201/// This trait can be implemented automatically for structs and enums by using
202/// the [`Decode`][macro] derive macro. All components of the type must
203/// implement `Decode`. Components are decoded in the order they appear in the
204/// type definition.
205///
206/// For enums, the variant to decode is determined by a leading [`VarInt`]
207/// discriminant (tag). The discriminant value can be changed using the
208/// `#[packet(tag = ...)]` attribute on the variant in question. Discriminant
209/// values are assigned to variants using rules similar to regular enum
210/// discriminants.
211///
212/// ```
213/// use valence_protocol::Decode;
214///
215/// #[derive(PartialEq, Debug, Decode)]
216/// struct MyStruct {
217///     first: i32,
218///     second: MyEnum,
219/// }
220///
221/// #[derive(PartialEq, Debug, Decode)]
222/// enum MyEnum {
223///     First,  // tag = 0
224///     Second, // tag = 1
225///     #[packet(tag = 25)]
226///     Third, // tag = 25
227///     Fourth, // tag = 26
228/// }
229///
230/// let mut r: &[u8] = &[0, 0, 0, 0, 26];
231///
232/// let value = MyStruct::decode(&mut r).unwrap();
233/// let expected = MyStruct {
234///     first: 0,
235///     second: MyEnum::Fourth,
236/// };
237///
238/// assert_eq!(value, expected);
239/// assert!(r.is_empty());
240/// ```
241///
242/// [macro]: valence_protocol_macros::Decode
243/// [`VarInt`]: var_int::VarInt
244pub trait Decode<'a>: Sized {
245    /// Reads this object from the provided byte slice.
246    ///
247    /// Implementations of `Decode` are expected to shrink the slice from the
248    /// front as bytes are read.
249    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self>;
250}
251
252/// Types considered to be Minecraft packets.
253///
254/// In serialized form, a packet begins with a [`VarInt`] packet ID followed by
255/// the body of the packet. If present, the implementations of [`Encode`] and
256/// [`Decode`] on `Self` are expected to only encode/decode the _body_ of this
257/// packet without the leading ID.
258pub trait Packet: std::fmt::Debug {
259    /// The leading `VarInt` ID of this packet.
260    const ID: i32;
261    /// The name of this packet for debugging purposes.
262    const NAME: &'static str;
263    /// The side this packet is intended for.
264    const SIDE: PacketSide;
265    /// The state in which this packet is used.
266    const STATE: PacketState;
267
268    /// Encodes this packet's `VarInt` ID first, followed by the packet's body.
269    fn encode_with_id(&self, mut w: impl Write) -> anyhow::Result<()>
270    where
271        Self: Encode,
272    {
273        VarInt(Self::ID)
274            .encode(&mut w)
275            .context("failed to encode packet ID")?;
276
277        self.encode(w)
278    }
279}
280
281/// The side a packet is intended for.
282#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
283pub enum PacketSide {
284    /// Server -> Client
285    Clientbound,
286    /// Client -> Server
287    Serverbound,
288}
289
290/// The statein  which a packet is used.
291#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
292pub enum PacketState {
293    Handshaking,
294    Status,
295    Login,
296    Play,
297}
298
299#[allow(dead_code)]
300#[cfg(test)]
301mod tests {
302    use std::borrow::Cow;
303
304    use bytes::BytesMut;
305
306    use super::*;
307    use crate::block_pos::BlockPos;
308    use crate::decode::PacketDecoder;
309    use crate::encode::PacketEncoder;
310    use crate::hand::Hand;
311    use crate::item::{ItemKind, ItemStack};
312    use crate::text::{IntoText, Text};
313    use crate::var_int::VarInt;
314    use crate::var_long::VarLong;
315    use crate::Ident;
316
317    #[derive(Encode, Decode, Packet, Debug)]
318    #[packet(id = 1, side = PacketSide::Clientbound)]
319    struct RegularStruct {
320        foo: i32,
321        bar: bool,
322        baz: f64,
323    }
324
325    #[derive(Encode, Decode, Packet, Debug)]
326    #[packet(id = 2, side = PacketSide::Clientbound)]
327    struct UnitStruct;
328
329    #[derive(Encode, Decode, Packet, Debug)]
330    #[packet(id = 3, side = PacketSide::Clientbound)]
331    struct EmptyStruct;
332
333    #[derive(Encode, Decode, Packet, Debug)]
334    #[packet(id = 4, side = PacketSide::Clientbound)]
335    struct TupleStruct(i32, bool, f64);
336
337    #[derive(Encode, Decode, Packet, Debug)]
338    #[packet(id = 5, side = PacketSide::Clientbound)]
339    struct StructWithGenerics<'z, T = ()> {
340        foo: &'z str,
341        bar: T,
342    }
343
344    #[derive(Encode, Decode, Packet, Debug)]
345    #[packet(id = 6, side = PacketSide::Clientbound)]
346    struct TupleStructWithGenerics<'z, T = ()>(&'z str, i32, T);
347
348    #[allow(unconditional_recursion, clippy::extra_unused_type_parameters)]
349    fn assert_has_impls<'a, T>()
350    where
351        T: Encode + Decode<'a> + Packet,
352    {
353        assert_has_impls::<RegularStruct>();
354        assert_has_impls::<UnitStruct>();
355        assert_has_impls::<EmptyStruct>();
356        assert_has_impls::<TupleStruct>();
357        assert_has_impls::<StructWithGenerics>();
358        assert_has_impls::<TupleStructWithGenerics>();
359    }
360
361    #[test]
362    fn packet_name() {
363        assert_eq!(RegularStruct::NAME, "RegularStruct");
364        assert_eq!(UnitStruct::NAME, "UnitStruct");
365        assert_eq!(StructWithGenerics::<()>::NAME, "StructWithGenerics");
366    }
367
368    #[cfg(feature = "encryption")]
369    const CRYPT_KEY: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
370
371    #[derive(PartialEq, Debug, Encode, Decode, Packet)]
372    #[packet(id = 42, side = PacketSide::Clientbound)]
373    struct TestPacket<'a> {
374        a: bool,
375        b: u8,
376        c: i32,
377        d: f32,
378        e: f64,
379        f: BlockPos,
380        g: Hand,
381        h: Ident<Cow<'a, str>>,
382        i: ItemStack,
383        j: Text,
384        k: VarInt,
385        l: VarLong,
386        m: &'a str,
387        n: &'a [u8; 10],
388        o: [u128; 3],
389    }
390
391    impl<'a> TestPacket<'a> {
392        fn new(string: &'a str) -> Self {
393            Self {
394                a: true,
395                b: 12,
396                c: -999,
397                d: 5.001,
398                e: 1e10,
399                f: BlockPos::new(1, 2, 3),
400                g: Hand::Off,
401                h: Ident::new("minecraft:whatever").unwrap(),
402                i: ItemStack::new(ItemKind::WoodenSword, 12, None),
403                j: "my ".into_text() + "fancy".italic() + " text",
404                k: VarInt(123),
405                l: VarLong(456),
406                m: string,
407                n: &[7; 10],
408                o: [123456789; 3],
409            }
410        }
411    }
412
413    fn check_test_packet(dec: &mut PacketDecoder, string: &str) {
414        let frame = dec.try_next_packet().unwrap().unwrap();
415
416        let pkt = frame.decode::<TestPacket>().unwrap();
417
418        assert_eq!(&pkt, &TestPacket::new(string));
419    }
420
421    #[test]
422    fn packets_round_trip() {
423        let mut buf = BytesMut::new();
424
425        let mut enc = PacketEncoder::new();
426
427        enc.append_packet(&TestPacket::new("first")).unwrap();
428        #[cfg(feature = "compression")]
429        enc.set_compression(0.into());
430        enc.append_packet(&TestPacket::new("second")).unwrap();
431        buf.unsplit(enc.take());
432        #[cfg(feature = "encryption")]
433        enc.enable_encryption(&CRYPT_KEY);
434        enc.append_packet(&TestPacket::new("third")).unwrap();
435        enc.prepend_packet(&TestPacket::new("fourth")).unwrap();
436
437        buf.unsplit(enc.take());
438
439        let mut dec = PacketDecoder::new();
440
441        dec.queue_bytes(buf);
442
443        check_test_packet(&mut dec, "first");
444
445        #[cfg(feature = "compression")]
446        dec.set_compression(0.into());
447
448        check_test_packet(&mut dec, "second");
449
450        #[cfg(feature = "encryption")]
451        dec.enable_encryption(&CRYPT_KEY);
452
453        check_test_packet(&mut dec, "fourth");
454        check_test_packet(&mut dec, "third");
455    }
456}