pub const SDK_STRING_MAX_LEN: usize = 128;
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub enum HandlerResult {
CONTINUE = 0,
BREAK = 1,
TERMINATE = 2,
ERR = -1,
}
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub enum HostId {
RE3 = 1,
REVC = 2,
GTA3 = 3,
VC = 4,
SA = 5,
GTA3_UNREAL = 6,
VC_UNREAL = 7,
SA_UNREAL = 8,
IV = 9,
BULLY = 10,
MANIFEST = 254,
UNKNOWN = 255,
}
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub enum Directory {
CLEO = 0,
CONFIG = 1,
TEXT = 2,
PLUGINS = 3,
CWD = 4,
HOST = 5,
}
#[allow(non_camel_case_types)]
pub type c_char = i8;
#[allow(non_camel_case_types)]
pub type c_void = std::ffi::c_void;
pub type Context = *const c_void;
pub type CustomCommand = extern "C" fn(Context) -> HandlerResult;
pub type CustomLoader = extern "C" fn(*const c_char) -> *mut c_void;
pub type OnTickCallback = extern "C" fn(current_time: u32, time_step: i32);
pub type OnRuntimeInitCallback = extern "C" fn();
pub type OnShowTextBoxCallback = extern "C" fn(*const c_char);
#[cfg_attr(target_arch = "x86", link(name = "cleo_redux"))]
#[cfg_attr(target_arch = "x86_64", link(name = "cleo_redux64"))]
extern "C" {
fn GetSDKVersion() -> i32;
fn GetHostId() -> HostId;
fn ResolvePath(src: *const c_char, dest: *mut c_char);
fn GetCLEOFolder(dest: *mut c_char);
fn GetCwd(dest: *mut c_char);
fn Log(text: *const c_char);
fn RegisterCommand(name: *const c_char, cb: CustomCommand, permission: *const c_char);
fn GetIntParam(ctx: Context) -> isize;
fn GetFloatParam(ctx: Context) -> f32;
fn GetStringParam(ctx: Context, dest: *mut c_char, maxlen: u8);
fn SetIntParam(ctx: Context, value: isize);
fn SetFloatParam(ctx: Context, value: f32);
fn SetStringParam(ctx: Context, src: *const c_char);
fn UpdateCompareFlag(ctx: Context, result: bool);
fn GetHostName(dest: *mut c_char, maxlen: u8);
fn SetHostName(src: *const c_char);
fn RuntimeInit();
fn RuntimeNextTick(current_time: u32, time_step: i32);
fn RegisterLoader(glob: *const c_char, cb: CustomLoader);
fn AllocMem(size: usize) -> *mut c_void;
fn FreeMem(ptr: *mut c_void);
fn OnBeforeScripts(cb: OnTickCallback);
fn OnAfterScripts(cb: OnTickCallback);
fn OnRuntimeInit(cb: OnRuntimeInitCallback);
fn OnShowTextBox(cb: OnShowTextBoxCallback);
fn GetDirectoryPath(dir: Directory, dest: *mut c_char);
fn GetCLEOVersion(dest: *mut c_char);
fn GetSymbolAddress(symbol: *const c_char) -> usize;
fn GetNumberOfActiveCSScripts() -> usize;
fn GetNumberOfActiveJSScripts() -> usize;
fn IsEndOfArguments(ctx: Context) -> bool;
fn TriggerEvent(event: *const c_char, data: *const c_char);
}
macro_rules! sz {
($name:expr) => {
std::ffi::CString::new($name).unwrap().as_ptr()
};
}
#[allow(dead_code)]
pub fn register_command(name: &str, cb: CustomCommand, permission: Option<&str>) {
unsafe {
match permission {
Some(token) => RegisterCommand(sz!(name), cb, sz!(token)),
None => RegisterCommand(sz!(name), cb, std::ptr::null()),
};
}
}
pub fn log<T: Into<Vec<u8>>>(text: T) {
unsafe { Log(sz!(text)) };
}
pub fn get_sdk_version() -> i32 {
unsafe { GetSDKVersion() }
}
pub fn get_host_id() -> HostId {
unsafe { GetHostId() }
}
pub fn get_string_param(ctx: Context) -> String {
let mut buf = [0i8; SDK_STRING_MAX_LEN];
unsafe { GetStringParam(ctx, buf.as_mut_ptr(), SDK_STRING_MAX_LEN as _) };
to_rust_string(buf.as_ptr())
}
pub fn set_string_param(ctx: Context, value: String) {
unsafe { SetStringParam(ctx, sz!(value)) };
}
pub fn get_int_param(ctx: Context) -> isize {
unsafe { GetIntParam(ctx) }
}
pub fn set_int_param(ctx: Context, value: isize) {
unsafe { SetIntParam(ctx, value) };
}
pub fn get_cleo_folder() -> std::path::PathBuf {
get_directory_path(Directory::CLEO)
}
pub fn get_cwd() -> std::path::PathBuf {
let mut buf = [0i8; 256];
unsafe { GetCwd(buf.as_mut_ptr()) };
std::path::Path::new(&to_rust_string(buf.as_ptr())).into()
}
pub fn resolve_path(path: &str) -> std::path::PathBuf {
let mut dest = [0i8; 256];
unsafe { ResolvePath(sz!(path), dest.as_mut_ptr()) };
std::path::Path::new(&to_rust_string(dest.as_ptr())).into()
}
pub fn get_float_param(ctx: Context) -> f32 {
unsafe { GetFloatParam(ctx) }
}
pub fn set_float_param(ctx: Context, value: f32) {
unsafe { SetFloatParam(ctx, value) };
}
pub fn update_compare_flag(ctx: Context, value: bool) {
unsafe { UpdateCompareFlag(ctx, value) }
}
pub fn get_host_name() -> String {
let mut buf = [0i8; SDK_STRING_MAX_LEN];
unsafe { GetHostName(buf.as_mut_ptr(), SDK_STRING_MAX_LEN as _) };
to_rust_string(buf.as_ptr())
}
pub fn set_host_name(value: String) {
unsafe { SetHostName(sz!(value)) };
}
pub fn runtime_init() {
unsafe { RuntimeInit() }
}
pub fn runtime_next_tick(current_time: u32, time_step: i32) {
unsafe { RuntimeNextTick(current_time, time_step) }
}
pub fn to_rust_string(addr: *const i8) -> String {
unsafe {
std::ffi::CStr::from_ptr(addr)
.to_owned()
.into_string()
.unwrap_or_default()
}
}
#[allow(dead_code)]
pub fn register_loader(glob: &str, cb: CustomLoader) {
unsafe {
RegisterLoader(sz!(glob), cb);
}
}
#[allow(dead_code)]
pub fn alloc_mem(size: usize) -> *mut c_void {
unsafe { AllocMem(size) }
}
#[allow(dead_code)]
pub fn free_mem(ptr: *mut c_void) {
unsafe { FreeMem(ptr) }
}
#[allow(dead_code)]
pub fn on_before_scripts(cb: OnTickCallback) {
unsafe {
OnBeforeScripts(cb);
}
}
#[allow(dead_code)]
pub fn on_after_scripts(cb: OnTickCallback) {
unsafe {
OnAfterScripts(cb);
}
}
#[allow(dead_code)]
pub fn on_runtime_init(cb: OnRuntimeInitCallback) {
unsafe {
OnRuntimeInit(cb);
}
}
#[allow(dead_code)]
pub fn on_show_text_box(cb: OnShowTextBoxCallback) {
unsafe {
OnShowTextBox(cb);
}
}
#[allow(dead_code)]
pub fn get_directory_path(dir: Directory) -> std::path::PathBuf {
let mut buf = [0i8; 256];
unsafe { GetDirectoryPath(dir, buf.as_mut_ptr()) };
std::path::Path::new(&to_rust_string(buf.as_ptr())).into()
}
#[allow(dead_code)]
pub fn get_cleo_version() -> String {
let mut buf = [0i8; 256];
unsafe { GetCLEOVersion(buf.as_mut_ptr()) };
to_rust_string(buf.as_ptr())
}
#[allow(dead_code)]
pub fn get_symbol_address(symbol: &str) -> usize {
unsafe { GetSymbolAddress(sz!(symbol)) }
}
#[allow(dead_code)]
pub fn get_number_of_active_cs_scripts() -> usize {
unsafe { GetNumberOfActiveCSScripts() }
}
#[allow(dead_code)]
pub fn get_number_of_active_js_scripts() -> usize {
unsafe { GetNumberOfActiveJSScripts() }
}
#[allow(dead_code)]
pub fn is_end_of_arguments(ctx: Context) -> bool {
unsafe { IsEndOfArguments(ctx) }
}
#[allow(dead_code)]
pub fn trigger_event(name: &str, data: &str) {
unsafe { TriggerEvent(sz!(name), sz!(data)) }
}