Skip to content

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-*'], RSGCore or lib.* directly - use GSD.*.
  • The server decides about money, items, permissions and distance. Client checks only filter the UI.
  • Always check return values: every Add / Remove returns true or false.
  • 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 ​

TypeVORPRSG
cashyesyes
goldyesyes (whole numbers)
rolyes-
bloodmoney-yes
bankyes (vorp_banking)yes (rsg-banking)

Server ​

Basics ​

FunctionReturnsNotes
GSD.Framework'vorp' | 'rsg' | 'custom'
GSD.BridgeVersionstring
GSD.RequireVersion(min)true / error
GSD.Has(cap)boolmoney, inventory, jobs, bank, society, needs, ui
GSD.IsTrue(v)boolnative 1 / 0 → bool
GSD.GetUiColors()tablethe bridge's Config.UiColors, for your own NUI windows

Players ​

FunctionReturns
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 ​

FunctionReturnsNotes
GSD.GetJob(src)Job
GSD.SetJob(src, job, grade, label?)bool
GSD.IsOnDuty(src)bool
GSD.SetDuty(src, bool)boolVORP: only jobs with a duty statebag
GSD.GetDutyCount(jobOrType)numberjob name or type ('leo')
GSD.IsAdmin(src)boolgsd.admin ACE, VORP admin group or RSG permission

Money ​

FunctionReturns
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 ​

FunctionReturns
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 the items table and need one server restart.

Weapons ​

FunctionNotes
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 ​

FunctionNotes
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 ​

FunctionNotes
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 / RemoveSocietyMoneyRSG 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 ​

FunctionReturnsNotes
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 = cancelledBackspace 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()boolnot 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 ...).

Red Dead Redemption 2 belongs to Rockstar Games. Gunsmoke Development is not connected to Rockstar Games.