classicube_helpers\entities/
entity.rs

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