Integrations
Editable bridges live in bridge/. Keep changes narrowly scoped to the installed provider and preserve server-side authorization. For grants, possession checks, removals, and radial-menu actions, use Exports.
Framework and inventory
Framework and inventory bridges register from resource-state checks. Start the selected providers before Carlock and restart Carlock after changing providers. Do not run several unrelated inventory backends and rely on file load order to select one.
The seven included inventory adapters and their item installation paths are listed under Dependencies and Installation. Physical item use is slot-aware: the server verifies the actual key item/plate rather than trusting client-supplied metadata.
For custom garages or ownership schemas, review the current ownership lookup and your purchase/spawn integration. Do not substitute HasKey for ownership: keys are transferable bearer access, while ownership comes from framework database records.
Dispatch
Configure policeAlerts in shared config:
policeAlerts = {
-- Keep the remaining existing policeAlerts fields.
enabled = true,
provider = 'auto',
},
This excerpt shows only the selector; do not replace the full table with it.
| Selector | Behavior |
|---|---|
auto | First started supported provider: Wasabi MDT V2, PS, CD; otherwise internal |
wasabi_mdt_v2 | Checks resource wasabi_mdt_v2; adapter calls exports.wasabi_mdt:CreateDispatch |
ps or ps-dispatch | Server event ps-dispatch:server:notify |
cd or cd_dispatch | Hands the validated alert to the client CD dispatch adapter |
internal | Notifies players matching policeAlerts.jobs through the framework bridge |
An unsupported or stopped explicitly selected provider falls back to internal dispatch with a warning. A provider error/rejection after submission is not retried through another provider, to avoid duplicate calls.
Wasabi MDT V2 owns department delivery; the adapter marks the external origin to avoid its PS/CD relay. Carlock's jobs list is not a guarantee that an external MDT will use identical recipient filtering. The server skips alerts when the acting player matches its configured police groups. Probability and rate limits also affect alerts.
Custom minigames
- In
config/shared/config.lua, set the desiredminigamesentry'sproviderto'custom'. - Implement the matching function in
bridge/minigames/client.lua:hooks.lockpick(context)hooks.hotwireHighEnd(context)hooks.hotwireStandard(context)
- Return
truefor success,falsefor failure, ornilfor cancellation/unavailability. The shipped placeholder functions returnnil; selectingcustomalone does not install a game. - Register cleanup for your external UI. Respect
context.isCancelled()and the configured duration.
Example: ox_lib skill check
Replace the existing hooks.lockpick function in the bridge, keeping the file's hooks table and module registration:
function hooks.lockpick(context)
if lib.skillCheckActive() or context.isCancelled() then return nil end
context.onCleanup(function()
if lib.skillCheckActive() then lib.cancelSkillCheck() end
end)
return lib.skillCheck({ 'easy', 'medium' }, { 'w', 'a', 's', 'd' })
end
The context provides kind, mode, difficulty, vehicle, netId, plate, ped, minimumDuration, duration, isCancelled, and onCleanup. mode/difficulty depend on the action. Durations are milliseconds. The adapter rejects late/stale results and applies its timing window; it does not make an arbitrary custom client minigame result independently authoritative. Do not call internal reward/grant events yourself.
Client listeners
Edit the existing functions in bridge/listeners/client.lua. These are same-resource Lua hooks, not exported functions or network event names.
| Function | Arguments | Purpose |
|---|---|---|
onVehicleLockUpdate | locked, vehicle | Legacy accepted-lock notification; not proof of native application |
onHazardsChanged | vehicle, enabled | Observed hazards readback change on an applying streamed client |
onLockStateChanged | vehicle, locked | Observed lock change on the requesting client |
onEngineStateChanged | vehicle, running | Observed engine change from local Carlock application |
onLightStateChanged | vehicle, lightMode | Readback mode: off, low, or high |
onDoorStateChanged | vehicle, doorIndex, open | Door readback crosses the open/closed threshold; indices 0–3 doors, 4 hood, 5 trunk |
onVehicleLockSound | locked, vehicle | Custom lock sound on nearby recipients; play locally, do not rebroadcast |
onVehicleAlarm | vehicle, duration, action | Custom theft alarm; action is hotwire or lockpick |
onLockpickComplete | success, vehicle, plate | Accepted lockpick completion |
onHotwireComplete | success, vehicle, plate, mode | Accepted hotwire completion; mode is wires or hacking |
onVehicleSearchComplete | vehicle, plate, reward | Accepted search completion; reward table or false |
isPlayerDead | None | Return a boolean for your death/incapacitation system |
Vehicle arguments are local entity handles. Observed-state hooks are not global vehicle watchers or guaranteed cross-client broadcasts: changes can coalesce, and stale contexts/readback timeouts are skipped. Use your HUD's supported API without feeding these hooks back into another Carlock mutation.
For custom audio, select locking.sound.provider = 'custom' or policeAlerts.vehicleAlarm.provider = 'custom' and implement the matching hook. Keep sound URLs/volume in your own configuration. Stop custom alarms after the supplied duration.
Server listeners
Edit bridge/listeners/server.lua:
function listeners.onKeyGranted(source, plate)
-- Your server-side integration after a successful key grant.
end
function listeners.onKeyRemoved(source, plate)
-- Your server-side integration after a complete removal.
end
function listeners.onKeyTransferred(source, target, plate, removedFromGiver)
-- Your server-side integration after a completed transfer.
end
source/target are server IDs, plate is a string, and removedFromGiver is a boolean. These notifications are not veto/permission callbacks and should not be used as a replacement for authorizing the initiating action. Individual operations may have their own hook behavior; do not assume every inventory move or locksmith operation emits these notifications.
Legacy events
The supported vehiclekeys:client:SetOwner compatibility event is described on the exports page. Other callbacks and events coordinate internal action tokens, inventory contexts, UI, or synchronization. In particular, legacy updateVehicle claims of hotwired, failed, or searched are rejected, and the legacy search callback does not grant rewards. Use public exports and editable hooks rather than constructing these internal payloads.