# Bridge System

***

### 📂 File Structure

| File         | Side   | Responsibility                                                             |
| ------------ | ------ | -------------------------------------------------------------------------- |
| `Detect.lua` | Shared | Detects the active framework and inventory at runtime.                     |
| `Shared.lua` | Shared | Provides utility functions used on both client and server.                 |
| `Server.lua` | Server | Implements server-side abstractions (player, items, money, callbacks).     |
| `Client.lua` | Client | Implements client-side abstractions (notifications, callbacks, targeting). |

***

### 🔍 Detect.lua

Performs runtime detection of the active framework and inventory system.

#### Resource State Helper

```lua
local function ResourceStarted(name)
    return GetResourceState(name) == 'started' or GetResourceState(name) == 'starting'
end
```

A small helper that returns `true` when a given resource is either fully started or currently starting up.

#### Framework Detection

```lua
local function DetectFramework()
    if Config.Framework and Config.Framework ~= 'auto' then
        return Config.Framework
    end
    if ResourceStarted('qbx_core')    then return 'qbox'   end
    if ResourceStarted('qb-core')     then return 'qbcore' end
    if ResourceStarted('es_extended') then return 'esx'    end
    return 'qbcore'
end
```

**Resolution order:**

1. If the user has explicitly set `Config.Framework`, that value is used.
2. Otherwise, detection follows the priority `qbx_core` → `qb-core` → `es_extended`.
3. If no match is found, the system falls back to `qbcore` as a safe default.

#### Inventory Detection

```lua
local function DetectInventory()
    if Config.Inventory and Config.Inventory ~= 'auto' then
        return Config.Inventory
    end
    if ResourceStarted('ox_inventory') then return 'ox_inventory' end
    if ResourceStarted('qs-inventory') then return 'qs-inventory' end
    if ResourceStarted('qb-inventory') then return 'qb-inventory' end
    return 'qb-inventory'
end
```

Follows the same pattern as framework detection. The detection priority reflects modern adoption: `ox_inventory` first, then `qs-inventory`, then `qb-inventory`.

#### Image Path Resolution

```lua
function Bridge.GetImagePath(itemName)
    if Bridge.Inventory == 'ox_inventory' then
        return ('nui://ox_inventory/web/images/%s.png'):format(itemName)
    elseif Bridge.Inventory == 'qs-inventory' then
        return ('nui://qs-inventory/html/images/%s.png'):format(itemName)
    end
    return ('nui://qb-inventory/html/images/%s.png'):format(itemName)
end
```

Returns the correct NUI path for an item icon based on the active inventory system. This ensures item images render correctly inside the script's UI regardless of the underlying inventory.

***

### 🔁 Shared.lua

A lightweight shared utility module exposed on both client and server.

```lua
function Bridge.GetItemImage(itemName)
    return Bridge.GetImagePath(itemName)
end
```

| Function                        | Description                                                      |
| ------------------------------- | ---------------------------------------------------------------- |
| `Bridge.GetItemImage(itemName)` | Convenience wrapper around `GetImagePath`, used by the UI layer. |

***

### 🖥️ Server.lua

Server-side abstractions for player data, inventory operations, currency, and callbacks.

#### Bridge.GetPlayer

```lua
Bridge.GetPlayer(src)
```

Returns the player object associated with the given source ID, abstracted across all supported frameworks.

| Framework | Underlying Call                   |
| --------- | --------------------------------- |
| QBCore    | `Core.Functions.GetPlayer(src)`   |
| QBox      | `exports.qbx_core:GetPlayer(src)` |
| ESX       | `Core.GetPlayerFromId(src)`       |

***

#### Bridge.GetItemCount

```lua
Bridge.GetItemCount(Player, itemName)
```

Returns the total quantity of a given item held by the player. Handles edge cases such as `ox_inventory` returning either a number or a structured table of stack counts.

| Inventory     | Mechanism                                                   |
| ------------- | ----------------------------------------------------------- |
| ox\_inventory | `exports.ox_inventory:Search(src, 'count', itemName)`       |
| qs-inventory  | `exports['qs-inventory']:GetItemTotalAmount(src, itemName)` |
| qb-inventory  | `Player.Functions.GetItemByName(itemName).amount`           |
| ESX           | `Player.getInventoryItem(itemName).count`                   |

{% hint style="success" %} The function always returns a valid number. Missing items resolve to `0` rather than `nil`. {% endhint %}

***

#### Bridge.RemoveItem

```lua
Bridge.RemoveItem(Player, itemName, amount)
```

Removes a specified amount of an item from the player's inventory. Routed to the correct API based on the active inventory.

***

#### Bridge.AddItem

```lua
Bridge.AddItem(Player, itemName, amount)
```

Adds a specified amount of an item to the player's inventory.

***

#### Bridge.AddMoney / Bridge.RemoveMoney

```lua
Bridge.AddMoney(Player, moneyType, amount, reason)
Bridge.RemoveMoney(Player, moneyType, amount, reason)
```

| Parameter   | Description                                               |
| ----------- | --------------------------------------------------------- |
| `moneyType` | Either `cash` or `bank`. Defaults to `cash`.              |
| `amount`    | The numeric amount to credit or debit.                    |
| `reason`    | Transaction reason, primarily used by QBCore for logging. |

ESX players use `addAccountMoney` / `removeAccountMoney` for bank operations and `addMoney` / `removeMoney` for cash. QBCore and QBox both rely on `Player.Functions.AddMoney` and `Player.Functions.RemoveMoney`.

***

#### Bridge.ItemBox

```lua
Bridge.ItemBox(src, itemName, amount, action)
```

Triggers the QBCore-style item notification box on the client.

| `action` | Behavior                                         |
| -------- | ------------------------------------------------ |
| `add`    | Displays the green "received item" notification. |
| `remove` | Displays the red "removed item" notification.    |

{% hint style="warning" %} This call is intentionally a no-op when running on `ox_inventory` or ESX, since both systems handle item notifications internally. {% endhint %}

***

#### Bridge.RegisterCallback

```lua
Bridge.RegisterCallback(name, function(src, cb, ...)
    cb(true)
end)
```

Registers a server-side callback that works seamlessly across frameworks.

| Framework | Mechanism                                                               |
| --------- | ----------------------------------------------------------------------- |
| QBCore    | `Core.Functions.CreateCallback`                                         |
| QBox      | `lib.callback.register` (ox\_lib)                                       |
| ESX       | `Core.RegisterServerCallback`, with fallback to `lib.callback.register` |

***

#### Bridge.Notify (Server)

```lua
Bridge.Notify(src, msg, type)
```

Triggers a client-side notification from the server. Internally fires the `bigdavid:client:notify` event, which is handled by the client-side `Bridge.Notify` implementation.

***

### 🎮 Client.lua

Client-side abstractions for notifications, callbacks, and target zones.

#### Bridge.Notify (Client)

```lua
Bridge.Notify(msg, type)
```

| `type`    | Visual Style             |
| --------- | ------------------------ |
| `inform`  | Neutral / informational. |
| `success` | Positive confirmation.   |
| `error`   | Failure or warning.      |

| Framework | Notification System                                    |
| --------- | ------------------------------------------------------ |
| QBCore    | `Core.Functions.Notify`                                |
| QBox      | `lib.notify` (ox\_lib)                                 |
| ESX       | `Core.ShowNotification`, with fallback to `lib.notify` |

***

#### Bridge.TriggerCallback

```lua
Bridge.TriggerCallback(name, function(result)
    print(result)
end, ...)
```

Invokes a registered server callback. The callback receives the server's response asynchronously through the provided handler function.

***

#### Bridge.AddTarget

```lua
Bridge.AddTarget({
    coords      = vector3(...),
    distance    = 4,
    interactDst = 2,
    id          = "unique_id",
    label       = "Talk",
    action      = function() end
})
```

Registers an interaction zone using the configured target system.

| Parameter     | Description                                                     |
| ------------- | --------------------------------------------------------------- |
| `coords`      | World coordinates of the interaction.                           |
| `distance`    | Visibility radius for the interaction prompt.                   |
| `interactDst` | Activation radius for the interaction itself.                   |
| `id`          | Unique identifier used for later removal.                       |
| `label`       | The interaction label displayed to the player.                  |
| `action`      | The function executed when the player triggers the interaction. |

| System     | Underlying Call                      |
| ---------- | ------------------------------------ |
| ox\_target | `exports.ox_target:addSphereZone`    |
| qb-target  | `exports['qb-target']:AddCircleZone` |
| interact   | `exports.interact:AddInteraction`    |

***

#### Bridge.RemoveTarget

```lua
Bridge.RemoveTarget(id)
```

Removes a previously registered target zone using its unique `id`. Wrapped in `pcall` for the `interact` system to prevent runtime errors when the target no longer exists.

***

### 🧠 Why Use a Bridge?

| Benefit             | Description                                                                            |
| ------------------- | -------------------------------------------------------------------------------------- |
| **Unified API**     | One function set works across QBCore, QBox, and ESX.                                   |
| **Maintainability** | Framework-specific changes are contained in a single location.                         |
| **Extensibility**   | Adding support for a new framework or inventory requires minimal changes.              |
| **Cleaner Logic**   | Business logic stays focused on what the script *does*, not what framework it runs on. |

***

### 📌 Practical Examples

#### Server-Side: Selling an Item

```lua
local Player = Bridge.GetPlayer(src)
if Bridge.GetItemCount(Player, "thermite") >= 1 then
    Bridge.RemoveItem(Player, "thermite", 1)
    Bridge.AddMoney(Player, "cash", 850, "sold-thermite")
    Bridge.Notify(src, "Item sold successfully", "success")
end
```

#### Client-Side: Registering a Vendor NPC

```lua
Bridge.AddTarget({
    coords      = vector3(-1150.87, -1519.22, 4.36),
    interactDst = 2,
    id          = "bigdavid_ped",
    label       = "Talk to Big David",
    action      = function()
        Bridge.Notify("Opening shop...", "inform")
    end
})
```

{% hint style="success" %} By isolating framework-specific behavior behind the Bridge, the rest of the codebase remains framework-agnostic, easier to maintain, and significantly easier to extend. {% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://x8project.gitbook.io/x8project/projects/big-david/bridge-system.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
