chunkedge_server/
client_settings.rs

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