Skip to main content

oxidized_mc_types/
difficulty.rs

1//! [`Difficulty`] — the difficulty level of the game.
2//!
3//! Maps to the vanilla `Difficulty` enum used in server-properties,
4//! login/join-game packets, and difficulty-change packets.
5
6/// The difficulty level of the game.
7///
8/// # Wire format
9///
10/// Encoded as a VarInt (0–3).
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12#[repr(i32)]
13pub enum Difficulty {
14    /// Peaceful — no hostile mobs, health regenerates.
15    Peaceful = 0,
16    /// Easy — hostile mobs deal less damage.
17    Easy = 1,
18    /// Normal — default difficulty.
19    Normal = 2,
20    /// Hard — hostile mobs deal more damage, hunger can kill.
21    Hard = 3,
22}
23
24impl_protocol_enum! {
25    Difficulty {
26        Peaceful = 0 => "peaceful",
27        Easy     = 1 => "easy",
28        Normal   = 2 => "normal",
29        Hard     = 3 => "hard",
30    }
31}
32
33#[cfg(test)]
34#[allow(clippy::unwrap_used, clippy::expect_used)]
35mod tests {
36    use bytes::BytesMut;
37
38    use super::*;
39
40    // ── by_id ───────────────────────────────────────────────────────
41
42    #[test]
43    fn test_difficulty_by_id_valid() {
44        assert_eq!(Difficulty::by_id(0), Some(Difficulty::Peaceful));
45        assert_eq!(Difficulty::by_id(1), Some(Difficulty::Easy));
46        assert_eq!(Difficulty::by_id(2), Some(Difficulty::Normal));
47        assert_eq!(Difficulty::by_id(3), Some(Difficulty::Hard));
48    }
49
50    #[test]
51    fn test_difficulty_by_id_invalid() {
52        assert_eq!(Difficulty::by_id(-1), None);
53        assert_eq!(Difficulty::by_id(4), None);
54        assert_eq!(Difficulty::by_id(100), None);
55    }
56
57    // ── by_name ─────────────────────────────────────────────────────
58
59    #[test]
60    fn test_difficulty_by_name_valid() {
61        assert_eq!(Difficulty::by_name("peaceful"), Some(Difficulty::Peaceful));
62        assert_eq!(Difficulty::by_name("easy"), Some(Difficulty::Easy));
63        assert_eq!(Difficulty::by_name("normal"), Some(Difficulty::Normal));
64        assert_eq!(Difficulty::by_name("hard"), Some(Difficulty::Hard));
65    }
66
67    #[test]
68    fn test_difficulty_by_name_invalid() {
69        assert_eq!(Difficulty::by_name("Peaceful"), None);
70        assert_eq!(Difficulty::by_name("unknown"), None);
71        assert_eq!(Difficulty::by_name(""), None);
72    }
73
74    // ── Display ─────────────────────────────────────────────────────
75
76    #[test]
77    fn test_difficulty_display() {
78        assert_eq!(format!("{}", Difficulty::Peaceful), "peaceful");
79        assert_eq!(format!("{}", Difficulty::Easy), "easy");
80        assert_eq!(format!("{}", Difficulty::Normal), "normal");
81        assert_eq!(format!("{}", Difficulty::Hard), "hard");
82    }
83
84    // ── Roundtrip ───────────────────────────────────────────────────
85
86    #[test]
87    fn test_difficulty_id_roundtrip() {
88        for id in 0..=3 {
89            let d = Difficulty::by_id(id).unwrap();
90            assert_eq!(d.id(), id);
91        }
92    }
93
94    // ── Wire roundtrip ──────────────────────────────────────────────
95
96    #[test]
97    fn test_difficulty_wire_roundtrip() {
98        for id in 0..=3 {
99            let d = Difficulty::by_id(id).unwrap();
100            let mut buf = BytesMut::new();
101            d.write(&mut buf);
102            let mut data = buf.freeze();
103            let decoded = Difficulty::read(&mut data).unwrap();
104            assert_eq!(decoded, d);
105        }
106    }
107}