valence_server/
client_settings.rs

1use bevy_app::prelude::*;
2use bevy_ecs::prelude::*;
3use valence_entity::player::{self, PlayerModelParts};
4use valence_protocol::packets::play::client_settings_c2s::ChatMode;
5use valence_protocol::packets::play::ClientSettingsC2s;
6
7use crate::client::ViewDistance;
8use crate::event_loop::{EventLoopPreUpdate, PacketEvent};
9
10pub struct ClientSettingsPlugin;
11
12impl Plugin for ClientSettingsPlugin {
13    fn build(&self, app: &mut App) {
14        app.add_systems(EventLoopPreUpdate, handle_client_settings);
15    }
16}
17
18/// Component containing client-controlled settings about a client.
19#[derive(Component, Default, Debug)]
20pub struct ClientSettings {
21    pub locale: Box<str>,
22    pub chat_mode: ChatMode,
23    pub chat_colors: bool,
24    pub enable_text_filtering: bool,
25    pub allow_server_listings: bool,
26}
27
28fn handle_client_settings(
29    mut packets: EventReader<PacketEvent>,
30    mut clients: Query<(
31        &mut ViewDistance,
32        &mut ClientSettings,
33        &mut PlayerModelParts,
34        &mut player::MainArm,
35    )>,
36) {
37    for packet in packets.read() {
38        if let Some(pkt) = packet.decode::<ClientSettingsC2s>() {
39            if let Ok((mut view_dist, mut settings, mut model_parts, mut main_arm)) =
40                clients.get_mut(packet.client)
41            {
42                view_dist.set_if_neq(ViewDistance::new(pkt.view_distance));
43
44                settings.locale = pkt.locale.into();
45                settings.chat_mode = pkt.chat_mode;
46                settings.chat_colors = pkt.chat_colors;
47                settings.enable_text_filtering = pkt.enable_text_filtering;
48                settings.allow_server_listings = pkt.allow_server_listings;
49
50                model_parts.set_if_neq(PlayerModelParts(u8::from(pkt.displayed_skin_parts) as i8));
51                main_arm.set_if_neq(player::MainArm(pkt.main_arm as i8));
52            }
53        }
54    }
55}