azalea_client/plugins/
brand.rs

1use azalea_buf::AzaleaWrite;
2use azalea_core::resource_location::ResourceLocation;
3use azalea_protocol::{
4    common::client_information::ClientInformation,
5    packets::config::{
6        s_client_information::ServerboundClientInformation,
7        s_custom_payload::ServerboundCustomPayload,
8    },
9};
10use bevy_app::prelude::*;
11use bevy_ecs::prelude::*;
12use tracing::{debug, warn};
13
14use super::packet::config::SendConfigPacketEvent;
15use crate::packet::login::InLoginState;
16
17pub struct BrandPlugin;
18impl Plugin for BrandPlugin {
19    fn build(&self, app: &mut App) {
20        app.add_systems(Update, handle_end_login_state);
21    }
22}
23
24pub fn handle_end_login_state(
25    mut commands: Commands,
26    mut removed: RemovedComponents<InLoginState>,
27    query: Query<&ClientInformation>,
28) {
29    for entity in removed.read() {
30        let mut brand_data = Vec::new();
31        // azalea pretends to be vanilla everywhere else so it makes sense to lie here
32        // too
33        "vanilla".azalea_write(&mut brand_data).unwrap();
34        commands.trigger(SendConfigPacketEvent::new(
35            entity,
36            ServerboundCustomPayload {
37                identifier: ResourceLocation::new("brand"),
38                data: brand_data.into(),
39            },
40        ));
41
42        let client_information = match query.get(entity).ok() {
43            Some(i) => i,
44            None => {
45                warn!(
46                    "ClientInformation component was not set before leaving login state, using a default"
47                );
48                &ClientInformation::default()
49            }
50        };
51
52        debug!("Writing ClientInformation while in config state: {client_information:?}");
53        commands.trigger(SendConfigPacketEvent::new(
54            entity,
55            ServerboundClientInformation {
56                information: client_information.clone(),
57            },
58        ));
59    }
60}