Skip to main content

azalea_protocol/packets/game/
c_player_info_update.rs

1use std::{
2    io::{self, Cursor, Write},
3    sync::Arc,
4};
5
6use azalea_auth::game_profile::{GameProfile, GameProfileProperties};
7use azalea_buf::{AzBuf, AzBufVar, BufReadError};
8use azalea_chat::FormattedText;
9use azalea_core::{bitset::FixedBitSet, game_type::GameMode};
10use azalea_protocol_macros::ClientboundGamePacket;
11use uuid::Uuid;
12
13use super::s_chat_session_update::RemoteChatSessionData;
14
15#[derive(ClientboundGamePacket, Clone, Debug, PartialEq)]
16pub struct ClientboundPlayerInfoUpdate {
17    pub actions: ActionEnumSet,
18    pub entries: Vec<PlayerInfoEntry>,
19}
20
21#[derive(Clone, Debug, Default, PartialEq)]
22pub struct PlayerInfoEntry {
23    pub profile: GameProfile,
24    pub listed: bool,
25    pub latency: i32,
26    pub game_mode: GameMode,
27    pub display_name: Option<Box<FormattedText>>,
28    pub list_order: i32,
29    pub update_hat: bool,
30    pub chat_session: Option<RemoteChatSessionData>,
31}
32
33#[derive(AzBuf, Clone, Debug)]
34pub struct AddPlayerAction {
35    pub name: String,
36    pub properties: GameProfileProperties,
37}
38#[derive(AzBuf, Clone, Debug)]
39pub struct InitializeChatAction {
40    pub chat_session: Option<RemoteChatSessionData>,
41}
42#[derive(AzBuf, Clone, Debug)]
43pub struct UpdateGameModeAction {
44    pub game_mode: GameMode,
45}
46#[derive(AzBuf, Clone, Debug)]
47pub struct UpdateListedAction {
48    pub listed: bool,
49}
50#[derive(AzBuf, Clone, Debug)]
51pub struct UpdateLatencyAction {
52    #[var]
53    pub latency: i32,
54}
55#[derive(AzBuf, Clone, Debug)]
56pub struct UpdateDisplayNameAction {
57    pub display_name: Option<Box<FormattedText>>,
58}
59#[derive(AzBuf, Clone, Debug)]
60pub struct UpdateHatAction {
61    pub update_hat: bool,
62}
63#[derive(AzBuf, Clone, Debug)]
64pub struct UpdateListOrderAction {
65    #[var]
66    pub list_order: i32,
67}
68
69impl AzBuf for ClientboundPlayerInfoUpdate {
70    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
71        let actions = ActionEnumSet::azalea_read(buf)?;
72        let mut entries = Vec::new();
73
74        let entry_count = u32::azalea_read_var(buf)?;
75        for _ in 0..entry_count {
76            let profile_id = Uuid::azalea_read(buf)?;
77            let mut entry = PlayerInfoEntry::default();
78            entry.profile.uuid = profile_id;
79
80            if actions.add_player {
81                let action = AddPlayerAction::azalea_read(buf)?;
82                entry.profile.name = action.name;
83                entry.profile.properties = Arc::new(action.properties);
84            }
85            if actions.initialize_chat {
86                let action = InitializeChatAction::azalea_read(buf)?;
87                entry.chat_session = action.chat_session;
88            }
89            if actions.update_game_mode {
90                let action = UpdateGameModeAction::azalea_read(buf)?;
91                entry.game_mode = action.game_mode;
92            }
93            if actions.update_listed {
94                let action = UpdateListedAction::azalea_read(buf)?;
95                entry.listed = action.listed;
96            }
97            if actions.update_latency {
98                let action = UpdateLatencyAction::azalea_read(buf)?;
99                entry.latency = action.latency;
100            }
101            if actions.update_display_name {
102                let action = UpdateDisplayNameAction::azalea_read(buf)?;
103                entry.display_name = action.display_name;
104            }
105            if actions.update_hat {
106                let action = UpdateHatAction::azalea_read(buf)?;
107                entry.update_hat = action.update_hat;
108            }
109            if actions.update_list_order {
110                let action = UpdateListOrderAction::azalea_read(buf)?;
111                entry.list_order = action.list_order;
112            }
113
114            entries.push(entry);
115        }
116
117        Ok(ClientboundPlayerInfoUpdate { actions, entries })
118    }
119    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
120        self.actions.azalea_write(buf)?;
121
122        (self.entries.len() as u32).azalea_write_var(buf)?;
123        for entry in &self.entries {
124            entry.profile.uuid.azalea_write(buf)?;
125
126            if self.actions.add_player {
127                AddPlayerAction {
128                    name: entry.profile.name.clone(),
129                    properties: (*entry.profile.properties).clone(),
130                }
131                .azalea_write(buf)?;
132            }
133            if self.actions.initialize_chat {
134                InitializeChatAction {
135                    chat_session: entry.chat_session.clone(),
136                }
137                .azalea_write(buf)?;
138            }
139            if self.actions.update_game_mode {
140                UpdateGameModeAction {
141                    game_mode: entry.game_mode,
142                }
143                .azalea_write(buf)?;
144            }
145            if self.actions.update_listed {
146                UpdateListedAction {
147                    listed: entry.listed,
148                }
149                .azalea_write(buf)?;
150            }
151            if self.actions.update_latency {
152                UpdateLatencyAction {
153                    latency: entry.latency,
154                }
155                .azalea_write(buf)?;
156            }
157            if self.actions.update_display_name {
158                UpdateDisplayNameAction {
159                    display_name: entry.display_name.clone(),
160                }
161                .azalea_write(buf)?;
162            }
163        }
164
165        Ok(())
166    }
167}
168
169#[derive(Clone, Debug, Eq, PartialEq)]
170pub struct ActionEnumSet {
171    pub add_player: bool,
172    pub initialize_chat: bool,
173    pub update_game_mode: bool,
174    pub update_listed: bool,
175    pub update_latency: bool,
176    pub update_display_name: bool,
177    pub update_hat: bool,
178    pub update_list_order: bool,
179}
180
181impl AzBuf for ActionEnumSet {
182    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
183        let set = FixedBitSet::<7>::azalea_read(buf)?;
184        Ok(ActionEnumSet {
185            add_player: set.index(0),
186            initialize_chat: set.index(1),
187            update_game_mode: set.index(2),
188            update_listed: set.index(3),
189            update_latency: set.index(4),
190            update_display_name: set.index(5),
191            update_hat: set.index(6),
192            update_list_order: set.index(7),
193        })
194    }
195    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
196        let mut set = FixedBitSet::<7>::new();
197        if self.add_player {
198            set.set(0);
199        }
200        if self.initialize_chat {
201            set.set(1);
202        }
203        if self.update_game_mode {
204            set.set(2);
205        }
206        if self.update_listed {
207            set.set(3);
208        }
209        if self.update_latency {
210            set.set(4);
211        }
212        if self.update_display_name {
213            set.set(5);
214        }
215        if self.update_hat {
216            set.set(6);
217        }
218        if self.update_list_order {
219            set.set(7);
220        }
221        set.azalea_write(buf)?;
222        Ok(())
223    }
224}
225
226#[cfg(test)]
227mod tests {
228    use super::*;
229
230    #[test]
231    fn test_action_enum_set() {
232        let data = ActionEnumSet {
233            add_player: true,
234            initialize_chat: false,
235            update_game_mode: true,
236            update_listed: false,
237            update_latency: true,
238            update_display_name: false,
239            update_hat: false,
240            update_list_order: true,
241        };
242        let mut buf = Vec::new();
243        data.azalea_write(&mut buf).unwrap();
244        let mut data_cursor: Cursor<&[u8]> = Cursor::new(&buf);
245        let read_data = ActionEnumSet::azalea_read(&mut data_cursor).unwrap();
246        assert_eq!(read_data, data);
247    }
248
249    #[test]
250    fn read_player_info_update_packet() {
251        // from wynncraft
252        let mut bytes = Cursor::new(
253            &[
254                63, 1, 196, 217, 99, 243, 221, 101, 79, 183, 167, 88, 48, 71, 25, 49, 5, 142, 5,
255                74, 66, 76, 80, 78, 1, 8, 116, 101, 120, 116, 117, 114, 101, 115, 152, 3, 101, 119,
256                111, 103, 73, 67, 74, 48, 97, 87, 49, 108, 99, 51, 82, 104, 98, 88, 65, 105, 73,
257                68, 111, 103, 77, 84, 99, 119, 77, 106, 99, 49, 78, 106, 89, 48, 77, 68, 81, 120,
258                78, 105, 119, 75, 73, 67, 65, 105, 99, 72, 74, 118, 90, 109, 108, 115, 90, 85, 108,
259                107, 73, 105, 65, 54, 73, 67, 74, 106, 78, 71, 81, 53, 78, 106, 78, 109, 77, 50,
260                82, 107, 78, 106, 85, 48, 90, 109, 73, 51, 89, 84, 99, 49, 79, 68, 77, 119, 78, 68,
261                99, 120, 79, 84, 77, 120, 77, 68, 85, 52, 90, 83, 73, 115, 67, 105, 65, 103, 73,
262                110, 66, 121, 98, 50, 90, 112, 98, 71, 86, 79, 89, 87, 49, 108, 73, 105, 65, 54,
263                73, 67, 74, 75, 81, 107, 120, 81, 84, 105, 73, 115, 67, 105, 65, 103, 73, 110, 78,
264                112, 90, 50, 53, 104, 100, 72, 86, 121, 90, 86, 74, 108, 99, 88, 86, 112, 99, 109,
265                86, 107, 73, 105, 65, 54, 73, 72, 82, 121, 100, 87, 85, 115, 67, 105, 65, 103, 73,
266                110, 82, 108, 101, 72, 82, 49, 99, 109, 86, 122, 73, 105, 65, 54, 73, 72, 115, 75,
267                73, 67, 65, 103, 73, 67, 74, 84, 83, 48, 108, 79, 73, 105, 65, 54, 73, 72, 115, 75,
268                73, 67, 65, 103, 73, 67, 65, 103, 73, 110, 86, 121, 98, 67, 73, 103, 79, 105, 65,
269                105, 97, 72, 82, 48, 99, 68, 111, 118, 76, 51, 82, 108, 101, 72, 82, 49, 99, 109,
270                86, 122, 76, 109, 49, 112, 98, 109, 86, 106, 99, 109, 70, 109, 100, 67, 53, 117,
271                90, 88, 81, 118, 100, 71, 86, 52, 100, 72, 86, 121, 90, 83, 56, 48, 79, 68, 107,
272                120, 89, 84, 107, 50, 89, 84, 74, 107, 77, 84, 103, 120, 78, 84, 69, 49, 79, 68,
273                107, 52, 78, 68, 89, 119, 77, 68, 82, 106, 77, 106, 100, 104, 78, 50, 86, 106, 77,
274                106, 85, 53, 77, 87, 77, 120, 79, 68, 66, 108, 77, 84, 70, 109, 77, 122, 104, 107,
275                89, 122, 69, 52, 77, 84, 74, 109, 77, 106, 100, 104, 77, 71, 82, 108, 78, 50, 69,
276                120, 77, 87, 85, 120, 73, 103, 111, 103, 73, 67, 65, 103, 102, 81, 111, 103, 73,
277                72, 48, 75, 102, 81, 61, 61, 1, 172, 5, 117, 69, 67, 88, 54, 83, 104, 55, 67, 100,
278                87, 49, 77, 99, 78, 88, 122, 72, 73, 105, 90, 86, 43, 103, 111, 121, 47, 120, 53,
279                102, 51, 65, 113, 119, 50, 115, 102, 114, 104, 106, 67, 118, 67, 102, 97, 54, 67,
280                112, 55, 88, 116, 109, 103, 118, 113, 73, 114, 122, 100, 85, 72, 90, 102, 79, 100,
281                100, 112, 109, 87, 70, 110, 70, 119, 97, 85, 109, 97, 76, 106, 86, 102, 121, 88,
282                119, 115, 76, 48, 78, 108, 118, 98, 56, 78, 104, 121, 115, 113, 87, 47, 104, 75,
283                120, 101, 86, 117, 90, 68, 71, 43, 102, 54, 98, 99, 98, 81, 113, 76, 79, 54, 83,
284                66, 88, 111, 81, 74, 85, 104, 74, 66, 90, 102, 88, 78, 53, 51, 100, 102, 80, 98,
285                75, 89, 81, 54, 68, 77, 57, 87, 102, 113, 81, 76, 100, 55, 121, 117, 119, 90, 81,
286                68, 55, 120, 48, 54, 118, 102, 105, 72, 121, 48, 110, 87, 50, 99, 68, 111, 72, 101,
287                71, 102, 72, 67, 53, 104, 52, 112, 84, 109, 65, 101, 100, 101, 109, 116, 48, 67,
288                72, 113, 86, 54, 76, 67, 77, 89, 118, 101, 110, 84, 88, 68, 83, 81, 107, 82, 43,
289                50, 53, 74, 76, 120, 101, 98, 74, 105, 98, 108, 54, 88, 106, 73, 118, 88, 120, 105,
290                87, 68, 121, 85, 49, 65, 43, 121, 48, 79, 104, 53, 89, 115, 116, 121, 86, 116, 106,
291                107, 76, 113, 67, 56, 85, 57, 118, 86, 110, 87, 65, 102, 111, 43, 52, 104, 78, 43,
292                79, 51, 122, 108, 72, 117, 84, 50, 87, 76, 86, 121, 98, 43, 88, 72, 100, 67, 111,
293                111, 88, 75, 82, 75, 83, 86, 71, 101, 122, 103, 75, 78, 47, 53, 65, 53, 67, 119,
294                78, 112, 82, 87, 98, 81, 55, 109, 90, 47, 108, 51, 57, 84, 114, 100, 84, 99, 54,
295                121, 79, 88, 73, 48, 56, 83, 101, 73, 54, 68, 118, 118, 50, 55, 78, 66, 112, 107,
296                47, 97, 72, 119, 65, 49, 116, 105, 78, 108, 55, 122, 49, 103, 97, 79, 107, 113,
297                107, 116, 54, 120, 85, 116, 70, 84, 85, 122, 72, 71, 97, 107, 69, 118, 105, 76, 72,
298                120, 67, 99, 106, 98, 121, 88, 111, 76, 71, 101, 101, 50, 57, 81, 84, 73, 102, 99,
299                97, 69, 56, 104, 108, 110, 73, 97, 74, 111, 115, 72, 117, 57, 116, 100, 54, 52,
300                119, 74, 88, 74, 115, 69, 78, 114, 121, 69, 56, 70, 53, 52, 52, 116, 114, 84, 54,
301                105, 112, 122, 73, 119, 43, 118, 120, 112, 76, 121, 88, 65, 87, 116, 103, 83, 113,
302                76, 108, 107, 121, 78, 50, 77, 115, 57, 74, 89, 110, 100, 79, 111, 90, 57, 77, 53,
303                84, 49, 87, 112, 75, 70, 97, 52, 55, 114, 112, 80, 106, 75, 114, 79, 107, 114, 110,
304                100, 50, 97, 83, 51, 90, 86, 77, 120, 118, 79, 49, 111, 78, 47, 100, 84, 55, 116,
305                77, 119, 82, 52, 109, 97, 55, 85, 73, 68, 50, 48, 84, 113, 105, 83, 75, 56, 108,
306                76, 85, 100, 53, 48, 86, 119, 108, 112, 67, 116, 98, 76, 99, 71, 86, 82, 98, 78,
307                84, 97, 108, 90, 83, 66, 56, 88, 65, 72, 72, 78, 100, 116, 88, 86, 50, 49, 111, 68,
308                77, 116, 77, 122, 79, 104, 82, 109, 43, 57, 88, 81, 90, 79, 50, 55, 66, 69, 71, 65,
309                47, 119, 117, 104, 113, 71, 108, 106, 82, 111, 76, 72, 111, 102, 98, 71, 48, 52,
310                82, 55, 84, 43, 80, 99, 112, 77, 116, 65, 69, 105, 49, 100, 57, 99, 66, 90, 115,
311                119, 84, 105, 107, 113, 114, 89, 49, 86, 49, 48, 106, 104, 77, 76, 118, 99, 99, 78,
312                50, 109, 70, 43, 89, 86, 81, 101, 48, 90, 55, 43, 78, 100, 119, 119, 104, 121, 47,
313                108, 79, 72, 81, 54, 71, 108, 122, 74, 110, 87, 122, 103, 50, 107, 61, 0, 255, 255,
314                255, 255, 15, 1, 255, 255, 255, 255, 15, 1, 10, 8, 0, 4, 116, 101, 120, 116, 0, 0,
315                0,
316            ][..],
317        );
318        let _packet = ClientboundPlayerInfoUpdate::azalea_read(&mut bytes).unwrap();
319    }
320}