Developer API
Build your own scripts on GSD Bridge and they run on VORP, RSG and custom cores without a single framework call.
Setup
lua
-- fxmanifest.lua
dependency 'gsd-bridge'
shared_script '@gsd-bridge/init.lua'Then call everything through the global GSD table:
lua
GSD.RequireVersion('1.0.0') -- stops your resource with a clear message if the bridge is too old
print(GSD.Framework) -- 'vorp' | 'rsg' | 'custom'Your resource also prints [your-resource] v1.0.0 ready in the console when it has loaded.
Rules that keep your script safe on every framework
- Never call
exports.vorp_*,exports['rsg-*'],RSGCoreorlib.*directly - useGSD.*. - The server decides about money, items, permissions and distance. Client checks only filter the UI.
- Always check return values: every
Add/Removereturnstrueorfalse. - Put money, item, needs, bank and society features behind
GSD.Has(...).
Data shapes
Player (server)
lua
{
source = 1,
charId = '1', -- ALWAYS a string (VORP: number as string, RSG: citizenid)
identifier = 'license:...',
firstname = 'Arthur', lastname = 'Morgan',
job = <Job>,
money = { cash = 200, gold = 0, rol = 0, bloodmoney = 0 }, -- bank is not here: GSD.GetMoney(src, 'bank')
isDead = false,
}Store character ids as VARCHAR(50) in your database.
Job
lua
{ name = 'police', label = 'Deputy', grade = 2, gradeLabel = 'Deputy', isBoss = false, onDuty = true, type = 'leo' }Item
lua
{ name = 'bread', label = 'Bread', count = 3, metadata = {}, slot = 4 --[[RSG]], id = 123 --[[VORP]], weight = 100 }slotOrId parameters take the slot on RSG and the id on VORP.
Notify
lua
'Simple text'
-- or
{ title = 'Store', description = 'You bought it!', type = 'inform' | 'success' | 'error' | 'warning', duration = 5000 }Money types
| Type | VORP | RSG |
|---|---|---|
cash | yes | yes |
gold | yes | yes (whole numbers) |
rol | yes | - |
bloodmoney | - | yes |
bank | yes (vorp_banking) | yes (rsg-banking) |
Server
Basics
| Function | Returns | Notes |
|---|---|---|
GSD.Framework | 'vorp' | 'rsg' | 'custom' | |
GSD.BridgeVersion | string | |
GSD.RequireVersion(min) | true / error | |
GSD.Has(cap) | bool | money, inventory, jobs, bank, society, needs, ui |
GSD.IsTrue(v) | bool | native 1 / 0 → bool |
GSD.GetUiColors() | table | the bridge's Config.UiColors, for your own NUI windows |
Players
| Function | Returns |
|---|---|
GSD.GetPlayer(src) | Player | nil |
GSD.GetCharId(src) | string | nil |
GSD.GetIdentifier(src) | string | nil |
GSD.GetName(src) | firstname, lastname |
GSD.GetSourceByCharId(charId) | number | nil |
GSD.GetPlayers() | { src, ... } - players with a loaded character |
GSD.IsDead(src) | bool |
Jobs and permissions
| Function | Returns | Notes |
|---|---|---|
GSD.GetJob(src) | Job | |
GSD.SetJob(src, job, grade, label?) | bool | |
GSD.IsOnDuty(src) | bool | |
GSD.SetDuty(src, bool) | bool | VORP: only jobs with a duty statebag |
GSD.GetDutyCount(jobOrType) | number | job name or type ('leo') |
GSD.IsAdmin(src) | bool | gsd.admin ACE, VORP admin group or RSG permission |
Money
| Function | Returns |
|---|---|
GSD.GetMoney(src, type) | number |
GSD.AddMoney(src, type, amount, reason?, opts?) | bool - opts = { bank = 'rhodes' } |
GSD.RemoveMoney(src, type, amount, reason?, opts?) | bool - false if the player can not pay |
GSD.GetBankBalance(src, bankId?) | number |
GSD.AddBankMoneyByCharId(charId, amount, reason?, bankId?) | bool - works for offline characters too |
An invalid amount (≤ 0, NaN, not a number) or an unknown type returns false.
Selling something - the safe order
GSD.CanCarry → GSD.RemoveMoney (check the result) → GSD.AddItem → if AddItem failed, give the money back with GSD.AddMoney.
Inventory
| Function | Returns |
|---|---|
GSD.AddItem(src, name, amount, metadata?, reason?) | bool |
GSD.RemoveItem(src, name, amount, metadata?, slotOrId?) | bool |
GSD.GetItemCount(src, name, metadata?) | number |
GSD.HasItem(src, name, amount?, metadata?) | bool |
GSD.CanCarry(src, name, amount) | bool |
GSD.GetInventory(src) | Item[] |
GSD.GetItemLabel(name) | string |
GSD.SetItemMetadata(src, slotOrId, metadata) | bool |
GSD.CloseInventory(src) | - |
GSD.RegisterUsableItem(name, fn(src, item), closeOnUse = true) | - |
GSD.EnsureItems({ { name, label, weight, description, usable, limit, image } }) | names of the created items |
- Usable items are removed automatically when your resource stops. On VORP an item can have only one handler.
EnsureItems(weight in grams): on RSG the items work right away; on VORP they are added to theitemstable and need one server restart.
Weapons
| Function | Notes |
|---|---|
GSD.GiveWeapon(src, weapon, ammo?) | VORP: upper-case weapon name; RSG: weapon item |
GSD.CanCarryWeapon(src, weapon) | |
GSD.RemoveWeapon(src, weapon, idOrSlot?) | |
GSD.AddAmmo(src, ammoType, amount) |
Stashes
| Function | Notes |
|---|---|
GSD.RegisterStash(id, { label, slots, maxWeight, shared, acceptWeapons }) | maxWeight in grams (RSG only) |
GSD.OpenStash(src, id) | server only |
GSD.AddItemToStash(id, name, amount, metadata?, ownerCharId) | VORP needs ownerCharId |
GSD.RemoveItemFromStash(id, name, amount) | |
GSD.GetStashItems(id) | Item[] |
GSD.RemoveStash(id, deleteData?) | deleteData = true also deletes the content |
GSD.OpenPlayerInventory(src, target) | search another player |
Other
| Function | Notes |
|---|---|
GSD.Notify(src, data, provider?) | see Notify above; provider: 'gsd', 'framework', 'ox_lib' or nil (bridge setting) |
GSD.Revive(src) / GSD.Heal(src) | uses the framework's medic resource, native fallback |
GSD.GetNeeds(src) | { hunger, thirst } 0-100 | nil |
GSD.SetNeed(src, key, value) / GSD.AddNeed(src, key, delta) | bool |
GSD.HasSociety() | bool - RSG only |
GSD.GetSocietyMoney(job) / AddSocietyMoney / RemoveSocietyMoney | RSG only; VORP returns 0 / false |
GSD.RegisterCallback(name, fn(src, ...)) | the handler answers with return (more values are fine) |
GSD.TriggerClientCallback(name, src, ...) | waits for the answer, nil after Config.CallbackTimeout |
Name your own callbacks <resource>:<name>, for example gsd-shop:buy.
Server events
lua
GSD.OnPlayerLoaded(function(src) end) -- also runs for players already online when your resource starts
GSD.OnPlayerUnloaded(function(src) end)
GSD.OnJobUpdate(function(src, job) end) -- job, grade or duty changed
GSD.OnMoneyChange(function(src, moneyType, amount, op) end) -- op: 'add' | 'remove' | 'set'Client
| Function | Returns | Notes |
|---|---|---|
GSD.IsLoggedIn() | bool | |
GSD.GetPlayerData() | { charId, firstname, lastname, job, money } | |
GSD.GetJob() | Job | |
GSD.GetItemCount(name) / GSD.HasItem(name, n) | ||
GSD.CloseInventory() | ||
GSD.Notify(data, provider?) | ||
GSD.Progress({ label, duration, canCancel, anim = { dict, clip, flag }, disable = { move } }, provider?) | bool - false = cancelled | Backspace cancels on every framework |
GSD.Input(title, { { label, type = 'text' | 'number' | 'textarea', placeholder, default, required } }) | values[] | nil | |
GSD.Confirm(title, text) | bool | |
GSD.Menu({ id, title, subtitle, options = { { label, description, value, disabled, onSelect } }, onClose }) | - | |
GSD.CloseMenu() | ||
GSD.TextUI(text) / GSD.HideTextUI() | bool | not available on VORP (false) |
GSD.TriggerCallback(name, ...) | the server's return values | |
GSD.RegisterCallback(name, fn(...)) | server → client | |
GSD.GetUiColors() | table |
Prompts, blips, peds
The same on every framework - native RedM prompts, no target resource needed:
lua
local id = GSD.AddPrompt({
coords = vector3(-308.1, 776.2, 118.7), -- or entity = ped
distance = 2.0,
title = 'Store',
prompts = {
{ key = 'E', label = 'Buy', name = 'buy' },
{ key = 'G', label = 'Sell', name = 'sell', hold = 1000 },
},
canInteract = function() return true end, -- checked every 250 ms
onSelect = function(name) end, -- runs in its own thread
})
GSD.RemovePrompt(id)
GSD.SetPromptEnabled(id, 'sell', false)
local blip = GSD.CreateBlip({ coords = vector3(-308.1, 776.2, 118.7), sprite = 'blip_shop_store', name = 'Store', scale = 0.2 })
GSD.RemoveBlip(blip)
local ped = GSD.SpawnPed({ model = 'S_M_M_BankClerk_01', coords = vector4(-308.1, 776.2, 118.7, 90.0), scenario = 'WORLD_HUMAN_SMOKE', freeze = true, invincible = true })
GSD.DeletePed(ped)Prompts, blips and peds are cleaned up automatically when your resource stops.
Client events
lua
GSD.OnPlayerLoaded(function() end) -- runs right away if the player is already in game
GSD.OnPlayerUnloaded(function() end)
GSD.OnJobUpdate(function(job) end)Your own NUI windows in the GSD look
Load the GSD UI template from the bridge in your html/index.html:
html
<link rel="stylesheet" href="nui://gsd-bridge/html/ui/gsd-ui.css">
<script src="nui://gsd-bridge/html/ui/gsd-ui.js"></script>
<body class="gsd"> ... </body>Send the server owner's colors when you open a window:
lua
SendNUIMessage({ action = 'open', colors = GSD.GetUiColors() }) -- JS: GsdUi.applyColors(data.colors)gsd-bridge/html/ui/example.html shows every component (window, rows, buttons, fields, tabs, key hints ...).