classicube_helpers\entities/
entity.rs

1use std::{
2    ffi::CStr,
3    ptr::{addr_of, NonNull},
4};
5
6use classicube_sys::{Entities, Vec3};
7
8/// 255 is self entity
9pub const ENTITY_SELF_ID: u8 = 255;
10
11#[derive(Debug)]
12pub struct Entity {
13    id: u8,
14    inner: &'static mut classicube_sys::Entity,
15}
16
17impl Entity {
18    /// # Safety
19    ///
20    /// `id` must exist.
21    ///
22    /// `Entity` cannot outlive the entity in-game.
23    ///
24    /// `Entities` will use `Weak` to make sure this dies when the entity is removed.
25    pub unsafe fn from_id(id: u8) -> Option<Self> {
26        let mut ptr = NonNull::new(Entities.List[id as usize])?;
27        let inner = ptr.as_mut();
28        Some(Self { id, inner })
29    }
30
31    #[must_use]
32    pub fn get_inner(&self) -> &classicube_sys::Entity {
33        self.inner
34    }
35
36    /// # Safety
37    ///
38    /// `Entity` cannot outlive the entity in-game.
39    ///
40    /// `Entities` will use `Weak` to make sure this dies when the entity is removed.
41    pub fn get_inner_mut(&mut self) -> &mut classicube_sys::Entity {
42        self.inner
43    }
44
45    #[must_use]
46    pub fn get_id(&self) -> u8 {
47        self.id
48    }
49
50    #[must_use]
51    pub fn get_position(&self) -> Vec3 {
52        self.inner.Position
53    }
54
55    #[must_use]
56    pub fn get_head(&self) -> [f32; 2] {
57        [self.inner.Pitch, self.inner.Yaw]
58    }
59
60    /// [x, y, z], numbers are 0-360
61    #[must_use]
62    pub fn get_rot(&self) -> [f32; 3] {
63        [self.inner.RotX, self.inner.RotY, self.inner.RotZ]
64    }
65
66    #[must_use]
67    pub fn get_velocity(&self) -> Vec3 {
68        self.inner.Velocity
69    }
70
71    #[must_use]
72    pub unsafe fn get_model(&self) -> Option<&classicube_sys::Model> {
73        let mut model = NonNull::new(self.inner.Model)?;
74        Some(model.as_mut())
75    }
76
77    #[must_use]
78    pub fn get_model_eye_y(&self) -> f32 {
79        let model = unsafe { self.get_model().expect("Entity::get_model") };
80        let get_eye_y = model.GetEyeY.expect("GetEyeY");
81
82        // it most likely doesn't mutate the Entity
83        let inner_ptr = (self.inner as *const classicube_sys::Entity).cast_mut();
84        unsafe { get_eye_y(inner_ptr) }
85    }
86
87    #[must_use]
88    pub fn get_model_name_y(&self) -> f32 {
89        let model = unsafe { self.get_model().expect("Entity::get_model") };
90        let get_name_y = model.GetNameY.expect("GetNameY");
91
92        // it most likely doesn't mutate the Entity
93        let inner_ptr = (self.inner as *const classicube_sys::Entity).cast_mut();
94        unsafe { get_name_y(inner_ptr) }
95    }
96
97    #[must_use]
98    pub fn get_model_scale(&self) -> Vec3 {
99        self.inner.ModelScale
100    }
101
102    #[must_use]
103    pub fn get_display_name(&self) -> String {
104        let c_str = unsafe { CStr::from_ptr(addr_of!(self.inner.NameRaw).cast()) };
105        c_str.to_string_lossy().to_string()
106    }
107
108    #[must_use]
109    pub fn get_eye_height(&self) -> f32 {
110        self.get_model_eye_y() * self.get_model_scale().y
111    }
112
113    #[must_use]
114    pub fn get_eye_position(&self) -> Vec3 {
115        let mut pos = self.get_position();
116        pos.y += self.get_eye_height();
117        pos
118    }
119}