Skip to content

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.count

Returns: 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 typeLua 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 typeLua argument/result mapping
int, Player, Ped, Entity, Vehicle, and other handle aliasesSigned 32-bit integer.
Hash, uint, unsigned intUnsigned 32-bit integer.
floatFinite number converted to a 32-bit float.
BOOL, boolUse 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 resultvec3, with native padded-result conversion handled by the bridge.
Any inputDynamically marshalled value; the caller must know the native's real ABI.
Any named resultSigned 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:

SettingBehavior
arguments = { [index] = value }Replace selected 1-based scalar argument slots before the original call.
return_value = valueReplace the first scalar return slot after the original call.
block = trueSkip 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)