chunkedge_protocol/packets/play/
update_advancements_s2c.rs

1// TODO: simplify this and bound packet fields where appropriate.
2
3use std::borrow::Cow;
4use std::io::Write;
5
6use chunkedge_binary::{Decode, Encode, TextComponent, VarInt};
7use chunkedge_generated::packet_id;
8use chunkedge_ident::Ident;
9use chunkedge_item::ItemStack;
10
11use crate::Packet;
12
13pub type UpdateAdvancementsS2c<'a> =
14    GenericUpdateAdvancementsS2c<'a, (Ident<Cow<'a, str>>, Advancement<'a, ItemStack>)>;
15
16#[derive(Clone, Debug, Encode, Decode, Packet)]
17#[packet(id = packet_id::PLAY_UPDATE_ADVANCEMENTS_S2C)]
18pub struct GenericUpdateAdvancementsS2c<'a, AM: 'a> {
19    pub reset: bool,
20    pub advancement_mapping: Vec<AM>,
21    pub identifiers: Vec<Ident<Cow<'a, str>>>,
22    pub progress_mapping: Vec<(Ident<Cow<'a, str>>, Vec<AdvancementCriteria<'a>>)>,
23    pub show_advancements: bool,
24}
25
26#[derive(Clone, PartialEq, Debug, Encode, Decode)]
27pub struct Advancement<'a, I> {
28    pub parent_id: Option<Ident<Cow<'a, str>>>,
29    pub display_data: Option<AdvancementDisplay<'a, I>>,
30    pub requirements: Vec<AdvancementRequirements<'a>>,
31    pub sends_telemetry_data: bool,
32}
33
34#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
35pub struct AdvancementRequirements<'a> {
36    pub requirement: Vec<&'a str>,
37}
38
39#[derive(Clone, PartialEq, Debug)]
40pub struct AdvancementDisplay<'a, I> {
41    pub title: Cow<'a, TextComponent>,
42    pub description: Cow<'a, TextComponent>,
43    pub icon: I,
44    pub frame_type: VarInt,
45    pub flags: i32,
46    pub background_texture: Option<Ident<Cow<'a, str>>>,
47    pub x_coord: f32,
48    pub y_coord: f32,
49}
50
51#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
52pub struct AdvancementCriteria<'a> {
53    pub criterion_identifier: Ident<Cow<'a, str>>,
54    /// If present, the criteria has been achieved at the
55    /// time wrapped; time represented as millis since epoch
56    pub criterion_progress: Option<i64>,
57}
58
59impl<I: Encode> Encode for AdvancementDisplay<'_, I> {
60    fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
61        self.title.encode(&mut w)?;
62        self.description.encode(&mut w)?;
63        self.icon.encode(&mut w)?;
64        self.frame_type.encode(&mut w)?;
65        self.flags.encode(&mut w)?;
66
67        match self.background_texture.as_ref() {
68            None => {}
69            Some(texture) => texture.encode(&mut w)?,
70        }
71
72        self.x_coord.encode(&mut w)?;
73        self.y_coord.encode(&mut w)?;
74
75        Ok(())
76    }
77}
78
79impl<'a, I: Decode<'a>> Decode<'a> for AdvancementDisplay<'a, I> {
80    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
81        let title = <Cow<'a, TextComponent>>::decode(r)?;
82        let description = <Cow<'a, TextComponent>>::decode(r)?;
83        let icon = I::decode(r)?;
84        let frame_type = VarInt::decode(r)?;
85        let flags = i32::decode(r)?;
86
87        let background_texture = if flags & 1 == 1 {
88            Some(Ident::decode(r)?)
89        } else {
90            None
91        };
92
93        let x_coord = f32::decode(r)?;
94        let y_coord = f32::decode(r)?;
95
96        Ok(Self {
97            title,
98            description,
99            icon,
100            frame_type,
101            flags,
102            background_texture,
103            x_coord,
104            y_coord,
105        })
106    }
107}