azalea_client/packet_handling/
configuration.rsuse std::io::Cursor;
use azalea_entity::indexing::EntityIdIndex;
use azalea_protocol::packets::configuration::serverbound_finish_configuration_packet::ServerboundFinishConfigurationPacket;
use azalea_protocol::packets::configuration::serverbound_keep_alive_packet::ServerboundKeepAlivePacket;
use azalea_protocol::packets::configuration::serverbound_pong_packet::ServerboundPongPacket;
use azalea_protocol::packets::configuration::serverbound_resource_pack_packet::ServerboundResourcePackPacket;
use azalea_protocol::packets::configuration::serverbound_select_known_packs_packet::ServerboundSelectKnownPacksPacket;
use azalea_protocol::packets::configuration::{
ClientboundConfigurationPacket, ServerboundConfigurationPacket,
};
use azalea_protocol::packets::ConnectionProtocol;
use azalea_protocol::read::deserialize_packet;
use bevy_ecs::prelude::*;
use bevy_ecs::system::SystemState;
use tracing::{debug, error, warn};
use crate::client::InConfigurationState;
use crate::disconnect::DisconnectEvent;
use crate::local_player::Hunger;
use crate::packet_handling::game::KeepAliveEvent;
use crate::raw_connection::RawConnection;
use crate::InstanceHolder;
#[derive(Event, Debug, Clone)]
pub struct ConfigurationPacketEvent {
pub entity: Entity,
pub packet: ClientboundConfigurationPacket,
}
pub fn send_packet_events(
query: Query<(Entity, &RawConnection), With<InConfigurationState>>,
mut packet_events: ResMut<Events<ConfigurationPacketEvent>>,
) {
packet_events.clear();
for (player_entity, raw_connection) in &query {
let packets_lock = raw_connection.incoming_packet_queue();
let mut packets = packets_lock.lock();
if !packets.is_empty() {
for raw_packet in packets.iter() {
let packet = match deserialize_packet::<ClientboundConfigurationPacket>(
&mut Cursor::new(raw_packet),
) {
Ok(packet) => packet,
Err(err) => {
error!("failed to read packet: {:?}", err);
debug!("packet bytes: {:?}", raw_packet);
continue;
}
};
packet_events.send(ConfigurationPacketEvent {
entity: player_entity,
packet,
});
}
packets.clear();
}
}
}
pub fn process_packet_events(ecs: &mut World) {
let mut events_owned = Vec::new();
let mut system_state: SystemState<EventReader<ConfigurationPacketEvent>> =
SystemState::new(ecs);
let mut events = system_state.get_mut(ecs);
for ConfigurationPacketEvent {
entity: player_entity,
packet,
} in events.read()
{
events_owned.push((*player_entity, packet.clone()));
}
for (player_entity, packet) in events_owned {
match packet {
ClientboundConfigurationPacket::RegistryData(p) => {
let mut system_state: SystemState<Query<&mut InstanceHolder>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let instance_holder = query.get_mut(player_entity).unwrap();
let mut instance = instance_holder.instance.write();
instance.registries.append(p.registry_id, p.entries);
}
ClientboundConfigurationPacket::CustomPayload(p) => {
debug!("Got custom payload packet {p:?}");
}
ClientboundConfigurationPacket::Disconnect(p) => {
warn!("Got disconnect packet {p:?}");
let mut system_state: SystemState<EventWriter<DisconnectEvent>> =
SystemState::new(ecs);
let mut disconnect_events = system_state.get_mut(ecs);
disconnect_events.send(DisconnectEvent {
entity: player_entity,
reason: Some(p.reason.clone()),
});
}
ClientboundConfigurationPacket::FinishConfiguration(p) => {
debug!("got FinishConfiguration packet: {p:?}");
let mut system_state: SystemState<Query<&mut RawConnection>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let mut raw_connection = query.get_mut(player_entity).unwrap();
raw_connection
.write_packet(ServerboundFinishConfigurationPacket {}.get())
.expect(
"we should be in the right state and encoding this packet shouldn't fail",
);
raw_connection.set_state(ConnectionProtocol::Game);
ecs.entity_mut(player_entity)
.remove::<InConfigurationState>()
.insert(crate::JoinedClientBundle {
physics_state: crate::PhysicsState::default(),
inventory: crate::inventory::Inventory::default(),
tab_list: crate::local_player::TabList::default(),
current_sequence_number: crate::interact::CurrentSequenceNumber::default(),
last_sent_direction: crate::movement::LastSentLookDirection::default(),
abilities: crate::local_player::PlayerAbilities::default(),
permission_level: crate::local_player::PermissionLevel::default(),
hunger: Hunger::default(),
chunk_batch_info: crate::chunks::ChunkBatchInfo::default(),
entity_id_index: EntityIdIndex::default(),
mining: crate::mining::MineBundle::default(),
attack: crate::attack::AttackBundle::default(),
_local_entity: azalea_entity::LocalEntity,
});
}
ClientboundConfigurationPacket::KeepAlive(p) => {
debug!("Got keep alive packet (in configuration) {p:?} for {player_entity:?}");
let mut system_state: SystemState<(
Query<&RawConnection>,
EventWriter<KeepAliveEvent>,
)> = SystemState::new(ecs);
let (query, mut keepalive_events) = system_state.get_mut(ecs);
let raw_connection = query.get(player_entity).unwrap();
keepalive_events.send(KeepAliveEvent {
entity: player_entity,
id: p.id,
});
raw_connection
.write_packet(ServerboundKeepAlivePacket { id: p.id }.get())
.unwrap();
}
ClientboundConfigurationPacket::Ping(p) => {
debug!("Got ping packet {p:?}");
let mut system_state: SystemState<Query<&RawConnection>> = SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let raw_connection = query.get_mut(player_entity).unwrap();
raw_connection
.write_packet(ServerboundPongPacket { id: p.id }.get())
.unwrap();
}
ClientboundConfigurationPacket::ResourcePackPush(p) => {
debug!("Got resource pack packet {p:?}");
let mut system_state: SystemState<Query<&RawConnection>> = SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let raw_connection = query.get_mut(player_entity).unwrap();
raw_connection.write_packet(
ServerboundResourcePackPacket {
id: p.id,
action: azalea_protocol::packets::configuration::serverbound_resource_pack_packet::Action::Accepted
}.get()
).unwrap();
}
ClientboundConfigurationPacket::ResourcePackPop(_) => {
}
ClientboundConfigurationPacket::UpdateEnabledFeatures(p) => {
debug!("Got update enabled features packet {p:?}");
}
ClientboundConfigurationPacket::UpdateTags(_p) => {
debug!("Got update tags packet");
}
ClientboundConfigurationPacket::CookieRequest(p) => {
debug!("Got cookie request packet {p:?}");
}
ClientboundConfigurationPacket::ResetChat(p) => {
debug!("Got reset chat packet {p:?}");
}
ClientboundConfigurationPacket::StoreCookie(p) => {
debug!("Got store cookie packet {p:?}");
}
ClientboundConfigurationPacket::Transfer(p) => {
debug!("Got transfer packet {p:?}");
}
ClientboundConfigurationPacket::SelectKnownPacks(p) => {
debug!("Got select known packs packet {p:?}");
let mut system_state: SystemState<Query<&RawConnection>> = SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let raw_connection = query.get_mut(player_entity).unwrap();
raw_connection
.write_packet(
ServerboundSelectKnownPacksPacket {
known_packs: vec![],
}
.get(),
)
.unwrap();
}
}
}
}
#[derive(Event)]
pub struct SendConfigurationPacketEvent {
pub entity: Entity,
pub packet: ServerboundConfigurationPacket,
}
pub fn handle_send_packet_event(
mut send_packet_events: EventReader<SendConfigurationPacketEvent>,
mut query: Query<&mut RawConnection>,
) {
for event in send_packet_events.read() {
if let Ok(raw_connection) = query.get_mut(event.entity) {
if let Err(e) = raw_connection.write_packet(event.packet.clone()) {
error!("Failed to send packet: {e}");
}
}
}
}