natives
Call game natives, inspect argument mapping, and register native hooks.
Named calls
Harmony generates the Lua native catalogue from src/rage/invoker/natives_raw.inl. This audited source contains 7,131 definitions across 86 namespaces, including two variadic helpers. The complete declared signatures are in the native catalogue.
lua
local page = menu.root("Local coordinates")
page:button("Log my coordinates", function()
local ped = natives.player.player_ped_id()
if ped == 0 then
util.log("The local ped is unavailable")
return
end
local position = natives.entity.get_entity_coords(ped, true, false)
util.log(string.format("Position: %.2f, %.2f, %.2f",
position.x, position.y, position.z))
end)Namespaces exist with their catalogue spelling, which is lowercase, and an all-uppercase alias. Function-name lookup is case-insensitive. For example, natives.player.player_ped_id() and natives.PLAYER.PLAYER_PED_ID() address the same definition. Mixed-case namespace names are not added. Leading underscores in native names are significant and must be retained.
Native functions are created lazily. Iterating a namespace with pairs() does not enumerate the complete catalogue. Use the generated reference for discovery and natives.count for its definition count.
Bridge reference
natives.count
Number of generated definitions.
text
natives.countReturns: Integer
natives.available
Whether a native handler is registered for the supplied 64-bit hash.
text
natives.available(hash)Returns: Boolean
natives.call
Generic native invocation; caller supplies the known ABI.
text
natives.call(hash, return_type, ...)Returns: Requested result
natives.i64
Explicit 64-bit argument bits from an exact integer or unsigned decimal/hex string.
text
natives.i64(value)Returns: NativeValue
natives.f32
Explicit finite 32-bit float argument representation.
text
natives.f32(value)Returns: NativeValue
natives.call() accepts exactly these lowercase return-type strings:
| Return type | Lua result |
|---|---|
"void" | nil |
"bool" | Boolean |
"int" | Signed 32-bit integer |
"uint" | Unsigned 32-bit integer |
"int64" | Signed 64-bit integer |
"float" | Number decoded from a 32-bit float |
"string" | Copied string or nil for a null address |
"pointer" | Borrowed Pointer; check :is_null() |
"vec3" | Vector value |
natives.available() checks handler presence only. It does not validate argument meaning, output-buffer sizes, game state, or whether a call is permitted by the Lua bridge. In particular, WAIT is rejected even when its handler exists.
Argument and result mapping
| Declared native type | Lua argument/result mapping |
|---|---|
int, Player, Ped, Entity, Vehicle, and other handle aliases | Signed 32-bit integer. |
Hash, uint, unsigned int | Unsigned 32-bit integer. |
float | Finite number converted to a 32-bit float. |
BOOL, bool | Use a Lua boolean; return value is boolean. |
const char* | Lua string or nil as an input; copied string or nil as a result. |
Other pointer types, such as int*, Any*, or Vector3* | Pointer or nil as input; borrowed Pointer as result. |
Vector3 result | vec3, with native padded-result conversion handled by the bridge. |
Any input | Dynamically marshalled value; the caller must know the native's real ABI. |
Any named result | Signed 32-bit result in this catalogue, not an arbitrary Lua object. |
Args... | Variadic tail; the fixed prefix remains required. |
For dynamic arguments, booleans become zero/one, strings supply their string address, Pointer supplies its address, Lua integers supply integer bits, non-integer numeric values use float representation, and nil supplies zero. Use the explicit wrappers when the known ABI requires a specific representation. Do not infer an undocumented Any parameter's meaning from this conversion behavior.
Named wrappers validate argument counts; the two variadic definitions validate their required prefix. The invoker accepts at most 100 argument slots. Returned strings must be terminated within the 4,096-byte copy limit. A null pointer result is still a Pointer object, so testing only if pointer then is insufficient.
Out-parameters are not automatically allocated, converted into multiple returns, or checked against a native's full output layout. The caller must supply a correctly sized buffer for a verified ABI. Borrowed game pointers and retained string/buffer arguments require explicit lifetime care. Prefer the named wrappers when a verified definition exists; generic calls do not discover or correct an ABI.
The catalogue includes functions whose semantics are unknown, including hash-named entries and parameters such as p0. Those names are preserved in the native catalogue; their purpose remains undocumented.
Native hooks
natives.hook(game_script, hash, callback[, options]) -> id registers a hook for one game script name through Harmony's existing native-hook manager. Registration takes effect on that program's next VM dispatch. natives.unhook(id) -> boolean removes a hook owned by the calling Lua script. Unload and callback failure remove all owned hooks; active VM scopes restore their original native-table entries before returning.
The original native runs by default. callback(event) is an observation delivered on a later Lua update, not a synchronous replacement function. Its return value is ignored. No Lua executes inside the native detour. The copied event contains hook, hash, arguments (1-based raw 64-bit argument slots), result (first raw 64-bit return slot), and blocked. Pointer-valued slots are addresses only; pointed-to memory is not copied or kept alive.
Optional settings apply synchronously in the detour:
| Setting | Behavior |
|---|---|
arguments = { [index] = value } | Replace selected 1-based scalar argument slots before the original call. |
return_value = value | Replace the first scalar return slot after the original call. |
block = true | Skip the original and return return_value, or zero when omitted. |
Override values accept integers, booleans, fractional numbers, natives.i64(...), and natives.f32(...). Use f32 for integral float values. String/pointer overrides and vector return overrides are not supported. Use only signatures whose complete ABI and effects you understand. If an override names an argument beyond the actual call count, the original runs without overrides or an observation.
natives.as_f32(bits) and natives.as_i32(bits) decode raw observed slots. Exact hashes can be hexadecimal strings. Duplicate hooks on the same game-script/native pair, including Harmony's own hooks, are rejected. WAIT hooks are prohibited. Limits: 32 hooks globally and 128 queued observations; overflow drops observations without changing the native's behavior. natives.hook_dropped() reports the cumulative drop count. A registered hook can remain inactive if the named game script does not execute that native. Calls made through Harmony's native invoker do not pass through a game's program table.
lua
-- Supply a verified game script name and native hash for the supported build.
local function observe_native(gameScript, nativeHash)
return natives.hook(gameScript, nativeHash, function(event)
util.log("Native result bits: " .. tostring(event.result))
end)
end
-- local id = observe_native(gameScript, nativeHash)
-- natives.unhook(id)