valence_protocol/packets/play/
team_s2c.rs

1use std::borrow::Cow;
2use std::io::Write;
3
4use anyhow::bail;
5use bitfield_struct::bitfield;
6use valence_text::Text;
7
8use crate::{Decode, Encode, Packet};
9
10#[derive(Clone, Debug, Encode, Decode, Packet)]
11pub struct TeamS2c<'a> {
12    pub team_name: &'a str,
13    pub mode: Mode<'a>,
14}
15
16#[derive(Clone, PartialEq, Debug)]
17pub enum Mode<'a> {
18    CreateTeam {
19        team_display_name: Cow<'a, Text>,
20        friendly_flags: TeamFlags,
21        name_tag_visibility: NameTagVisibility,
22        collision_rule: CollisionRule,
23        team_color: TeamColor,
24        team_prefix: Cow<'a, Text>,
25        team_suffix: Cow<'a, Text>,
26        entities: Vec<&'a str>,
27    },
28    RemoveTeam,
29    UpdateTeamInfo {
30        team_display_name: Cow<'a, Text>,
31        friendly_flags: TeamFlags,
32        name_tag_visibility: NameTagVisibility,
33        collision_rule: CollisionRule,
34        team_color: TeamColor,
35        team_prefix: Cow<'a, Text>,
36        team_suffix: Cow<'a, Text>,
37    },
38    AddEntities {
39        entities: Vec<&'a str>,
40    },
41    RemoveEntities {
42        entities: Vec<&'a str>,
43    },
44}
45
46impl Encode for Mode<'_> {
47    fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
48        match self {
49            Mode::CreateTeam {
50                team_display_name,
51                friendly_flags,
52                name_tag_visibility,
53                collision_rule,
54                team_color,
55                team_prefix,
56                team_suffix,
57                entities,
58            } => {
59                0_i8.encode(&mut w)?;
60                team_display_name.encode(&mut w)?;
61                friendly_flags.encode(&mut w)?;
62                match name_tag_visibility {
63                    NameTagVisibility::Always => "always",
64                    NameTagVisibility::Never => "never",
65                    NameTagVisibility::HideForOtherTeams => "hideForOtherTeams",
66                    NameTagVisibility::HideForOwnTeam => "hideForOwnTeam",
67                }
68                .encode(&mut w)?;
69                match collision_rule {
70                    CollisionRule::Always => "always",
71                    CollisionRule::Never => "never",
72                    CollisionRule::PushOtherTeams => "pushOtherTeams",
73                    CollisionRule::PushOwnTeam => "pushOwnTeam",
74                }
75                .encode(&mut w)?;
76                team_color.encode(&mut w)?;
77                team_prefix.encode(&mut w)?;
78                team_suffix.encode(&mut w)?;
79                entities.encode(&mut w)?;
80            }
81            Mode::RemoveTeam => 1_i8.encode(&mut w)?,
82            Mode::UpdateTeamInfo {
83                team_display_name,
84                friendly_flags,
85                name_tag_visibility,
86                collision_rule,
87                team_color,
88                team_prefix,
89                team_suffix,
90            } => {
91                2_i8.encode(&mut w)?;
92                team_display_name.encode(&mut w)?;
93                friendly_flags.encode(&mut w)?;
94                match name_tag_visibility {
95                    NameTagVisibility::Always => "always",
96                    NameTagVisibility::Never => "never",
97                    NameTagVisibility::HideForOtherTeams => "hideForOtherTeams",
98                    NameTagVisibility::HideForOwnTeam => "hideForOwnTeam",
99                }
100                .encode(&mut w)?;
101                match collision_rule {
102                    CollisionRule::Always => "always",
103                    CollisionRule::Never => "never",
104                    CollisionRule::PushOtherTeams => "pushOtherTeams",
105                    CollisionRule::PushOwnTeam => "pushOwnTeam",
106                }
107                .encode(&mut w)?;
108                team_color.encode(&mut w)?;
109                team_prefix.encode(&mut w)?;
110                team_suffix.encode(&mut w)?;
111            }
112            Mode::AddEntities { entities } => {
113                3_i8.encode(&mut w)?;
114                entities.encode(&mut w)?;
115            }
116            Mode::RemoveEntities { entities } => {
117                4_i8.encode(&mut w)?;
118                entities.encode(&mut w)?;
119            }
120        }
121        Ok(())
122    }
123}
124
125impl<'a> Decode<'a> for Mode<'a> {
126    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
127        Ok(match i8::decode(r)? {
128            0 => Self::CreateTeam {
129                team_display_name: Decode::decode(r)?,
130                friendly_flags: Decode::decode(r)?,
131                name_tag_visibility: match <&str>::decode(r)? {
132                    "always" => NameTagVisibility::Always,
133                    "never" => NameTagVisibility::Never,
134                    "hideForOtherTeams" => NameTagVisibility::HideForOtherTeams,
135                    "hideForOwnTeam" => NameTagVisibility::HideForOwnTeam,
136                    other => bail!("unknown name tag visibility type \"{other}\""),
137                },
138                collision_rule: match <&str>::decode(r)? {
139                    "always" => CollisionRule::Always,
140                    "never" => CollisionRule::Never,
141                    "pushOtherTeams" => CollisionRule::PushOtherTeams,
142                    "pushOwnTeam" => CollisionRule::PushOwnTeam,
143                    other => bail!("unknown collision rule type \"{other}\""),
144                },
145                team_color: Decode::decode(r)?,
146                team_prefix: Decode::decode(r)?,
147                team_suffix: Decode::decode(r)?,
148                entities: Decode::decode(r)?,
149            },
150            1 => Self::RemoveTeam,
151            2 => Self::UpdateTeamInfo {
152                team_display_name: Decode::decode(r)?,
153                friendly_flags: Decode::decode(r)?,
154                name_tag_visibility: match <&str>::decode(r)? {
155                    "always" => NameTagVisibility::Always,
156                    "never" => NameTagVisibility::Never,
157                    "hideForOtherTeams" => NameTagVisibility::HideForOtherTeams,
158                    "hideForOwnTeam" => NameTagVisibility::HideForOwnTeam,
159                    other => bail!("unknown name tag visibility type \"{other}\""),
160                },
161                collision_rule: match <&str>::decode(r)? {
162                    "always" => CollisionRule::Always,
163                    "never" => CollisionRule::Never,
164                    "pushOtherTeams" => CollisionRule::PushOtherTeams,
165                    "pushOwnTeam" => CollisionRule::PushOwnTeam,
166                    other => bail!("unknown collision rule type \"{other}\""),
167                },
168                team_color: Decode::decode(r)?,
169                team_prefix: Decode::decode(r)?,
170                team_suffix: Decode::decode(r)?,
171            },
172            3 => Self::AddEntities {
173                entities: Decode::decode(r)?,
174            },
175            4 => Self::RemoveEntities {
176                entities: Decode::decode(r)?,
177            },
178            n => bail!("unknown update teams action of {n}"),
179        })
180    }
181}
182
183#[bitfield(u8)]
184#[derive(PartialEq, Eq, Encode, Decode)]
185pub struct TeamFlags {
186    pub friendly_fire: bool,
187    pub see_invisible_teammates: bool,
188    #[bits(6)]
189    _pad: u8,
190}
191
192#[derive(Copy, Clone, PartialEq, Eq, Debug)]
193pub enum NameTagVisibility {
194    Always,
195    Never,
196    HideForOtherTeams,
197    HideForOwnTeam,
198}
199
200#[derive(Copy, Clone, PartialEq, Eq, Debug)]
201pub enum CollisionRule {
202    Always,
203    Never,
204    PushOtherTeams,
205    PushOwnTeam,
206}
207
208#[derive(Copy, Clone, PartialEq, Eq, Debug, Encode, Decode)]
209pub enum TeamColor {
210    Black,
211    DarkBlue,
212    DarkGreen,
213    DarkCyan,
214    DarkRed,
215    Purple,
216    Gold,
217    Gray,
218    DarkGray,
219    Blue,
220    BrightGreen,
221    Cyan,
222    Red,
223    Pink,
224    Yellow,
225    White,
226    Obfuscated,
227    Bold,
228    Strikethrough,
229    Underlined,
230    Italic,
231    Reset,
232}