1use std::any::Any;
2use std::collections::{BTreeMap, HashMap};
3use std::fmt::{Debug, Formatter};
4use strum::FromRepr;
5use crate::item::{Inventory, Item};
6
7#[derive(Debug, Clone)]
8pub struct DimensionId(String);
9
10impl Default for DimensionId {
11 fn default() -> Self {
12 return Self::overworld();
13 }
14}
15
16#[allow(dead_code)]
17impl DimensionId {
18 pub fn overworld() -> Self {
19 return DimensionId("minecraft:overworld".to_string());
20 }
21 pub fn nether() -> Self {
22 return DimensionId("minecraft:nether".to_string());
23 }
24 pub fn the_end() -> Self {
25 return DimensionId("minecraft:the_end".to_string());
26 }
27}
28
29#[repr(i32)]
30#[derive(Debug, Clone, Copy, FromRepr)]
31#[allow(dead_code)]
32pub enum AttributeOperation {
33 Add = 0,
34 MultiplyBase = 1,
35 Multiply = 2,
36}
37
38#[derive(Debug, Clone)]
39pub struct AttributeModifier {
40 pub name: String,
41 pub amount: f64,
42 pub operation: AttributeOperation,
43 pub uuid: [i32; 4],
44}
45
46#[derive(Debug, Clone)]
47pub struct EntityAttribute {
48 pub base: f64,
49 pub modifiers: Vec<AttributeModifier>,
50}
51
52#[derive(Debug, Clone)]
53pub struct EntityFields {
54 pub air: i16,
55 pub custom_name: Option<String>,
56 pub custom_name_visible: bool,
57 pub fall_distance: f32,
58 pub fire: i16,
59 pub glowing: bool,
60 pub has_visual_fire: bool,
61 pub invulnerable: bool,
62 pub motion: [f64; 3],
63 pub no_gravity: bool,
64 pub on_ground: bool,
65 pub passenger: Vec<EntityBox>,
66 pub portal_cool_down: i32,
67 pub pos: [f64; 3],
68 pub rotation: [f32; 2],
69 pub silent: bool,
70 pub tags: HashMap<String, ScoreboardTag>,
71 pub ticks_frozen: i32,
72 pub uuid: [i32; 4],
73}
74
75#[derive(Debug, Clone)]
76pub struct ScoreboardTag {
77 pub score: i32,
78 pub locked: bool,
79}
80
81impl Default for EntityFields {
82 fn default() -> Self {
83 return Self {
84 air: 0,
85 custom_name: None,
86 custom_name_visible: false,
87 fall_distance: 0.0,
88 fire: 0,
89 glowing: false,
90 has_visual_fire: false,
91 invulnerable: false,
92 motion: [0.0, 0.0, 0.0],
93 no_gravity: false,
94 on_ground: false,
95 passenger: vec![],
96 portal_cool_down: 0,
97 pos: [0.0, 0.0, 0.0],
98 rotation: [0.0, 0.0],
99 silent: false,
100 tags: Default::default(),
101 ticks_frozen: 0,
102 uuid: [0; 4],
103 };
104 }
105}
106
107#[derive(Debug, Clone)]
108pub struct MobFields {
109 pub absorption_amount: f32,
110 pub active_effects: Vec<PotionEffect>,
111 pub attributes: BTreeMap<String, EntityAttribute>,
112 pub brain: HashMap<String, MobMemory>,
113 pub death_time: i16,
114 pub fall_flying: bool,
115 pub hurt_by_time_stamp: i32,
116 pub hurt_time: i16,
117 pub sleeping_pos: [i32; 3],
118}
119
120impl Default for MobFields {
121 fn default() -> Self {
122 return Self {
123 absorption_amount: 0.0,
124 active_effects: vec![],
125 attributes: Default::default(),
126 brain: Default::default(),
127 death_time: 0,
128 fall_flying: false,
129 hurt_by_time_stamp: 0,
130 hurt_time: 0,
131 sleeping_pos: [0, 0, 0],
132 };
133 }
134}
135
136#[derive(Debug, Clone, Default)]
137#[allow(dead_code)]
138pub struct MobMemory {
139 ttl: i64,
140 value: MemoryValue,
141}
142
143#[derive(Debug, Clone)]
144#[allow(dead_code)]
145pub enum MemoryValue {
146 Boolean(bool),
147 Integer(i32),
148 Long(i64),
149 UUID([i32; 4]),
150 GlobalPos {
151 dimension: DimensionId,
152 pos: [i32; 3],
153 },
154 BlockPosList(Vec<[i32; 3]>),
155 Unit,
157}
158
159impl Default for MemoryValue {
160 fn default() -> Self {
161 return MemoryValue::Unit;
162 }
163}
164
165#[derive(Debug, Clone)]
166pub struct PotionEffect {
167 pub ambient: bool,
169 pub amplifier: i8,
171 pub duration: i32,
172 pub id: String,
173 pub show_icon: bool,
174 pub show_particles: bool,
175 pub factor_calculation_data: PotionEffectFactorCalculationData,
176 pub hidden_effects: Vec<PotionEffect>,
177}
178
179#[derive(Debug, Clone)]
180pub struct PotionEffectFactorCalculationData {
181 pub effect_changed_timestamp: i32,
182 pub factor_current: f32,
183 pub factor_previous_frame: f32,
184 pub factor_start: f32,
185 pub factor_target: f32,
186 pub had_effect_last_tick: bool,
187 pub padding_duration: i32,
188}
189
190
191#[derive(Debug, Clone)]
192pub struct PlayerAbilities {
193 pub flying: bool,
194 pub instant_build: bool,
195 pub invulnerable: bool,
196 pub may_build: bool,
197 pub may_fly: bool,
198 pub walk_speed: f32,
199 pub fly_speed: f32,
200}
201
202impl Default for PlayerAbilities {
203 fn default() -> Self {
204 return Self {
205 flying: false,
206 instant_build: false,
207 invulnerable: false,
208 may_build: true,
209 may_fly: false,
210 walk_speed: 1.0,
211 fly_speed: 1.0,
212 };
213 }
214}
215
216#[repr(i32)]
217#[derive(Debug, Clone, Copy, FromRepr)]
218#[allow(dead_code)]
219pub enum PlayerGameType {
220 Survival = 0,
221 Creative = 1,
222 Adventure = 2,
223 Spectator = 3,
224}
225
226
227#[derive(Debug, Clone)]
228pub struct WardenSpawnTracker {
229 pub cooldown_ticks: i32,
230 pub ticks_since_last_warning: i32,
231 pub warning_level: i32,
232}
233
234impl Default for WardenSpawnTracker {
235 fn default() -> Self {
236 return Self {
237 cooldown_ticks: 0,
238 ticks_since_last_warning: 0,
239 warning_level: 0,
240 };
241 }
242}
243
244#[derive(Debug, Clone)]
245pub struct XpInfo {
246 pub level: i32,
247 pub xp_p: f32,
248 pub speed: i32,
249 pub total: i32,
250}
251
252impl Default for XpInfo {
253 fn default() -> Self {
254 return Self {
255 level: 0,
256 xp_p: 0.0,
257 speed: 0,
258 total: 0,
259 };
260 }
261}
262
263#[derive(Debug, Clone)]
264pub struct PlayerFields {
265 pub abilities: PlayerAbilities,
266 pub dimension: DimensionId,
267 pub ender_items: Inventory,
268 pub inventory: Inventory,
269 pub entered_nether_position: Option<[f64; 3]>,
270 pub food_exhaust_level: f32,
271 pub food_saturation_level: f32,
272 pub food_level: i32,
273 pub food_tick_timer: i32,
274 pub last_death_location: (DimensionId, [i32; 3]),
275 pub game_type: PlayerGameType,
276 pub previous_game_type: PlayerGameType,
277 pub root_vehicle: Option<[i32; 4]>,
279 pub score: i32,
280 pub seen_credits: bool,
281 pub selected_item_slot: i32,
282 pub sleep_timer: i16,
283
284 pub should_entity_left: Option<EntityBox>,
285 pub should_entity_right: Option<EntityBox>,
286 pub spawn_angle: f32,
287 pub spawn_dimension: DimensionId,
288 pub spawn_forced: bool,
289 pub spawn_pos: Option<[i32; 3]>,
290 pub warden_spawn_tracker: WardenSpawnTracker,
291 pub xp_info: XpInfo,
292}
293
294impl Default for PlayerFields {
295 fn default() -> Self {
296 return Self {
297 abilities: Default::default(),
298 dimension: DimensionId::default(),
299 ender_items: Default::default(),
300 inventory: Default::default(),
301 entered_nether_position: None,
302 food_exhaust_level: 0.0,
303 food_saturation_level: 0.0,
304 food_level: 0,
305 food_tick_timer: 0,
306 last_death_location: (Default::default(), [0, 0, 0]),
307 game_type: PlayerGameType::Survival,
308 previous_game_type: PlayerGameType::Survival,
309 root_vehicle: None,
310 score: 0,
311 seen_credits: false,
312 selected_item_slot: 0,
313 sleep_timer: 0,
314 should_entity_left: None,
315 should_entity_right: None,
316 spawn_angle: 0.0,
317 spawn_dimension: Default::default(),
318 spawn_forced: false,
319 spawn_pos: None,
320 warden_spawn_tracker: Default::default(),
321 xp_info: Default::default(),
322 };
323 }
324}
325
326#[allow(dead_code)]
327impl PlayerFields {
328 fn selected_item(&self) -> Option<&Item> {
329 let slot = self.selected_item_slot as i8;
330 return self.inventory.0.get(&slot);
331 }
332 fn selected_item_mut(&mut self) -> Option<&mut Item> {
333 let slot = self.selected_item_slot as i8;
334 return self.inventory.0.get_mut(&slot);
335 }
336}
337
338pub trait GetEntity {
339 fn entity_fields(&self) -> &EntityFields;
340 fn pos(&self) -> [f64; 3] {
341 return self.entity_fields().pos;
342 }
343 fn to_mob_fields(&self) -> Option<&dyn GetMob> {
344 return None;
345 }
346 fn is_living_body(&self) -> bool {
347 return self.to_mob_fields().is_some();
348 }
349
350 fn clone_as_entity(&self) -> Box<dyn GetEntityMut>;
351}
352
353pub trait GetEntityMut: GetEntity {
354 fn entity_fields_mut(&mut self) -> &mut EntityFields;
355 fn to_mob_mut(&mut self) -> Option<&mut dyn GetMobMut> {
356 return None;
357 }
358}
359
360pub trait GetMob: GetEntity {
361 fn mob_fields(&self) -> &MobFields;
362
363 fn to_player(&self) -> Option<&dyn GetPlayer>;
364
365 fn is_player(&self) -> bool {
366 return self.to_player().is_some();
367 }
368
369 fn clone_as_living_body(&self) -> Box<dyn GetMobMut>;
370}
371
372pub trait GetMobMut: GetMob + GetEntityMut {
373 fn mob_fields_mut(&mut self) -> &mut MobFields;
374 fn to_player_mut(&mut self) -> Option<&mut dyn GetPlayerMut>;
375}
376
377pub trait GetPlayer: GetMob + GetEntity {
378 fn player_fields(&self) -> &PlayerFields;
379
380 fn clone_as_player(&self) -> Box<dyn GetPlayerMut>;
381}
382
383pub trait GetPlayerMut: GetPlayer + GetMobMut {
384 fn player_fields_mut(&mut self) -> &mut PlayerFields;
385}
386
387#[derive(Debug, Clone, Default)]
388pub struct Player {
389 pub entity_fields: EntityFields,
390 pub mob_fields: MobFields,
391 pub player_fields: PlayerFields,
392}
393
394impl GetEntity for Player {
395 fn entity_fields(&self) -> &EntityFields {
396 return &self.entity_fields;
397 }
398
399 fn clone_as_entity(&self) -> Box<dyn GetEntityMut> {
400 return Box::new(self.clone());
401 }
402}
403
404impl GetEntityMut for Player {
405 fn entity_fields_mut(&mut self) -> &mut EntityFields {
406 return &mut self.entity_fields;
407 }
408}
409
410impl GetMob for Player {
411 fn mob_fields(&self) -> &MobFields {
412 return &self.mob_fields;
413 }
414
415 fn to_player(&self) -> Option<&dyn GetPlayer> {
416 return Some(self);
417 }
418
419 fn clone_as_living_body(&self) -> Box<dyn GetMobMut> {
420 return Box::new(self.clone());
421 }
422}
423
424impl GetMobMut for Player {
425 fn mob_fields_mut(&mut self) -> &mut MobFields {
426 return &mut self.mob_fields;
427 }
428
429 fn to_player_mut(&mut self) -> Option<&mut dyn GetPlayerMut> {
430 return Some(self);
431 }
432}
433
434impl GetPlayer for Player {
435 fn player_fields(&self) -> &PlayerFields {
436 return &self.player_fields;
437 }
438
439 fn clone_as_player(&self) -> Box<dyn GetPlayerMut> {
440 return Box::new(self.clone());
441 }
442}
443
444impl GetPlayerMut for Player {
445 fn player_fields_mut(&mut self) -> &mut PlayerFields {
446 return &mut self.player_fields;
447 }
448}
449
450pub struct EntityBox(Box<dyn GetEntityMut>);
451
452impl Debug for EntityBox {
453 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
454 let ptr = self.0.as_ref() as *const dyn GetEntityMut;
455 return write!(f, "EntityBox, type: {:?}, address: {:?}", self.0.type_id(), ptr);
456 }
457}
458
459impl Clone for EntityBox {
460 fn clone(&self) -> Self {
461 return EntityBox(self.0.clone_as_entity());
462 }
463}