aboutsummaryrefslogtreecommitdiff
path: root/azalea-client/src/local_player.rs
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2023-09-21 11:16:29 -0500
committerGitHub <noreply@github.com>2023-09-21 11:16:29 -0500
commit7b3e2e4bf793466a351510c7fbbd08234e93bb0e (patch)
tree7177a919de9982d9e3c7f36a76d2025696f465b6 /azalea-client/src/local_player.rs
parent83cce236145cdab1872a472a70943b669a880965 (diff)
downloadazalea-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.rs133
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}");
+ }
}
}
}