use crate::ffi::{NotThreadSafe, borrow_cstr, copy_cstr, vcall};
use std::ffi::{CStr, CString, c_int};
use std::marker::PhantomData;
use std::ptr::NonNull;
interface! {
#[doc(alias = "ICvar")]
pub struct Cvar(sys::ICvar) = Engine c"VEngineCvar004";
}
impl<'s> Cvar<'s> {
#[doc(alias = "FindVar")]
pub fn find_var(self, name: &CStr) -> Option<ConVar<'s>> {
let var = NonNull::new(unsafe { vcall!(self.as_ptr() => ICvar_FindVar(name.as_ptr())) })?;
Some(ConVar {
raw: var,
_scope: PhantomData,
_not_thread_safe: PhantomData,
})
}
#[doc(alias = "ConsolePrintf")]
pub(crate) fn console_printf(self, message: &CStr) {
unsafe { vcall!(self.as_ptr() => ICvar_ConsolePrintf(c"%s".as_ptr(), message.as_ptr())) };
}
#[doc(alias = "FindCommandBase")]
pub(crate) fn find_command_base(self, name: &CStr) -> Option<NonNull<sys::ConCommandBase>> {
NonNull::new(unsafe { vcall!(self.as_ptr() => ICvar_FindCommandBase(name.as_ptr())) })
}
#[doc(alias = "AllocateDLLIdentifier")]
pub(crate) fn allocate_dll_identifier(self) -> sys::CVarDLLIdentifier_t {
unsafe { vcall!(self.as_ptr() => ICvar_AllocateDLLIdentifier()) }
}
#[doc(alias = "RegisterConCommand")]
pub(crate) unsafe fn register_con_command(self, command: NonNull<sys::ConCommandBase>) {
unsafe { vcall!(self.as_ptr() => ICvar_RegisterConCommand(command.as_ptr())) };
}
#[doc(alias = "UnregisterConCommand")]
pub(crate) unsafe fn unregister_con_command(self, command: NonNull<sys::ConCommandBase>) {
unsafe { vcall!(self.as_ptr() => ICvar_UnregisterConCommand(command.as_ptr())) };
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ConVar<'s> {
raw: NonNull<sys::ConVar>,
_scope: PhantomData<&'s ()>,
_not_thread_safe: NotThreadSafe,
}
impl<'s> ConVar<'s> {
pub const fn as_ptr(self) -> *mut sys::ConVar {
self.raw.as_ptr()
}
#[doc(alias = "GetName")]
pub fn name(self) -> &'s CStr {
unsafe { borrow_cstr((&raw const (*self.as_ptr())._base.m_pszName).read()) }
.unwrap_or_default()
}
#[doc(alias = "GetString")]
pub fn string(self) -> CString {
unsafe { copy_cstr((&raw const (*self.parent()).m_pszString).read()) }.unwrap_or_default()
}
#[doc(alias = "GetFloat")]
pub fn float(self) -> f32 {
unsafe { (&raw const (*self.parent()).m_fValue).read() }
}
#[doc(alias = "GetInt")]
pub fn int(self) -> c_int {
unsafe { (&raw const (*self.parent()).m_nValue).read() }
}
fn parent(self) -> *mut sys::ConVar {
let parent = unsafe { (&raw const (*self.as_ptr()).m_pParent).read() };
if parent.is_null() {
self.as_ptr()
} else {
parent
}
}
}