Skip to main content

steel_registry/data_components/components/
ominous_bottle_amplifier.rs

1//! Vanilla `minecraft:ominous_bottle_amplifier` item component.
2
3use 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::nbt::NbtNumeric as _;
10use steel_utils::serial::{ReadFrom, WriteTo};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct OminousBottleAmplifier {
14    value: i32,
15}
16
17impl OminousBottleAmplifier {
18    pub const EFFECT_DURATION: i32 = 120_000;
19    pub const MIN_AMPLIFIER: i32 = 0;
20    pub const MAX_AMPLIFIER: i32 = 4;
21
22    #[must_use]
23    pub const fn new(value: i32) -> Self {
24        Self { value }
25    }
26
27    #[must_use]
28    pub const fn value(self) -> i32 {
29        self.value
30    }
31}
32
33impl WriteTo for OminousBottleAmplifier {
34    fn write(&self, writer: &mut impl Write) -> Result<()> {
35        VarInt(self.value).write(writer)
36    }
37}
38
39impl ReadFrom for OminousBottleAmplifier {
40    fn read(data: &mut Cursor<&[u8]>) -> Result<Self> {
41        Ok(Self::new(VarInt::read(data)?.0))
42    }
43}
44
45impl ToNbtTag for OminousBottleAmplifier {
46    fn to_nbt_tag(self) -> NbtTag {
47        NbtTag::Int(self.value)
48    }
49}
50
51impl FromNbtTag for OminousBottleAmplifier {
52    fn from_nbt_tag(tag: simdnbt::borrow::NbtTag<'_, '_>) -> Option<Self> {
53        let value = tag.codec_i32()?;
54        (Self::MIN_AMPLIFIER..=Self::MAX_AMPLIFIER)
55            .contains(&value)
56            .then(|| Self::new(value))
57    }
58}
59
60impl HashComponent for OminousBottleAmplifier {
61    fn hash_component(&self, hasher: &mut ComponentHasher) {
62        hasher.put_int(self.value);
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use std::io::Cursor;
69
70    use simdnbt::FromNbtTag as _;
71    use simdnbt::borrow::read_tag;
72    use simdnbt::owned::NbtTag;
73    use steel_utils::codec::VarInt;
74    use steel_utils::serial::{ReadFrom as _, WriteTo as _};
75
76    use super::OminousBottleAmplifier;
77
78    fn parse(tag: NbtTag) -> Option<OminousBottleAmplifier> {
79        let mut bytes = Vec::new();
80        tag.write(&mut bytes);
81        let borrowed = read_tag(&mut Cursor::new(bytes.as_slice())).ok()?;
82        OminousBottleAmplifier::from_nbt_tag(borrowed.as_tag())
83    }
84
85    #[test]
86    fn persistent_codec_enforces_vanilla_range() {
87        assert_eq!(parse(NbtTag::Byte(0)), Some(OminousBottleAmplifier::new(0)));
88        assert_eq!(parse(NbtTag::Long(4)), Some(OminousBottleAmplifier::new(4)));
89        assert_eq!(parse(NbtTag::Int(-1)), None);
90        assert_eq!(parse(NbtTag::Int(5)), None);
91    }
92
93    #[test]
94    fn network_codec_accepts_any_varint_like_vanilla_constructor() {
95        for value in [-1, 0, 4, 5, i32::MAX] {
96            let mut encoded = Vec::new();
97            VarInt(value)
98                .write(&mut encoded)
99                .expect("amplifier should encode");
100            assert_eq!(
101                OminousBottleAmplifier::read(&mut Cursor::new(encoded.as_slice()))
102                    .expect("amplifier should decode"),
103                OminousBottleAmplifier::new(value)
104            );
105        }
106    }
107}