OPX//77
Creators

Creators

Last updated on

How your own Open77 resource talks to opx_infinity — exports, events, who may call, and when to await.

For a separate resource (your own job, shop or heist). opx_infinity gives you three doors and nothing else:

DoorSideUse it to
Server exportsserverread a player, the roster, the jobs, the catalogue, a bag, vehicles and doors; change money, jobs, gangs, duty, your own metadata (online or not), items, stashes, chat, keys, vehicles, doors; register items, use handlers and crafting benches; a toast, a bar the server judges; revive
Client exportsclientopen a menu, form or panel, show a toast, run a progress bar, put rows on the eye and hints on the key strip, open a crafting bench, play an animation, read the local player; subscribe to OPX client events
Public server eventsserverreact when a character loads, money moves, an item is used…

The modules' own contracts (OPX.Api.Get) stay inside opx_infinity. If you need more, write a module instead.

Every export answers one table

{ ok = true,  value = <answer> }    -- value may be nil
{ ok = false, error = '<code>' }    -- a stable code you can branch on

An export never raises. Always test answer.ok == true.

CodeMeaning
export.callerDeniedYour resource is not allowed to make this call (Who may call).
export.badArgumentAn argument could not be read (wrong type, bad player id, bad citizen id, name too long…).
export.bootingThe server has not finished starting. Try again later.
export.badValueSetMetadata: the value is not plain data.
export.tooLargeSetMetadata: over a size or key-count limit.
export.notSubscribableSubscribe: that event is not on the list.
export.ownerTakenEye and key strip: your resource is named like a module of OPX, whose rows it would share.
export.usableTakenRegisterUsableItem: another owner already handles that item's use.
export.duplicateNotify: the same toast was just shown to that player.
export.mustAwaitThis call can reach the database. Call it with Open77.exports.call(...) and :await() (below).
error.unavailableThe module behind the export is not running, or the call failed.
error.notLoggedInThat player has no character loaded.
other codesPassed through from the module: money.insufficient, stash_cap, vehicle.busy… Each export lists its own.

A code is not a sentence. The export.* codes have English and French text in opx_infinity, but your resource shows its own text: translate the codes you show. See Error codes.

Who may call

The caller is the resource name the host reports (GetInvokingResource), never an argument. The operator decides:

SettingFileDefaultControls
SERVER.EXPORTS.READconfig/server.lua'*' (everyone)server exports that only read
SERVER.EXPORTS.WRITERSconfig/server.lua{} (nobody)server exports that change something
CLIENT.EXPORTS.CALLERSconfig/client.lua'*' (everyone)client exports

A list is '*', a set { my_shop = true } or an array { 'my_shop' }. When a server export refuses your resource, the journal prints the line to add, once per resource and export:

[exports] my_shop was refused AddMoney; to admit it, add `my_shop = true` to EXPORTS.WRITERS in config/server.lua

Writers are trusted with money

A resource in WRITERS can create money and items. Every write is audited with the caller's name (event=export.<Name>), and money reasons are written ext:<resource>:<reason>.

Sync or await?

-- synchronous: answers at once; fails if the export has to wait
local answer = exports.opx_infinity:GetPlayerData(playerId)

-- asynchronous: returns a promise; call it from a thread and await it
local pending, why = Open77.exports.call('opx_infinity', 'AddMoney', playerId, 'EDDIES', 250, 'tip')
local answer = pending and pending:await()
Sync is fineMust use Open77.exports.call(...):await()
GetVersion, GetPlayerData, GetPlayerByCitizenId, GetPlayers, GetJobs, GetGangs, IsStaff, GetMoney, HasJob, HasGang, GetJob, GetGang, GetItem, GetItems, IsDown, the door reads, GetMetadata / GetInventory / CanCarryItem / HasKeys for a player id, and the memory-only writes SetDuty, SetMetadata (player id), Revive, RegisterItem, RegisterUsableItem, UnregisterUsableItem, Notify, StartProgress, StopProgress, RegisterCraftingBench, UnregisterCraftingBenchAddMoneyOffline, SetJob, SetGang, RemoveJob, RemoveGang, GetNeeds, AddNeeds, SetNeeds, the stash exports and OpenStash, RevokeKeys, RevokeAllKeys, GiveKeys, SetVehicleState, GetVehicle, GetOwnedVehicles, AddVehicle, the door writes, and the item, metadata and key exports when target is a citizen id. The promise form for every other write is a safe habit.
  • A call that may reach the database, made synchronously, answers export.mustAwait before touching anything, so it is safe to retry with the promise form.
  • await needs a thread: CreateThread, an event handler or a command handler, never file scope.

Your manifest

my_shop/open77.lua
dependency "opx_infinity"  -- optional, recommended
  • A declared dependency starts opx_infinity first and stops your resource with it. It grants nothing: the allowlist still decides.
  • Publishing and calling exports needs no permission.
  • A client resource that wants answers must publish a reply export: see Client exports.

On this page