From 7b3e2e4bf793466a351510c7fbbd08234e93bb0e Mon Sep 17 00:00:00 2001 From: mat <27899617+mat-1@users.noreply.github.com> Date: Thu, 21 Sep 2023 11:16:29 -0500 Subject: 1.20.2 (#99) * add configuration state * start updating to 23w31a * implement a bit more of 23w31a * chunk batching * start adding configuration state * ioasfhjgsd * almost works * configuration state mostly implemented * handle other packets in configuration state and fix keepalive * cleanup, fix warnings * 23w32a * fix some doctests * 23w33a * 23w35a * 1.20.2-pre2 * fix system conflicts * 1.20.2-pre4 * make tests compile * tests pass * 1.20.2-rc2 * 1.20.2 * Revert "1.20.2" This reverts commit dd152fd265332ead333c919e585ded6d609d7468. * didn't mean to commit that code --------- Co-authored-by: mat --- azalea-client/src/local_player.rs | 133 +++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 60 deletions(-) (limited to 'azalea-client/src/local_player.rs') diff --git a/azalea-client/src/local_player.rs b/azalea-client/src/local_player.rs index 1bcb0948..2989f36e 100644 --- a/azalea-client/src/local_player.rs +++ b/azalea-client/src/local_player.rs @@ -1,51 +1,40 @@ -use std::{io, sync::Arc}; +use std::{collections::HashMap, io, sync::Arc}; use azalea_auth::game_profile::GameProfile; use azalea_core::GameMode; use azalea_entity::Dead; -use azalea_protocol::packets::game::ServerboundGamePacket; +use azalea_protocol::packets::game::{ + clientbound_player_abilities_packet::ClientboundPlayerAbilitiesPacket, ServerboundGamePacket, +}; use azalea_world::{Instance, PartialInstance}; use bevy_ecs::{ - component::Component, entity::Entity, event::EventReader, prelude::Event, query::Added, + component::Component, entity::Entity, event::EventReader, prelude::*, query::Added, system::Query, }; use derive_more::{Deref, DerefMut}; +use log::error; use parking_lot::RwLock; use thiserror::Error; -use tokio::{sync::mpsc, task::JoinHandle}; +use tokio::sync::mpsc; +use uuid::Uuid; use crate::{ events::{Event as AzaleaEvent, LocalPlayerEvents}, - ClientInformation, + raw_connection::RawConnection, + ClientInformation, PlayerInfo, }; -/// This is a component for our local player entities that are probably in a -/// world. If you have access to a [`Client`], you probably don't need to care -/// about this since `Client` gives you access to everything here. -/// -/// You can also use the [`LocalEntity`] marker component for queries if you're -/// only checking for a local player and don't need the contents of this -/// component. -/// -/// [`LocalEntity`]: azalea_entity::LocalEntity -/// [`Client`]: crate::Client +/// A component that keeps strong references to our [`PartialInstance`] and +/// [`Instance`] for local players. #[derive(Component)] -pub struct LocalPlayer { - pub packet_writer: mpsc::UnboundedSender, - +pub struct InstanceHolder { /// The partial instance is the world this client currently has loaded. It /// has a limited render distance. pub partial_instance: Arc>, /// The world is the combined [`PartialInstance`]s of all clients in the /// same world. (Only relevant if you're using a shared world, i.e. a /// swarm) - pub world: Arc>, - - /// A task that reads packets from the server. The client is disconnected - /// when this task ends. - pub(crate) read_packets_task: JoinHandle<()>, - /// A task that writes packets from the server. - pub(crate) write_packets_task: JoinHandle<()>, + pub instance: Arc>, } /// A component only present in players that contains the [`GameProfile`] (which @@ -64,6 +53,53 @@ pub struct LocalGameMode { pub previous: Option, } +/// A component that contains the abilities the player has, like flying +/// or instantly breaking blocks. This is only present on local players. +#[derive(Clone, Debug, Component, Default)] +pub struct PlayerAbilities { + pub invulnerable: bool, + pub flying: bool, + pub can_fly: bool, + /// Whether the player can instantly break blocks and can duplicate blocks + /// in their inventory. + pub instant_break: bool, + + pub flying_speed: f32, + /// Used for the fov + pub walking_speed: f32, +} +impl From for PlayerAbilities { + fn from(packet: ClientboundPlayerAbilitiesPacket) -> Self { + Self { + invulnerable: packet.flags.invulnerable, + flying: packet.flags.flying, + can_fly: packet.flags.can_fly, + instant_break: packet.flags.instant_break, + flying_speed: packet.flying_speed, + walking_speed: packet.walking_speed, + } + } +} + +/// Level must be 0..=4 +#[derive(Component, Clone, Default, Deref, DerefMut)] +pub struct PermissionLevel(pub u8); + +/// A component that contains a map of player UUIDs to their information in the +/// tab list. +/// +/// ``` +/// # use azalea_client::TabList; +/// # fn example(client: &azalea_client::Client) { +/// let tab_list = client.component::(); +/// println!("Online players:"); +/// for (uuid, player_info) in tab_list.iter() { +/// println!("- {} ({}ms)", player_info.profile.name, player_info.latency); +/// } +/// # } +#[derive(Component, Resource, Clone, Debug, Deref, DerefMut, Default)] +pub struct TabList(HashMap); + #[derive(Component, Clone)] pub struct Hunger { /// The main hunger bar. Goes from 0 to 20. @@ -83,50 +119,24 @@ impl Default for Hunger { } } -impl LocalPlayer { - /// Create a new `LocalPlayer`. - pub fn new( - entity: Entity, - packet_writer: mpsc::UnboundedSender, - world: Arc>, - read_packets_task: JoinHandle<()>, - write_packets_task: JoinHandle<()>, - ) -> Self { +impl InstanceHolder { + /// Create a new `InstanceHolder`. + pub fn new(entity: Entity, world: Arc>) -> Self { let client_information = ClientInformation::default(); - LocalPlayer { - packet_writer, - - world, + InstanceHolder { + instance: world, partial_instance: Arc::new(RwLock::new(PartialInstance::new( azalea_world::calculate_chunk_storage_range( client_information.view_distance.into(), ), Some(entity), ))), - - read_packets_task, - write_packets_task, } } - - /// Write a packet directly to the server. - pub fn write_packet(&self, packet: ServerboundGamePacket) { - self.packet_writer - .send(packet) - .expect("write_packet shouldn't be able to be called if the connection is closed"); - } -} - -impl Drop for LocalPlayer { - /// Stop every active task when the `LocalPlayer` is dropped. - fn drop(&mut self) { - self.read_packets_task.abort(); - self.write_packets_task.abort(); - } } -/// Send the "Death" event for [`LocalPlayer`]s that died with no reason. +/// Send the "Death" event for [`LocalEntity`]s that died with no reason. pub fn death_event(query: Query<&LocalPlayerEvents, Added>) { for local_player_events in &query { local_player_events.send(AzaleaEvent::Death(None)).unwrap(); @@ -160,11 +170,14 @@ pub struct SendPacketEvent { pub fn handle_send_packet_event( mut send_packet_events: EventReader, - mut query: Query<&mut LocalPlayer>, + mut query: Query<&mut RawConnection>, ) { for event in send_packet_events.iter() { - if let Ok(local_player) = query.get_mut(event.entity) { - local_player.write_packet(event.packet.clone()); + if let Ok(raw_connection) = query.get_mut(event.entity) { + // debug!("Sending packet: {:?}", event.packet); + if let Err(e) = raw_connection.write_packet(event.packet.clone()) { + error!("Failed to send packet: {e}"); + } } } } -- cgit v1.2.3