Convert from FiveM
Last updated on
How FiveM, ESX and QBCore habits map onto Open77 and opx_infinity — what stays, what changes, and where each familiar framework call now lives.
The runtime shape of Open77 is close to FiveM: CreateThread, Wait, RegisterNetEvent, TriggerServerEvent, RegisterCommand and exports all exist. The natives do not: Open77 has its own Open77.* API. And OPX//77 is not ESX or QBCore, even where the names look familiar.
For the old opx77_* resources, read From opx77_* to opx_infinity instead.
Decide where your code goes
| Your code | Put it in |
|---|---|
| Gameplay that needs money, jobs, items, vehicles | a module inside opx_infinity — the only place the contracts are reachable |
| Something independent: a job, a shop, a log tool | a separate resource using the creator exports |
Runtime habits
| FiveM habit | Open77 / OPX//77 |
|---|---|
Natives such as GetPlayerPed, SetEntityCoords | Different API. Look up each one with the Open77 devkit (open77_fivem_equivalent); never guess a name. |
while true do ... Wait(0) end on the client | OPX.Scheduler.Every. The client has a per-resume instruction budget; an overrun stops the loop silently. |
require / shared Lua modules on the server | Not available on the server. Shared helpers are in lib/. |
| Metatables / classes in shared code | Not available on the client. Use plain tables. |
CfxLua syntax (vectors, backtick hashes, ?., +=) | Plain Lua 5.4 only. |
TriggerEvent to talk to another resource on the client | Does not leave the resource on Open77. |
ExecuteCommand with console authority | Needs runtime.commands, and restricted commands are refused. |
NUI page per resource, SendNUIMessage | One shared WebUI page; OPX.UI.Send on a named channel. See The WebUI page. |
fxmanifest.lua | open77.lua, a manifest DSL with a permissions { } block. List every script on its own line. |
| Server ACE permissions | ACL rights in acl.jsonc; a restricted command checks command.<name>. See Permissions. |
oxmysql | The platform's MySQL bridge (MySQL), wrapped by OPX.Storage. |
ESX / QBCore calls
The character API is QBCore-shaped (PlayerData, citizenId, Functions), but reached through the character contract, server side, inside opx_infinity.
local character = OPX.Api.Get('character')
local player = character.GetPlayer(source)| ESX / QBCore | OPX//77 (server, inside a module) |
|---|---|
QBCore.Functions.GetPlayer(src) / ESX.GetPlayerFromId(src) | character.GetPlayer(source) |
Player.PlayerData | player.PlayerData — see the Player object |
Player.Functions.AddMoney('bank', n, reason) / xPlayer.addAccountMoney | character.AddMoney(source, 'BANK', n, reason) — answers ok, code |
Player.Functions.RemoveMoney | character.RemoveMoney |
Player.Functions.SetJob(job, grade) | character.SetJob (yields) |
Player.Functions.SetMetaData | character.SetMetadata |
QBCore.Functions.GetPlayers() | character.GetPlayers() |
exports['qb-inventory']:AddItem / xPlayer.addInventoryItem | the inventory contract |
QBCore.Functions.Notify / ESX.ShowNotification | OPX.Notify (server) or OPX.Toast.Show (client) |
QBCore.Functions.CreateCallback | a network event pair, or OPX.UI.On plus OPX.UI.Answer for the page; on the client, Lib.Callback in opx_lib |
qb-menu / esx_menu_default | the menu module |
qb-input / esx_dialog | the form module |
qb-target / ox_target | the target module |
qb-garages | the garages module |
money hooks / onMoneyChange | OPX.Hooks money:beforeAdd and friends |
Money types are upper case (EDDIES, BANK), from MONEY.TYPES.
A short checklist
- Move the code into a module folder, or decide it stays a separate resource.
- Replace every native using the devkit.
- Replace client loops with scheduler jobs.
- Replace framework calls with contract calls (table above).
- Re-check every network payload on the server.
- Move text into
locales.lua(English and French). - List every file in
open77.lua; add the permissions your natives need. - Run
lua tests/run.lua.
Write a separate resource
How a resource outside opx_infinity uses OPX//77 — server and client exports, public server events, opx_lib — what the player state bag no longer carries, and what it still cannot do.
Contributing
How to change opx_infinity, opx_lib or this site — branches, checks before pushing, code conventions, text, and the documentation to update in the same change.