Bridge / API

The bridge layer is an open-source abstraction that lets server owners customize data providers, hooks, and third-party integrations without modifying core code.

Open Source: The bridge/ folder is fully open-source and editable. The rest of the resource (client/, server/, web/) is obfuscated.

Architecture

The bridge system uses two global Lua tables:

TableSideFilePurpose
BridgeClientbridge/client.luaLocation system, plate hit handler, NUI interaction hooks
BridgeServerServerbridge/server.luaData providers, dispatch hooks, radar integration

The core system calls bridge functions at specific points. If a bridge function returns data, the core uses it. If it returns nil, the core falls back to default behavior.

Server Bridge Functions

Override these functions in bridge/server.lua to customize server-side behavior.

Data Provider Hooks

FunctionParametersReturnsDescription
BridgeServer.GetPersonProfileExtras(citizenid) citizenid: string table or nil Add extra fields to person profiles (e.g., mugshot URL, physical description)
BridgeServer.GetPhysicalDescription(citizenid) citizenid: string string or nil Return a text description of the person's appearance
BridgeServer.GetVehicleExtras(plate) plate: string table or nil Add extra fields to vehicle profiles (e.g., insurance status, mods)

Dispatch Hooks

FunctionParametersDescription
BridgeServer.OnCallCreated(callData) callData: table Called when a new dispatch call is created. Use for external integrations (Discord webhooks, etc.)
BridgeServer.OnUnitAssigned(callId, unitData) callId: number, unitData: table Called when a unit is assigned to a call
BridgeServer.OnCallClosed(callData) callData: table Called when a dispatch call is closed
Example: Discord Webhook on Call Created
function BridgeServer.OnCallCreated(callData)
    -- Send a Discord webhook when a new dispatch call is created
    local embed = {
        title = callData.code .. ' - ' .. callData.title,
        description = callData.description or 'No description',
        color = callData.priority == 3 and 16711680 or 16776960,
        fields = {
            { name = 'Location', value = callData.location or 'Unknown', inline = true },
            { name = 'Priority', value = tostring(callData.priority), inline = true },
        },
    }
    -- PerformHttpRequest(webhookUrl, function() end, 'POST', json.encode({embeds = {embed}}), {['Content-Type'] = 'application/json'})
end

Radar / ALPR Integration (wk_wars2x)

The bridge includes built-in integration with wk_wars2x (Wraith ARS 2X) for automatic plate scanning and alert generation.

Optional: This integration only activates if wk_wars2x is running on your server. The MDT works fine without it.

How It Works

  1. Officer activates the radar/ALPR in their vehicle (wk_wars2x)
  2. When a plate is scanned, wk_wars2x fires the wk:onPlateScanned event
  3. The bridge intercepts this event and calls BridgeServer.OnPlateScanned()
  4. The server checks the plate against:
    • Vehicle Flags — Active flags in computer_vehicle_flags table (stolen, BOLO, wanted, etc.)
    • Active BOLOs — Any active BOLO in computer_bolos that matches the plate
  5. If a hit is found, the server sends an alert to the scanning officer
  6. The plate reader automatically locks onto the flagged plate
  7. The client shows a notification and optionally forwards the hit to the MDT UI

Server-side Functions

bridge/server.lua - Radar Functions
--- Called when wk_wars2x scans a plate
--- @param source number Player server ID
--- @param cam string Camera name ('front' or 'rear')
--- @param plate string The scanned plate (trimmed, uppercase)
--- @param index number Plate reader index
function BridgeServer.OnPlateScanned(source, cam, plate, index)
    -- Checks plate against vehicle flags + active BOLOs
    -- Sends hit to officer if found
    -- Auto-locks the plate reader
end

--- Lock/unlock the plate reader on a specific camera
--- @param source number Player server ID
--- @param cam string Camera name
function BridgeServer.LockPlateReader(source, cam)
    -- Uses wk_wars2x TogglePlateLock export
end

Client-side Functions

bridge/client.lua - Plate Hit Handler
--- Called when a plate hit is received from the server
--- @param hit table { plate, flags, bolos }
function Bridge.OnPlateHit(hit)
    -- Default behavior:
    -- 1. Show lib.notify with plate and flag/BOLO details
    -- 2. Forward hit data to MDT NUI (plateHit message)
    -- 3. Play alert sound
end

Customizing Radar Behavior

You can override the default radar functions to customize alerts:

Example: Custom Alert with Sound
-- In bridge/client.lua, override OnPlateHit:
function Bridge.OnPlateHit(hit)
    -- Custom notification
    lib.notify({
        title = 'ALPR HIT',
        description = ('Plate: %s | Flags: %d | BOLOs: %d'):format(
            hit.plate,
            #(hit.flags or {}),
            #(hit.bolos or {})
        ),
        type = 'error',
        duration = 10000,
    })

    -- Forward to MDT
    SendNUIMessage({ action = 'plateHit', data = hit })

    -- Custom sound
    PlaySoundFrontend(-1, 'CONFIRM_BEEP', 'HUD_MINI_GAME_SOUNDSET', true)
end

Client Bridge Functions

Location System

FunctionParametersReturnsDescription
Bridge.GetCurrentLocationData() none table { street, area, coords } Returns the player's current location data for dispatch calls. Uses GTA native street/zone names by default.
Example: Custom Location Provider
-- Override in bridge/client.lua
function Bridge.GetCurrentLocationData()
    local coords = GetEntityCoords(cache.ped)
    local streetHash, crossHash = GetStreetNameAtCoord(coords.x, coords.y, coords.z)
    local street = GetStreetNameFromHashKey(streetHash)
    local zone = GetNameOfZone(coords.x, coords.y, coords.z)
    local area = GetLabelText(zone)

    return {
        street = street,
        area = area,
        coords = { x = coords.x, y = coords.y, z = coords.z },
    }
end

File Loading Order

The bridge files load in a specific order defined in fxmanifest.lua:

Loading Order
1. shared/config/*.lua          -- All config files
2. bridge/server.lua            -- Server bridge (BridgeServer table)
3. bridge/client.lua            -- Client bridge (Bridge table)
4. server/modules/*.lua         -- Core server modules
5. server/*.lua                 -- Core server scripts
6. client/*.lua                 -- Core client scripts
Bridge files load before core scripts, so all bridge functions are available when the core initializes.