azalea_client/
local_player.rs1use std::{
2 collections::HashMap,
3 error, io,
4 sync::{Arc, PoisonError},
5};
6
7use azalea_core::game_type::GameMode;
8use azalea_protocol::packets::game::c_player_abilities::ClientboundPlayerAbilities;
9use azalea_world::{Instance, PartialInstance};
10use bevy_ecs::{component::Component, prelude::*};
11use derive_more::{Deref, DerefMut};
12use parking_lot::RwLock;
13use thiserror::Error;
14use tokio::sync::mpsc;
15use tracing::error;
16use uuid::Uuid;
17
18use crate::{ClientInformation, events::Event as AzaleaEvent, player::PlayerInfo};
19
20#[derive(Component, Clone)]
30pub struct InstanceHolder {
31 pub partial_instance: Arc<RwLock<PartialInstance>>,
34 pub instance: Arc<RwLock<Instance>>,
40}
41
42#[derive(Component, Clone, Debug, Copy)]
45pub struct LocalGameMode {
46 pub current: GameMode,
47 pub previous: Option<GameMode>,
48}
49impl From<GameMode> for LocalGameMode {
50 fn from(current: GameMode) -> Self {
51 LocalGameMode {
52 current,
53 previous: None,
54 }
55 }
56}
57
58#[derive(Clone, Debug, Component, Default)]
61pub struct PlayerAbilities {
62 pub invulnerable: bool,
63 pub flying: bool,
64 pub can_fly: bool,
65 pub instant_break: bool,
68
69 pub flying_speed: f32,
70 pub walking_speed: f32,
72}
73impl From<&ClientboundPlayerAbilities> for PlayerAbilities {
74 fn from(packet: &ClientboundPlayerAbilities) -> Self {
75 Self {
76 invulnerable: packet.flags.invulnerable,
77 flying: packet.flags.flying,
78 can_fly: packet.flags.can_fly,
79 instant_break: packet.flags.instant_break,
80 flying_speed: packet.flying_speed,
81 walking_speed: packet.walking_speed,
82 }
83 }
84}
85
86#[derive(Component, Clone, Default, Deref, DerefMut)]
88pub struct PermissionLevel(pub u8);
89
90#[derive(Component, Resource, Clone, Debug, Deref, DerefMut, Default)]
110pub struct TabList(HashMap<Uuid, PlayerInfo>);
111
112#[derive(Component, Clone)]
113pub struct Hunger {
114 pub food: u32,
116 pub saturation: f32,
120}
121
122impl Default for Hunger {
123 fn default() -> Self {
124 Hunger {
125 food: 20,
126 saturation: 5.,
127 }
128 }
129}
130
131impl InstanceHolder {
132 pub fn new(entity: Entity, instance: Arc<RwLock<Instance>>) -> Self {
138 let client_information = ClientInformation::default();
139
140 InstanceHolder {
141 instance,
142 partial_instance: Arc::new(RwLock::new(PartialInstance::new(
143 azalea_world::chunk_storage::calculate_chunk_storage_range(
144 client_information.view_distance.into(),
145 ),
146 Some(entity),
147 ))),
148 }
149 }
150
151 pub fn reset(&mut self) {
156 let registries = self.instance.read().registries.clone();
157
158 let new_instance = Instance {
159 registries,
160 ..Default::default()
161 };
162 self.instance = Arc::new(RwLock::new(new_instance));
163
164 self.partial_instance.write().reset();
165 }
166}
167
168#[derive(Error, Debug)]
169pub enum HandlePacketError {
170 #[error("{0}")]
171 Poison(String),
172 #[error(transparent)]
173 Io(#[from] io::Error),
174 #[error(transparent)]
175 Other(#[from] Box<dyn error::Error + Send + Sync>),
176 #[error("{0}")]
177 Send(#[from] mpsc::error::SendError<AzaleaEvent>),
178}
179
180impl<T> From<PoisonError<T>> for HandlePacketError {
181 fn from(e: PoisonError<T>) -> Self {
182 HandlePacketError::Poison(e.to_string())
183 }
184}