diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2023-09-21 11:16:29 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-21 11:16:29 -0500 |
| commit | 7b3e2e4bf793466a351510c7fbbd08234e93bb0e (patch) | |
| tree | 7177a919de9982d9e3c7f36a76d2025696f465b6 /azalea-client/src/local_player.rs | |
| parent | 83cce236145cdab1872a472a70943b669a880965 (diff) | |
| download | azalea-drasl-7b3e2e4bf793466a351510c7fbbd08234e93bb0e.tar.xz | |
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 <git@matdoes.dev>
Diffstat (limited to 'azalea-client/src/local_player.rs')
| -rw-r--r-- | azalea-client/src/local_player.rs | 133 |
1 files changed, 73 insertions, 60 deletions
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<ServerboundGamePacket>, - +pub struct InstanceHolder { /// The partial instance is the world this client currently has loaded. It /// has a limited render distance. pub partial_instance: Arc<RwLock<PartialInstance>>, /// 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<RwLock<Instance>>, - - /// 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<RwLock<Instance>>, } /// A component only present in players that contains the [`GameProfile`] (which @@ -64,6 +53,53 @@ pub struct LocalGameMode { pub previous: Option<GameMode>, } +/// 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<ClientboundPlayerAbilitiesPacket> 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::<TabList>(); +/// 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<Uuid, PlayerInfo>); + #[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<ServerboundGamePacket>, - world: Arc<RwLock<Instance>>, - read_packets_task: JoinHandle<()>, - write_packets_task: JoinHandle<()>, - ) -> Self { +impl InstanceHolder { + /// Create a new `InstanceHolder`. + pub fn new(entity: Entity, world: Arc<RwLock<Instance>>) -> 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<Dead>>) { 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<SendPacketEvent>, - 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}"); + } } } } |
