steel_registry/data_components/components/
rarity.rs1use std::io::{Cursor, Result, Write};
4
5use simdnbt::owned::NbtTag;
6use simdnbt::{FromNbtTag, ToNbtTag};
7use steel_utils::codec::VarInt;
8use steel_utils::hash::{ComponentHasher, HashComponent};
9use steel_utils::serial::{ReadFrom, WriteTo};
10use text_components::format::Color;
11
12#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
14pub enum Rarity {
15 #[default]
16 Common,
17 Uncommon,
18 Rare,
19 Epic,
20}
21
22impl Rarity {
23 #[must_use]
24 pub const fn serialized_name(self) -> &'static str {
25 match self {
26 Self::Common => "common",
27 Self::Uncommon => "uncommon",
28 Self::Rare => "rare",
29 Self::Epic => "epic",
30 }
31 }
32
33 #[must_use]
34 pub const fn color(self) -> Color {
35 match self {
36 Self::Common => Color::White,
37 Self::Uncommon => Color::Yellow,
38 Self::Rare => Color::Aqua,
39 Self::Epic => Color::LightPurple,
40 }
41 }
42
43 const fn network_id(self) -> i32 {
44 match self {
45 Self::Common => 0,
46 Self::Uncommon => 1,
47 Self::Rare => 2,
48 Self::Epic => 3,
49 }
50 }
51
52 const fn from_network_id(id: i32) -> Self {
53 match id {
54 1 => Self::Uncommon,
55 2 => Self::Rare,
56 3 => Self::Epic,
57 _ => Self::Common,
58 }
59 }
60
61 const fn from_serialized_name(name: &str) -> Option<Self> {
62 match name {
63 "common" => Some(Self::Common),
64 "uncommon" => Some(Self::Uncommon),
65 "rare" => Some(Self::Rare),
66 "epic" => Some(Self::Epic),
67 _ => None,
68 }
69 }
70}
71
72impl WriteTo for Rarity {
73 fn write(&self, writer: &mut impl Write) -> Result<()> {
74 VarInt(self.network_id()).write(writer)
75 }
76}
77
78impl ReadFrom for Rarity {
79 fn read(data: &mut Cursor<&[u8]>) -> Result<Self> {
80 Ok(Self::from_network_id(VarInt::read(data)?.0))
81 }
82}
83
84impl ToNbtTag for Rarity {
85 fn to_nbt_tag(self) -> NbtTag {
86 self.serialized_name().to_nbt_tag()
87 }
88}
89
90impl FromNbtTag for Rarity {
91 fn from_nbt_tag(tag: simdnbt::borrow::NbtTag) -> Option<Self> {
92 Self::from_serialized_name(&tag.string()?.to_str())
93 }
94}
95
96impl HashComponent for Rarity {
97 fn hash_component(&self, hasher: &mut ComponentHasher) {
98 hasher.put_string(self.serialized_name());
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use std::io::Cursor;
105
106 use steel_utils::codec::VarInt;
107 use steel_utils::serial::{ReadFrom as _, WriteTo as _};
108
109 use super::Rarity;
110
111 #[test]
112 fn network_ids_match_vanilla_and_fall_back_to_common() {
113 for (rarity, expected_id) in [
114 (Rarity::Common, 0),
115 (Rarity::Uncommon, 1),
116 (Rarity::Rare, 2),
117 (Rarity::Epic, 3),
118 ] {
119 let mut encoded = Vec::new();
120 rarity.write(&mut encoded).expect("rarity should encode");
121 let mut cursor = Cursor::new(encoded.as_slice());
122 assert_eq!(
123 VarInt::read(&mut cursor).expect("id should decode").0,
124 expected_id
125 );
126 }
127
128 for id in [-1, 4, i32::MAX] {
129 let mut encoded = Vec::new();
130 VarInt(id).write(&mut encoded).expect("id should encode");
131 assert_eq!(
132 Rarity::read(&mut Cursor::new(encoded.as_slice())).expect("rarity should decode"),
133 Rarity::Common
134 );
135 }
136 }
137}