steel_core/player/
abilities.rs1use steel_protocol::packets::game::{CPlayerAbilities, SPlayerAbilities, ability_flags};
4use steel_utils::types::GameType;
5
6use crate::player::Player;
7
8pub const DEFAULT_FLYING_SPEED: f32 = 0.05;
10pub const DEFAULT_WALKING_SPEED: f32 = 0.1;
12
13#[derive(Debug, Clone)]
16pub struct Abilities {
17 pub invulnerable: bool,
19 pub flying: bool,
21 pub may_fly: bool,
23 pub instabuild: bool,
25 pub may_build: bool,
27 pub flying_speed: f32,
29 pub walking_speed: f32,
31}
32
33impl Default for Abilities {
34 fn default() -> Self {
35 Self {
36 invulnerable: false,
37 flying: false,
38 may_fly: false,
39 instabuild: false,
40 may_build: true,
41 flying_speed: DEFAULT_FLYING_SPEED,
42 walking_speed: DEFAULT_WALKING_SPEED,
43 }
44 }
45}
46
47impl Abilities {
48 #[must_use]
50 pub fn survival() -> Self {
51 Self::default()
52 }
53
54 #[must_use]
56 pub fn creative() -> Self {
57 Self {
58 invulnerable: true,
59 flying: false,
60 may_fly: true,
61 instabuild: true,
62 may_build: true,
63 ..Self::default()
64 }
65 }
66
67 #[must_use]
69 pub fn adventure() -> Self {
70 Self {
71 may_build: false,
72 ..Self::default()
73 }
74 }
75
76 pub const fn update_for_game_mode(&mut self, game_mode: GameType) {
79 match game_mode {
80 GameType::Survival => {
81 self.invulnerable = false;
82 self.may_fly = false;
83 self.instabuild = false;
84 self.flying = false;
85 self.may_build = true;
86 }
87 GameType::Creative => {
88 self.invulnerable = true;
89 self.may_fly = true;
90 self.instabuild = true;
91 self.may_build = true;
93 }
94 GameType::Adventure => {
95 self.invulnerable = false;
96 self.may_fly = false;
97 self.instabuild = false;
98 self.flying = false;
99 self.may_build = false;
100 }
101 GameType::Spectator => {
102 self.invulnerable = true;
103 self.may_fly = true;
104 self.instabuild = false;
105 self.flying = true;
106 self.may_build = false;
107 }
108 }
109 }
110
111 #[must_use]
113 pub const fn to_packet(&self) -> CPlayerAbilities {
114 let mut flags: u8 = 0;
115
116 if self.invulnerable {
117 flags |= ability_flags::INVULNERABLE;
118 }
119 if self.flying {
120 flags |= ability_flags::FLYING;
121 }
122 if self.may_fly {
123 flags |= ability_flags::MAY_FLY;
124 }
125 if self.instabuild {
126 flags |= ability_flags::INSTABUILD;
127 }
128
129 CPlayerAbilities {
130 flags,
131 flying_speed: self.flying_speed,
132 walking_speed: self.walking_speed,
133 }
134 }
135}
136
137impl Player {
138 pub fn send_abilities(&self) {
141 let packet = self.abilities.lock().to_packet();
142 self.send_packet(packet);
143 }
144
145 #[must_use]
147 pub fn is_flying(&self) -> bool {
148 self.abilities.lock().flying
149 }
150
151 pub fn set_flying(&self, flying: bool) {
153 self.abilities.lock().flying = flying;
154 }
155
156 #[must_use]
158 pub fn get_flying_speed(&self) -> f32 {
159 self.abilities.lock().flying_speed
160 }
161
162 pub fn set_flying_speed(&self, speed: f32) {
164 self.abilities.lock().flying_speed = speed;
165 }
166
167 #[must_use]
169 pub fn get_abilities(&self) -> Abilities {
170 self.abilities.lock().clone()
171 }
172
173 pub fn handle_player_abilities(&self, packet: SPlayerAbilities) {
176 let mut abilities = self.abilities.lock();
177
178 if abilities.may_fly {
179 abilities.flying = packet.is_flying();
180 } else if packet.is_flying() {
181 drop(abilities);
183 self.send_abilities();
184 }
185 }
186}