mc_schem/
player.rs

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    /// No tags, only the existence of memory is required
156    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    /// Is added by beacon
168    pub ambient: bool,
169    /// level
170    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    // recipe book
278    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}