azalea_protocol/packets/game/
c_player_info_update.rs

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