Expand description
Resolve struct field offsets, module globals, Source 2 interfaces and button addresses at runtime with compile-time literal fallbacks.
Declare modules with the attribute macros below. When the runtime feature is
enabled and init has been called with a Process implementation, the
generated accessors return live values from the target process. Without the
feature (or before init), they return the declared literal.
The crate supports #![no_std] + alloc.
§Using With MinHook
dynoffsets does not provide a hook engine. It resolves runtime addresses;
a library such as MinHook installs the detour.
The usual flow is:
- Resolve a live interface pointer with
interfaces. - Read the vtable slot for the method you want to hook.
- Pass that function entry address to MinHook.
schema and globals usually resolve data addresses rather than hook
targets, so interfaces is the most common fit for MinHook-based setups.
use core::{ffi::c_void, mem, ptr};
use dynoffsets::interfaces;
use minhook_sys::{MH_CreateHook, MH_EnableHook, MH_Initialize, MH_OK};
#[interfaces("engine2.dll")]
mod engine2 {
pub const Source2EngineToClient001: usize = 0;
}
type TargetFn = unsafe extern "system" fn(this: *mut c_void, arg: i32) -> i32;
static mut ORIGINAL_TARGET: Option<TargetFn> = None;
unsafe extern "system" fn hk_target(this: *mut c_void, arg: i32) -> i32 {
let original = ORIGINAL_TARGET.expect("hook not installed");
original(this, arg)
}
unsafe fn vfunc(instance: usize, index: usize) -> *mut c_void {
let vtable = *(instance as *const *const usize);
*vtable.add(index) as *mut c_void
}
unsafe fn install_hook() {
let iface = engine2::Source2EngineToClient001();
assert_ne!(iface, 0, "interface was not resolved");
let target = vfunc(iface, 42);
assert_eq!(MH_Initialize(), MH_OK);
let mut original = ptr::null_mut();
assert_eq!(
MH_CreateHook(target, hk_target as *mut c_void, &mut original),
MH_OK,
);
ORIGINAL_TARGET = Some(mem::transmute(original));
assert_eq!(MH_EnableHook(target), MH_OK);
}The same pattern works for exported functions when your backend can resolve the function entry address.
Structs§
- Populate
Stats - Runtime
Buttons - Button name → address of its
state: u32field, walked from the liveg_pButtonListlinked list in client.dll. - Runtime
Globals - Live globals from pattern scan; None on signature miss.
- Runtime
Interfaces - Map of module → interface name → instance pointer obtained by walking
each module’s
CreateInterfaceregistration list.
Traits§
- Process
- Memory access trait for the runtime dumper.
Functions§
- discover_
buttons - Walk the live
KeyButtonlinked list inclient.dlland collect button name →&statemappings. - discover_
globals - Discover engine globals via patterns (for #[globals] macro).
- discover_
interfaces - Walk
CreateInterfaceregistration chains for all known CS2 modules and return the collected interface instances. - discover_
interfaces_ in - Walk
CreateInterfacefor a caller-provided list of modules. - fnv1a
- FNV-1a 32-bit hash (const-eval).
- get_
runtime_ buttons - Returns the discovered button state addresses from client.dll’s KeyButton list.
- get_
runtime_ globals - Returns the lazily-discovered global pointers (pattern scan).
- get_
runtime_ interfaces - Returns the discovered Source 2 interfaces (via CreateInterface chains).
- init
- Register the process backend used by all runtime accessors.
- is_
initialized - Returns
trueafterinithas been called. - lookup_
or_ fallback - Internal helper used by the
#[schema]macro. - lookup_
or_ fallback_ h - Hash-keyed variant of
lookup_or_fallback. - populate
- Populates registered
r#staticslots via live discovery (or no-op). Returns per-category counts. SeePopulateStats. - try_
lookup_ offset - Internal helper used by the cached
#[schema]accessor. - try_
lookup_ offset_ h - Hash-keyed variant of
try_lookup_offset.
Type Aliases§
- Slot
(name, &AtomicUsize)for ar#staticslot.
Attribute Macros§
- buttons
#[buttons]/#[buttons(r#static)]- globals
#[globals]/#[globals(r#static)]- interfaces
#[interfaces]/#[interfaces("dll")]/#[interfaces(false)]/#[interfaces(..., r#static)]- schema
#[schema]/#[schema("client.dll")]/#[schema(false)]/#[schema(..., r#static)]/#[schema(hashed)]