# Bridge

> ✅ **Tip:** You don't need to touch any of these files. The Bridge auto-detects everything on resource start.

***

### 🔍 Auto-Detect

When the resource starts, the Bridge scans your server and detects:

| System    | Detected From                          |
| --------- | -------------------------------------- |
| Framework | `qbx_core` → `qb-core`                 |
| Inventory | `ox_inventory` → `qb-inventory`        |
| Notify    | `ox_lib`→ `qb`                         |
| Target    | `ox_target` → `qb-target` → `interact` |
| DrawText  | `qb-ui` → `ox_lib`                     |

Result is printed in console on boot:

```
[X8-WeedlaP] [SERVER] Framework=qb Inventory=ox_inventory Notify=ox_lib Target=ox_target DrawText=ox_lib
[X8-WeedlaP] [CLIENT] Framework=qb Inventory=ox_inventory Notify=ox_lib Target=ox_target DrawText=ox_lib
```

To override the detection, set the values manually in `Config.Bridge`:

```lua
Config.Bridge = {
    Framework = 'qbx',
    Inventory = 'ox_inventory',
    Notify    = 'ox_lib',
    Target    = 'ox_target',
    DrawText  = 'ox_lib',
}
```

***

### 📁 File Structure

```
bridge/
├─ client/
│  ├─ framework.lua
│  ├─ inventory.lua
│  ├─ notify.lua
│  ├─ target.lua
│  └─ drawtext.lua
└─ server/
   ├─ framework.lua
   ├─ inventory.lua
   └─ notify.lua
```

Each file handles **one** subsystem on **one** side (client or server).

***

### 🧠 Framework

Wraps framework-specific calls so the same code works on **QBCore** and **QBox**.

#### Client (`framework.lua`)

```lua
Bridge.GetPlayerData()
Bridge.TriggerCallback(name, cb, ...)
```

| Function                                | Description                                            |
| --------------------------------------- | ------------------------------------------------------ |
| `Bridge.GetPlayerData()`                | Returns the current player data table.                 |
| `Bridge.TriggerCallback(name, cb, ...)` | Triggers a callback. Uses `lib.callback.await` on QBX. |

#### Server (`framework.lua`)

```lua
Bridge.GetPlayer(src)
Bridge.GetPlayerByCitizenId(cid)
Bridge.GetPlayers()
Bridge.AddMoney(Player, account, amount, reason)
Bridge.RemoveMoney(Player, account, amount, reason)
Bridge.GetMoney(Player, account)
Bridge.SetGang(Player, gang, grade)
Bridge.HasPermission(src, perm)
Bridge.CreateCallback(name, cb)
Bridge.CreateUseableItem(item, cb)
Bridge.GetGang(Player)
Bridge.GetGangLabel(gang)
Bridge.GetGangs()
Bridge.GetSharedItem(item)
Bridge.GetItemLabel(item)
Bridge.GetCharName(Player)
Bridge.GetCitizenId(Player)
```

| Function                                              | Description                                                            |
| ----------------------------------------------------- | ---------------------------------------------------------------------- |
| `Bridge.GetPlayer(src)`                               | Returns a Player object from a source ID.                              |
| `Bridge.GetPlayerByCitizenId(cid)`                    | Returns a Player object from a citizenid (online only).                |
| `Bridge.GetPlayers()`                                 | Returns all online players (compatible with QB / QBX).                 |
| `Bridge.AddMoney(Player, account, amount, reason)`    | Adds money. Returns `true` on success.                                 |
| `Bridge.RemoveMoney(Player, account, amount, reason)` | Removes money. Returns `true` on success.                              |
| `Bridge.GetMoney(Player, account)`                    | Returns the player's balance for the given account.                    |
| `Bridge.SetGang(Player, gang, grade)`                 | Sets a player's gang and grade.                                        |
| `Bridge.HasPermission(src, perm)`                     | Checks ace permission.                                                 |
| `Bridge.CreateCallback(name, cb)`                     | Registers a server callback (works on QB & QBX via `lib.callback`).    |
| `Bridge.CreateUseableItem(item, cb)`                  | Registers a usable item.                                               |
| `Bridge.GetGang(Player)`                              | Returns `gangName, gangGrade` for a player.                            |
| `Bridge.GetGangLabel(gang)`                           | Returns the display label of a gang.                                   |
| `Bridge.GetGangs()`                                   | Returns the full gangs table.                                          |
| `Bridge.GetSharedItem(item)`                          | Returns shared item data (QBCore.Shared.Items / qbx items / ox items). |
| `Bridge.GetItemLabel(item)`                           | Returns the display label of an item.                                  |
| `Bridge.GetCharName(Player)`                          | Returns the player's first + last name.                                |
| `Bridge.GetCitizenId(Player)`                         | Returns the player's citizenid.                                        |

#### Usage Example

```lua
RegisterNetEvent('X8-WeedlaP:server:buyLab', function()
    local src    = source
    local Player = Bridge.GetPlayer(src)
    if not Player then return end

    local gang, grade = Bridge.GetGang(Player)
    if grade < 3 then
        Bridge.Notify(src, 'Only the boss can buy a lab', 'error')
        return
    end

    if Bridge.GetMoney(Player, 'bank') < 50000 then
        Bridge.Notify(src, 'Not enough money', 'error')
        return
    end

    Bridge.RemoveMoney(Player, 'bank', 50000, 'lab-purchase')
end)
```

***

### 📦 Inventory

Wraps inventory operations so the same code works on **ox\_inventory** and **QB-style inventories**.

#### Server (`inventory.lua`)

```lua
Bridge.AddItem(Player, item, amount, slot, info)
Bridge.RemoveItem(Player, item, amount, slot)
Bridge.GetItem(Player, item)
Bridge.GetItemCount(Player, item)
Bridge.GetItemBySlot(Player, slot)
Bridge.SetItemMetadata(Player, slot, info)
Bridge.GetItemMetadata(Player, slot)
Bridge.FindBottle(Player, itemName)
Bridge.SetBottleWater(Player, slot, newWater, itemName)
Bridge.GetAllBottles(Player, itemName)
Bridge.RegisterStash(stashId, label, slots, maxWeight, owner)
Bridge.OpenStash(src, stashId, label, slots, maxWeight)
Bridge.UpdateStashSlots(stashId, newSlots, maxWeight)
Bridge.ShowItemBox(src, item, action)
Bridge.CanCarry(Player, item, amount)
```

| Function                                           | Description                                                            |
| -------------------------------------------------- | ---------------------------------------------------------------------- |
| `Bridge.AddItem(Player, item, amount, slot, info)` | Adds an item to the player's inventory. Auto-shows item box on QB.     |
| `Bridge.RemoveItem(Player, item, amount, slot)`    | Removes an item.                                                       |
| `Bridge.GetItem(Player, item)`                     | Returns `{name, amount, count}` or `nil`.                              |
| `Bridge.GetItemCount(Player, item)`                | Returns the total count of an item.                                    |
| `Bridge.GetItemBySlot(Player, slot)`               | Returns the item at a specific slot.                                   |
| `Bridge.SetItemMetadata(Player, slot, info)`       | Updates item metadata (info on QB, metadata on ox).                    |
| `Bridge.GetItemMetadata(Player, slot)`             | Returns metadata for a slot.                                           |
| `Bridge.FindBottle(Player, itemName)`              | Finds a water bottle and returns `slot, waterLevel`.                   |
| `Bridge.SetBottleWater(Player, slot, water, item)` | Updates a bottle's water level (0–100).                                |
| `Bridge.GetAllBottles(Player, itemName)`           | Returns all bottles `{ {slot, water}, ... }`.                          |
| `Bridge.RegisterStash(...)`                        | Registers a persistent stash (ox\_inventory only).                     |
| `Bridge.OpenStash(...)`                            | Forces a stash to open for the player.                                 |
| `Bridge.UpdateStashSlots(stashId, slots, weight)`  | Updates stash size on the fly (QB only).                               |
| `Bridge.ShowItemBox(src, item, action)`            | Shows the QB item box (no-op on ox).                                   |
| `Bridge.CanCarry(Player, item, amount)`            | Returns `true` if the player has space (ox only; always `true` on QB). |

#### Usage Example

```lua
local Player = Bridge.GetPlayer(src)

if not Bridge.CanCarry(Player, 'joint', 5) then
    Bridge.Notify(src, 'Inventory full', 'error')
    return
end

local seed = Bridge.GetItem(Player, 'seed_bluedream')
if not seed or (seed.amount or 0) < 1 then
    Bridge.Notify(src, 'No seeds', 'error')
    return
end

Bridge.RemoveItem(Player, 'seed_bluedream', 1)
Bridge.AddItem(Player, 'bud_bluedream', 5)
```

#### Client (`inventory.lua`)

```lua
Bridge.OpenStash(stashId, label, slots, maxWeight)
```

Opens a stash from the client side. Picks the correct export for the detected inventory:

* `ox_inventory` → `openInventory('stash', stashId)`
* `ps-inventory` / `qs-inventory` / `codem-inventory` → their custom exports
* fallback → standard `inventory:server:OpenInventory` event

***

### 💧 Bottle Metadata Helpers

These are inventory-specific helpers for the **water bottle system** (each bottle stores a `water` value 0–100).

| Function                                           | Purpose                                               |
| -------------------------------------------------- | ----------------------------------------------------- |
| `Bridge.FindBottle(Player, itemName)`              | Find the first bottle in inventory.                   |
| `Bridge.GetAllBottles(Player, itemName)`           | List all bottles with their water level.              |
| `Bridge.SetBottleWater(Player, slot, water, item)` | Set a specific bottle's water level (0–100, clamped). |

Works seamlessly on ox\_inventory (uses `metadata.water`) and QB-style inventory (uses `info.water`).

***

### 🔔 Notify

Unified notification system supporting **ox\_lib**, **okokNotify**, and **QB notify**.

#### Server (`notify.lua`)

```lua
Bridge.Notify(src, msg, nType, duration)
Bridge.NotifyAll(msg, nType, duration)
```

| Function           | Description                                     |
| ------------------ | ----------------------------------------------- |
| `Bridge.Notify`    | Sends a notification to one player.             |
| `Bridge.NotifyAll` | Sends a notification to **all** online players. |

#### Client (`notify.lua`)

```lua
Bridge.Notify(msg, nType, duration)
```

Shows a local notification. Auto-routes to:

* `lib.notify` (if ox\_lib is detected)
* `okokNotify` (if okok is detected)
* `QBCore.Functions.Notify` (fallback)

#### Notification Types

| Input     | Maps to   |
| --------- | --------- |
| `primary` | `inform`  |
| `success` | `success` |
| `error`   | `error`   |
| `warning` | `warning` |

#### Usage Example

```lua
-- Server
Bridge.Notify(src, 'Plant harvested', 'success')
Bridge.NotifyAll('A lab has been raided!', 'warning', 8000)

-- Client
Bridge.Notify('You are too far from the plant', 'error')
```

***

### 🎯 Target

Wraps `ox_target` and `qb-target` under one unified API. QB-style options are auto-converted to ox-style options.

#### Functions

```lua
Bridge.AddTargetEntity(entity, options, distance)
Bridge.RemoveTargetEntity(entity, names)
Bridge.AddBoxZone(name, center, length, width, options, params)
Bridge.RemoveZone(name)
```

| Function             | Description                                 |
| -------------------- | ------------------------------------------- |
| `AddTargetEntity`    | Attach target options to a specific entity. |
| `RemoveTargetEntity` | Remove options from an entity by name.      |
| `AddBoxZone`         | Add a box-shaped target zone.               |
| `RemoveZone`         | Remove a target zone by name.               |

#### Option Format (QB-style — auto-converted)

```lua
{
    name        = 'open_safe',
    label       = 'Open Safe',
    icon        = 'fa-solid fa-lock',
    event       = 'X8-WeedlaP:client:openSafe',
    serverEvent = nil,
    action      = function(entity) ... end,
    canInteract = function(entity, distance, ctx) return true end,
    item        = 'lab_tablet',
    distance    = 2.0,
}
```

#### Usage Example

```lua
Bridge.AddTargetEntity(safeEntity, {
    {
        name   = 'open_lab_safe',
        label  = 'Open Lab Safe',
        icon   = 'fa-solid fa-vault',
        event  = 'X8-WeedlaP:client:openSafe',
        canInteract = function()
            return Bridge.GetPlayerData().gang.name == 'ballas'
        end
    }
}, 2.5)

Bridge.AddBoxZone('lab_entrance', vector3(100.0, 200.0, 30.0), 2.0, 1.5, options, {
    heading   = 90.0,
    minZ      = 29.0,
    maxZ      = 31.0,
    distance  = 2.5,
    debugPoly = false,
})
```

***

### 📝 DrawText

Wraps `qb-ui` and `ox_lib` text UI.

#### Functions

```lua
Bridge.DrawText(text, icon)
Bridge.HideText()
```

| Function   | Description                                        |
| ---------- | -------------------------------------------------- |
| `DrawText` | Shows a floating UI text. Auto-dedup (no flicker). |
| `HideText` | Hides the text UI.                                 |

The icon is automatically normalized between FA-Awesome syntax (`fa-solid fa-hand`) and ox\_lib short names (`hand`).

#### Usage Example

```lua
CreateThread(function()
    while true do
        local sleep = 1000
        local ped   = PlayerPedId()
        local coords = GetEntityCoords(ped)

        if #(coords - vec3(100.0, 200.0, 30.0)) < 2.0 then
            sleep = 0
            Bridge.DrawText('[E] Manage Lab', 'fa-solid fa-flask')
            if IsControlJustPressed(0, 38) then
                TriggerEvent('X8-WeedlaP:client:openLab')
            end
        else
            Bridge.HideText()
        end

        Wait(sleep)
    end
end)
```

Text is automatically hidden when the resource stops.

***

### 🏗️ Bridge Initialization

The Bridge initializes at the bottom of `Config.lua`:

```lua
Bridge = {}
Bridge.IsServer = IsDuplicityVersion()

Bridge.Framework      = detectFramework()
Bridge.Inventory      = detectInventory()
Bridge.NotifySystem   = detectNotify()
Bridge.TargetSystem   = detectTarget()
Bridge.DrawTextSystem = detectDrawText()
```

The `Core` object is also resolved:

```lua
if Bridge.Framework == 'qbx' then
    Core = exports.qbx_core
else
    Core = exports['qb-core']:GetCoreObject()
end

Bridge.Core = Core
QBCore = Core
```

> 💡 **Note:** The global `QBCore` is kept for backward-compatibility — even on QBX it points to the resolved Core object.

For QBX, a `Shared` proxy is added so the script can still access `QBCore.Shared.Items / Jobs / Gangs` as if it was running on QBCore.

***

### ✅ Compatibility Matrix

| System    | Supported Resources                                                                         |
| --------- | ------------------------------------------------------------------------------------------- |
| Framework | qb-core, qbx\_core                                                                          |
| Inventory | ox\_inventory, qb-inventory, ps-inventory, qs-inventory, codem-inventory, origen\_inventory |
| Notify    | ox\_lib, okokNotify, qb (default)                                                           |
| Target    | ox\_target, qb-target, interact                                                             |
| DrawText  | qb-ui, ox\_lib                                                                              |

> ⚠️ **Warning:** If your fork uses different event names (especially QB-style inventories), edit `Config.InventoryQB.Events` instead of the bridge files.


---

# 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/weed-lab/bridge.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.
