valence_protocol/packets/play/
player_list_s2c.rs

1use std::borrow::Cow;
2use std::io::Write;
3
4use bitfield_struct::bitfield;
5use uuid::Uuid;
6use valence_text::Text;
7
8use crate::profile::Property;
9use crate::{Decode, Encode, GameMode, Packet, VarInt};
10
11#[derive(Clone, Debug, Packet)]
12pub struct PlayerListS2c<'a> {
13    pub actions: PlayerListActions,
14    pub entries: Cow<'a, [PlayerListEntry<'a>]>,
15}
16
17impl Encode for PlayerListS2c<'_> {
18    fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
19        self.actions.0.encode(&mut w)?;
20
21        // Write number of entries.
22        VarInt(self.entries.len() as i32).encode(&mut w)?;
23
24        for entry in self.entries.as_ref() {
25            entry.player_uuid.encode(&mut w)?;
26
27            if self.actions.add_player() {
28                entry.username.encode(&mut w)?;
29                entry.properties.encode(&mut w)?;
30            }
31
32            if self.actions.initialize_chat() {
33                entry.chat_data.encode(&mut w)?;
34            }
35
36            if self.actions.update_game_mode() {
37                entry.game_mode.encode(&mut w)?;
38            }
39
40            if self.actions.update_listed() {
41                entry.listed.encode(&mut w)?;
42            }
43
44            if self.actions.update_latency() {
45                VarInt(entry.ping).encode(&mut w)?;
46            }
47
48            if self.actions.update_display_name() {
49                entry.display_name.encode(&mut w)?;
50            }
51        }
52
53        Ok(())
54    }
55}
56
57impl<'a> Decode<'a> for PlayerListS2c<'a> {
58    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
59        let actions = PlayerListActions(u8::decode(r)?);
60
61        let mut entries = vec![];
62
63        for _ in 0..VarInt::decode(r)?.0 {
64            let mut entry = PlayerListEntry {
65                player_uuid: Uuid::decode(r)?,
66                ..Default::default()
67            };
68
69            if actions.add_player() {
70                entry.username = Decode::decode(r)?;
71                entry.properties = Decode::decode(r)?;
72            }
73
74            if actions.initialize_chat() {
75                entry.chat_data = Decode::decode(r)?;
76            }
77
78            if actions.update_game_mode() {
79                entry.game_mode = Decode::decode(r)?;
80            }
81
82            if actions.update_listed() {
83                entry.listed = Decode::decode(r)?;
84            }
85
86            if actions.update_latency() {
87                entry.ping = VarInt::decode(r)?.0;
88            }
89
90            if actions.update_display_name() {
91                entry.display_name = Decode::decode(r)?;
92            }
93
94            entries.push(entry);
95        }
96
97        Ok(Self {
98            actions,
99            entries: entries.into(),
100        })
101    }
102}
103
104#[bitfield(u8)]
105pub struct PlayerListActions {
106    pub add_player: bool,
107    pub initialize_chat: bool,
108    pub update_game_mode: bool,
109    pub update_listed: bool,
110    pub update_latency: bool,
111    pub update_display_name: bool,
112    #[bits(2)]
113    _pad: u8,
114}
115
116#[derive(Clone, Default, Debug)]
117pub struct PlayerListEntry<'a> {
118    pub player_uuid: Uuid,
119    pub username: &'a str,
120    pub properties: Cow<'a, [Property]>,
121    pub chat_data: Option<ChatData<'a>>,
122    pub listed: bool,
123    pub ping: i32,
124    pub game_mode: GameMode,
125    pub display_name: Option<Cow<'a, Text>>,
126}
127
128#[derive(Clone, PartialEq, Debug, Encode, Decode)]
129pub struct ChatData<'a> {
130    pub session_id: Uuid,
131    /// Unix timestamp in milliseconds.
132    pub key_expiry_time: i64,
133    pub public_key: &'a [u8],
134    pub public_key_signature: &'a [u8],
135}