Hooks and server actions
Client and server hooks that replace bridge presets, client routines the server can trigger, and secured Config.ServerActions with their ctx context.
Goal: plug your own code where no preset fits, and create server-checked actions.
Files: config_client.lua (Config.ClientHooks) and config_server.lua (Config.ServerHooks, Config.ServerActions).
How hooks work
A defined hook replaces the matching preset: the bridge calls your function and no longer runs the preset code. Leave a hook nil (undefined) to keep the preset chosen in config.lua. Server hooks are called after the engine checks: no need to re-check the permission of the action that triggers them.
Some hooks also change an option’s availability: defining SendBill, GiveVehicleKeys or RestoreAppearance makes the matching option available even with the selector set to 'custom'.
Notable exception: with Config.Medical.nativeHealFallback = true, the extra native heal applies after your HealSelf or HealPlayer hook.
Client hooks
| Hook | Signature | Returns | Usage |
|---|---|---|---|
Notify | Config.ClientHooks.Notify(message, ntype, duration) | nothing | Every client notification. ntype: info, success, error, warning, primary. |
TextInput | Config.ClientHooks.TextInput(title, label, maxLength) | the typed string or nil | /me, forced emote, forced /me. |
InputDialog | Config.ClientHooks.InputDialog(title, rows) | an array of values or nil (ox_lib inputDialog format) | Invoice form. |
Confirm | Config.ClientHooks.Confirm(title, text) | true to confirm; any other value counts as refusal | Rock Paper Scissors invitation. |
ProgressBar | Config.ClientHooks.ProgressBar(data) | true when completed; any other value counts as cancelled | Lockpick, native repair, tyre slash, trunk (ox_lib progressBar format). |
ShowTextUI | Config.ClientHooks.ShowTextUI(text) | nothing | Text shown inside the trunk. |
HideTextUI | Config.ClientHooks.HideTextUI() | nothing | Hides the trunk text. |
GetPlayerJob | Config.ClientHooks.GetPlayerJob() | { name = 'police', grade = 2 } or nil | Display jobs filters, billing, lockpick, repair. |
HasItem | Config.ClientHooks.HasItem(itemName, count) | boolean | Lockpick and repair display (required item). |
PlayEmote | Config.ClientHooks.PlayEmote(emote) | nothing | emote type, copy and forced emote. |
PlaySharedEmote | Config.ClientHooks.PlaySharedEmote(emote, targetServerId) | nothing | shared_emote type. |
GetCurrentEmote | Config.ClientHooks.GetCurrentEmote() | emote name (string) or nil | Answers emote copy requests. |
CancelEmote | Config.ClientHooks.CancelEmote() | nothing | Emote cancel. |
Me | Config.ClientHooks.Me(text) | nothing | Typed and forced /me and RPS announcement. |
ReviveSelf | Config.ClientHooks.ReviveSelf() | nothing | self_revive with selfMode = client. |
HealSelf | Config.ClientHooks.HealSelf() | nothing | self_heal with selfMode = client. The extra native heal then applies when enabled. |
GiveVehicleKeys | Config.ClientHooks.GiveVehicleKeys(vehicle, plate, model) | nothing | give_keys. Makes the give_keys option available. |
LockpickVehicle | Config.ClientHooks.LockpickVehicle(vehicle) | true when successful; the vehicle is then unlocked | Replaces the lockpick progress bar, after server validation. |
RepairVehicle | Config.ClientHooks.RepairVehicle(vehicle) | false to report a failure; any other value shows repair_done | repair_vehicle, after server validation. |
OnTrunkEnter | Config.ClientHooks.OnTrunkEnter(vehicle) | nothing | After entering the trunk. |
OnTrunkExit | Config.ClientHooks.OnTrunkExit(vehicle) | nothing | After leaving the trunk (vehicle may be nil). |
SendBill | Config.ClientHooks.SendBill(targetServerId, reason, amount, job) | nothing | send_bill. Makes the send_bill option available. |
RestoreAppearance | Config.ClientHooks.RestoreAppearance() | false to report a failure | dev_restore_appearance. Makes the dev_restore_appearance option available. |
SetLocalRain | Config.ClientHooks.SetLocalRain(enabled) | nothing | Local tools: enabled = true turns rain on. Makes the weather menu available client side. |
SetLocalFreeze | Config.ClientHooks.SetLocalFreeze(state) | nothing | Local tools. Makes the weather menu available client side. |
Server hooks
| Hook | Signature | Returns | Usage |
|---|---|---|---|
Notify | Config.ServerHooks.Notify(source, message, ntype, duration) | nothing | Notifications sent by the server. |
HasGroup | Config.ServerHooks.HasGroup(source, group) | true when the player belongs to the group | admin/staff levels and group lists. |
GetPlayerJob | Config.ServerHooks.GetPlayerJob(source) | { name = 'mechanic', grade = 0 } or nil | jobs check of server actions. |
HasItem | Config.ServerHooks.HasItem(source, item, count) | true when owned | item check of server actions. |
RemoveItem | Config.ServerHooks.RemoveItem(source, item, count) | nothing | Repair with removeItem = true. |
RevivePlayer | Config.ServerHooks.RevivePlayer(source, targetId) | false to report a failure | admin_revive and self_revive with selfMode = server. |
HealPlayer | Config.ServerHooks.HealPlayer(source, targetId) | ignored: heal_sent is always shown | admin_heal and self_heal with selfMode = server. |
ForceMe | Config.ServerHooks.ForceMe(source, targetId, text) | nothing | force_me; without a hook, the targeted client runs Bridge.Me. |
SetWeather | Config.ServerHooks.SetWeather(zone, weather) | false to report a failure | zone is nil when useZones = false. Makes weather actions available server side. |
SetTime | Config.ServerHooks.SetTime(hour, minute) | false to report a failure | Time presets. |
FreezeTime | Config.ServerHooks.FreezeTime(state) | false to report a failure | Freeze ON/OFF. |
SetBlackout | Config.ServerHooks.SetBlackout(state) | false to report a failure | Blackout ON/OFF/Toggle. |
GetBlackout | Config.ServerHooks.GetBlackout() | boolean | Blackout toggle and info. |
GenerateWeathers | Config.ServerHooks.GenerateWeathers() | false to report a failure | Random weather. |
GetTime | Config.ServerHooks.GetTime() | { hour = 12, minutes = 0, seconds = 0 } or nil | Time info and av_weather preset freeze. |
GetZoneInfo | Config.ServerHooks.GetZoneInfo(zone) | { zone, weather, fog, temperature, wind } or nil | Active zone info. |
OnSuspiciousActivity | Config.ServerHooks.OnSuspiciousActivity(source, reason) | nothing | Suspiciously rejected request; replaces the logSuspicious console output. |
OnActionExecuted | Config.ServerHooks.OnActionExecuted(source, actionName, ctx) | nothing | After every server action executed without error. |
Example: custom notifications
my_notify is an example resource name.
Config.ClientHooks.Notify = function(message, ntype, duration)
exports['my_notify']:Show(message, ntype, duration)
end
Config.ServerHooks.Notify = function(source, message, ntype, duration)
TriggerClientEvent('my_notify:show', source, message, ntype, duration)
end
Client routines
The server can run a whitelisted client routine: TriggerClientEvent('ox_target:core:run', id, '<Routine>', ...). Routines documented by the archive: PlayEmote(emote), Me(text), ReviveSelf(), HealSelf(), NativeRevive(), NativeHeal(). They go through the bridge, hence through your client hooks. PlayEmote re-validates the name with Config.Emotes; Me truncates to 120 characters.
Config.ServerHooks.RevivePlayer = function(source, targetId)
TriggerClientEvent('ox_target:core:run', targetId, 'NativeRevive')
end
Custom server actions
An action declared in Config.ServerActions is called by a type = 'server_action' option. The engine runs its checks, then your handler(ctx).
| Field | Values | Effect |
|---|---|---|
permission |
Config.Permissions key, 'everyone', 'staff', 'admin', list of groups, false or function(source) |
Absent: everyone. |
jobs |
{ 'police' }, { police = 2 }, 'police' |
Job checked server side. |
item, itemCount |
item name, integer (1 by default) | Ownership checked server side; nothing is removed automatically. |
feature |
Config.Features key |
Refused when the feature is false. |
target |
'none' (default), 'player', 'vehicle', 'entity' |
Expected and checked target type. |
allowSelf |
boolean | With target = 'player', allows targeting yourself. |
maxDistance |
metres, or false |
false: unlimited. Absent: Config.Distances.default. Security.distanceTolerance is added. |
cooldown |
ms | Absent: Config.Security.actionCooldown. |
args |
list of rules | Schema of the arguments sent by the client. |
handler |
function(ctx) |
Required. Without it, the action is refused at registration. |
Built-in action names (admin_revive, weather_set…) cannot be reused.
Argument rules
| Type | Options |
|---|---|
{ type = 'string' } |
min (1 by default), max (255 by default), pattern (Lua pattern), oneOf ({ value = true }). Leading and trailing spaces are removed. |
{ type = 'number' } |
min, max, integer = true. NaN and infinities are refused. |
{ type = 'boolean' } |
— |
{ type = 'vector3' } |
Accepts a vector3 or an { x, y, z } table. |
Every rule accepts optional = true. A missing non-optional or invalid argument makes the request refused (invalid_input) and reports it as suspicious.
ctx object
| Field | Content |
|---|---|
ctx.source |
Server ID of the player who triggered the action. |
ctx.action |
Action name. |
ctx.args |
Validated arguments (list). |
ctx.target, ctx.targetPed |
With target = 'player': server ID and ped of the target. |
ctx.entity, ctx.netId |
With target = 'vehicle' or 'entity': server entity and network ID. |
ctx.notify(message, ntype) |
Notifies the source player. |
ctx.notifyTarget(message, ntype) |
Notifies the targeted player (when target = 'player'). |
ctx.runClient(routine, ...) |
Runs a client routine on the source player. |
ctx.runClientOn(id, routine, ...) |
Runs a client routine on another player. |
Full example
Server side (config_server.lua); my_script:showLicense is an example name:
Config.ServerActions = {
check_license = {
permission = 'everyone',
jobs = { 'police' },
target = 'player',
maxDistance = 3.0,
cooldown = 2000,
args = { { type = 'string', oneOf = { quick = true, full = true } } },
handler = function(ctx)
TriggerClientEvent('my_script:showLicense', ctx.target, ctx.source, ctx.args[1])
ctx.notify('Request sent.', 'success')
end,
},
}
Client side (config_interactions.lua):
{ name = 'check_license', label = 'Check papers', icon = 'fa-solid fa-id-card', jobs = { 'police' }, type = 'server_action', action = 'check_license', args = { 'quick' } },
The client sends the target’s server ID for the Players and Self lists, and the entity network ID for the other lists. Choose target accordingly.
Logging
Config.ServerHooks.OnActionExecuted = function(source, actionName, ctx)
print(('[ox_target] %s used %s'):format(GetPlayerName(source), actionName))
end
Other resources can register actions with exports.ox_target:registerAction.
Common mistakes
- Action without
permission: allowed to everyone, rarely what you want for a sensitive action. target = 'player'on a vehicle option: the request sends a network ID, refused as a nonexistent player target.- Empty hook
function() end: the preset is replaced by a function that does nothing. - Handler that changes money or inventory without re-checking amounts: the engine validates the declared types and bounds, not the business logic.