azalea_client/
local_player.rs1use std::{collections::HashMap, io, sync::Arc};
2
3use azalea_auth::game_profile::GameProfile;
4use azalea_core::game_type::GameMode;
5use azalea_entity::Dead;
6use azalea_protocol::packets::game::c_player_abilities::ClientboundPlayerAbilities;
7use azalea_world::{Instance, PartialInstance};
8use bevy_ecs::{component::Component, prelude::*};
9use derive_more::{Deref, DerefMut};
10use parking_lot::RwLock;
11use thiserror::Error;
12use tokio::sync::mpsc;
13use tracing::error;
14use uuid::Uuid;
15
16use crate::{
17 events::{Event as AzaleaEvent, LocalPlayerEvents},
18 ClientInformation, PlayerInfo,
19};
20
21#[derive(Component, Clone)]
31pub struct InstanceHolder {
32 pub partial_instance: Arc<RwLock<PartialInstance>>,
35 pub instance: Arc<RwLock<Instance>>,
41}
42
43#[derive(Component, Clone, Debug, Deref, DerefMut)]
49pub struct GameProfileComponent(pub GameProfile);
50
51#[derive(Component, Clone, Debug, Copy)]
54pub struct LocalGameMode {
55 pub current: GameMode,
56 pub previous: Option<GameMode>,
57}
58
59#[derive(Clone, Debug, Component, Default)]
62pub struct PlayerAbilities {
63 pub invulnerable: bool,
64 pub flying: bool,
65 pub can_fly: bool,
66 pub instant_break: bool,
69
70 pub flying_speed: f32,
71 pub walking_speed: f32,
73}
74impl From<&ClientboundPlayerAbilities> for PlayerAbilities {
75 fn from(packet: &ClientboundPlayerAbilities) -> Self {
76 Self {
77 invulnerable: packet.flags.invulnerable,
78 flying: packet.flags.flying,
79 can_fly: packet.flags.can_fly,
80 instant_break: packet.flags.instant_break,
81 flying_speed: packet.flying_speed,
82 walking_speed: packet.walking_speed,
83 }
84 }
85}
86
87#[derive(Component, Clone, Default, Deref, DerefMut)]
89pub struct PermissionLevel(pub u8);
90
91#[derive(Component, Resource, Clone, Debug, Deref, DerefMut, Default)]
111pub struct TabList(HashMap<Uuid, PlayerInfo>);
112
113#[derive(Component, Clone)]
114pub struct Hunger {
115 pub food: u32,
117 pub saturation: f32,
121}
122
123impl Default for Hunger {
124 fn default() -> Self {
125 Hunger {
126 food: 20,
127 saturation: 5.,
128 }
129 }
130}
131
132impl InstanceHolder {
133 pub fn new(entity: Entity, instance: Arc<RwLock<Instance>>) -> Self {
139 let client_information = ClientInformation::default();
140
141 InstanceHolder {
142 instance,
143 partial_instance: Arc::new(RwLock::new(PartialInstance::new(
144 azalea_world::chunk_storage::calculate_chunk_storage_range(
145 client_information.view_distance.into(),
146 ),
147 Some(entity),
148 ))),
149 }
150 }
151}
152
153pub fn death_event(query: Query<&LocalPlayerEvents, Added<Dead>>) {
155 for local_player_events in &query {
156 local_player_events.send(AzaleaEvent::Death(None)).unwrap();
157 }
158}
159
160#[derive(Error, Debug)]
161pub enum HandlePacketError {
162 #[error("{0}")]
163 Poison(String),
164 #[error(transparent)]
165 Io(#[from] io::Error),
166 #[error(transparent)]
167 Other(#[from] Box<dyn std::error::Error + Send + Sync>),
168 #[error("{0}")]
169 Send(#[from] mpsc::error::SendError<AzaleaEvent>),
170}
171
172impl<T> From<std::sync::PoisonError<T>> for HandlePacketError {
173 fn from(e: std::sync::PoisonError<T>) -> Self {
174 HandlePacketError::Poison(e.to_string())
175 }
176}