#[cfg(test)]
#[path = "tests/edicts.rs"]
mod tests;
use crate::NotThreadSafe;
use crate::entities::Entity;
use crate::interfaces::ValveEngine;
use sdk_raw::edicts::FL_EDICT_FREE;
use sdk_raw::util::cstr::borrow_cstr;
use sdk_raw::vcall;
use std::ffi::{CStr, c_int};
use std::marker::PhantomData;
use std::ptr::NonNull;
pub use sdk_raw::edicts::MAX_EDICTS;
#[doc(alias("edict_t"))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Edict<'s> {
pointer: NonNull<sys::edict_t>,
_scope: PhantomData<&'s ()>,
_not_thread_safe: NotThreadSafe,
}
impl<'s> Edict<'s> {
pub(crate) const unsafe fn from_raw(pointer: NonNull<sys::edict_t>) -> Self {
Self {
pointer,
_scope: PhantomData,
_not_thread_safe: PhantomData,
}
}
pub const fn as_ptr(self) -> *mut sys::edict_t {
self.pointer.as_ptr()
}
#[doc(alias("GetClassName"))]
pub fn class_name(self) -> Option<&'s CStr> {
if self.is_free() {
return None;
}
let networkable =
NonNull::new(unsafe { (&raw const (*self.as_ptr())._base.m_pNetworkable).read() })?;
unsafe { borrow_cstr(vcall!(networkable.as_ptr() => IServerNetworkable_GetClassName())) }
}
#[doc(alias("GetBaseEntity", "GetUnknown"))]
pub fn entity(self) -> Option<Entity<'s>> {
if self.is_free() {
return None;
}
let unknown = NonNull::new(unsafe { (&raw const (*self.as_ptr())._base.m_pUnk).read() })?;
let entity = unsafe { vcall!(unknown.as_ptr() => IServerUnknown_GetBaseEntity()) };
NonNull::new(entity).map(|entity| unsafe { Entity::from_raw(entity) })
}
#[doc(alias("StateChanged"))]
pub fn full_state_changed(self, engine: ValveEngine<'_>) {
let accessor = engine.change_accessor(self);
unsafe { sdk_raw::edicts::full_state_changed(self.as_ptr(), accessor) };
}
#[doc(alias("ENTINDEX", "IndexOfEdict", "m_EdictIndex"))]
pub fn index(self) -> c_int {
let index = unsafe { (&raw const (*self.as_ptr())._base.m_EdictIndex).read() };
c_int::from(index)
}
#[doc(alias("FL_EDICT_FREE", "IsFree"))]
pub fn is_free(self) -> bool {
self.state_flags() & FL_EDICT_FREE != 0
}
#[doc(alias("StateChanged"))]
pub fn state_changed(self, engine: ValveEngine<'_>, offset: u16) {
unsafe {
sdk_raw::edicts::state_changed(self.as_ptr(), offset, || {
engine
.change_accessor(self)
.zip(engine.shared_edict_change_info())
})
};
}
fn state_flags(self) -> c_int {
unsafe { (&raw const (*self.as_ptr())._base.m_fStateFlags).read() }
}
}