Skip to main content

deepslate_protocol/
version.rs

1//! Minecraft protocol version definitions.
2//!
3//! Only versions 1.21+ are supported. Each entry maps a protocol number
4//! to the Minecraft release versions that use it.
5
6/// Minecraft protocol version.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub enum ProtocolVersion {
9    /// 1.21, 1.21.1 (protocol 767)
10    V1_21,
11    /// 1.21.2, 1.21.3 (protocol 768)
12    V1_21_2,
13    /// 1.21.4 (protocol 769)
14    V1_21_4,
15    /// 1.21.5 (protocol 770)
16    V1_21_5,
17    /// 1.21.6 (protocol 771)
18    V1_21_6,
19    /// 1.21.7, 1.21.8 (protocol 772)
20    V1_21_7,
21    /// 1.21.9, 1.21.10 (protocol 773)
22    V1_21_9,
23    /// 1.21.11 (protocol 774)
24    V1_21_11,
25}
26
27impl ProtocolVersion {
28    /// The minimum supported protocol version.
29    pub const MINIMUM: Self = Self::V1_21;
30
31    /// The maximum supported protocol version.
32    pub const MAXIMUM: Self = Self::V1_21_11;
33
34    /// The minimum protocol number we accept.
35    pub const MINIMUM_PROTOCOL: i32 = 767;
36
37    /// The maximum protocol number we accept.
38    pub const MAXIMUM_PROTOCOL: i32 = 774;
39
40    /// Create a `ProtocolVersion` from a protocol number.
41    ///
42    /// Returns `None` if the protocol number is not supported.
43    #[must_use]
44    pub const fn from_protocol(protocol: i32) -> Option<Self> {
45        match protocol {
46            767 => Some(Self::V1_21),
47            768 => Some(Self::V1_21_2),
48            769 => Some(Self::V1_21_4),
49            770 => Some(Self::V1_21_5),
50            771 => Some(Self::V1_21_6),
51            772 => Some(Self::V1_21_7),
52            773 => Some(Self::V1_21_9),
53            774 => Some(Self::V1_21_11),
54            _ => None,
55        }
56    }
57
58    /// Get the protocol number for this version.
59    #[must_use]
60    pub const fn protocol(self) -> i32 {
61        match self {
62            Self::V1_21 => 767,
63            Self::V1_21_2 => 768,
64            Self::V1_21_4 => 769,
65            Self::V1_21_5 => 770,
66            Self::V1_21_6 => 771,
67            Self::V1_21_7 => 772,
68            Self::V1_21_9 => 773,
69            Self::V1_21_11 => 774,
70        }
71    }
72
73    /// Get a human-readable version string.
74    #[must_use]
75    pub const fn name(self) -> &'static str {
76        match self {
77            Self::V1_21 => "1.21-1.21.1",
78            Self::V1_21_2 => "1.21.2-1.21.3",
79            Self::V1_21_4 => "1.21.4",
80            Self::V1_21_5 => "1.21.5",
81            Self::V1_21_6 => "1.21.6",
82            Self::V1_21_7 => "1.21.7-1.21.8",
83            Self::V1_21_9 => "1.21.9-1.21.10",
84            Self::V1_21_11 => "1.21.11",
85        }
86    }
87
88    /// Check if this version is at least the given version.
89    #[must_use]
90    pub const fn at_least(self, other: Self) -> bool {
91        self.protocol() >= other.protocol()
92    }
93
94    /// The supported version range as a human-readable string.
95    pub const SUPPORTED_VERSIONS: &'static str = "1.21-1.21.11";
96}
97
98impl std::fmt::Display for ProtocolVersion {
99    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100        write!(f, "{} ({})", self.name(), self.protocol())
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107
108    #[test]
109    fn test_from_protocol() {
110        assert_eq!(
111            ProtocolVersion::from_protocol(767),
112            Some(ProtocolVersion::V1_21)
113        );
114        assert_eq!(
115            ProtocolVersion::from_protocol(774),
116            Some(ProtocolVersion::V1_21_11)
117        );
118        assert_eq!(ProtocolVersion::from_protocol(0), None);
119        assert_eq!(ProtocolVersion::from_protocol(766), None);
120        assert_eq!(ProtocolVersion::from_protocol(775), None);
121    }
122
123    #[test]
124    fn test_roundtrip() {
125        for proto in [767, 768, 769, 770, 771, 772, 773, 774] {
126            let version = ProtocolVersion::from_protocol(proto).unwrap();
127            assert_eq!(version.protocol(), proto);
128        }
129    }
130}