FiveM Development — vRP
Framework Architecture
vRP Creative Network is based on Lua 5.4 with communication via Proxy (server-to-server) and Tunnel (client-server).
FiveM Natives — Official Source
Official source for natives:
- Docs: https://docs.fivem.net/natives/
- Official Repository (mirror): https://github.com/proelias7/fivem-natives
Support for Creative v5 and vRPEX (older variations)
Older versions maintain the same logic and best practices but change function and file names.
- Creative v5: core in
camelCase,modules/group.lua, configs inconfig/*.lua. - vRPEX: classic core (
getUserId,getUserSource,getUsers, etc.) and configs incfg/*.lua.
See the full mapping in reference.md.
Key Concepts
| Concept | Description |
|---|---|
| Passport | Unique character ID (equivalent to user_id in other vRPs) |
| Source | Player connection ID on the server (changes on every reconnection) |
| Datatable | In-memory table with character data (inventory, position, skin, etc.) |
| Characters | Global server-side table indexed by source with character data |
| Sources | Global table Sources[Passport] = source for reverse lookup |
Identification Flow
-- Server-side: get Passport from source
local Passport = vRP.Passport(source)
-- Server-side: get source from Passport
local source = vRP.Source(Passport)
-- Server-side: get character Datatable
local Datatable = vRP.Datatable(Passport)
-- Server-side: get inventory
local Inventory = vRP.Inventory(Passport)
Proxy/Tunnel System
-- In any SERVER-SIDE resource, get access to vRP:
local Proxy = module("vrp", "lib/Proxy")
vRP = Proxy.getInterface("vRP")
-- In any CLIENT-SIDE resource:
local Tunnel = module("vrp", "lib/Tunnel")
local Proxy = module("vrp", "lib/Proxy")
vRPS = Tunnel.getInterface("vRP") -- call server functions
-- Expose your resource functions (server):
myResource = {}
Proxy.addInterface("myResource", myResource)
Tunnel.bindInterface("myResource", myResource)
Fire-and-forget Rule
Prefix Tunnel calls with _ to not wait for a response:
-- Await response (blocking)
local result = vRP.Generateitem(Passport,"water",1)
-- Fire-and-forget (non-blocking)
vRP._Generateitem(Passport,"water",1)
Main API (Server-side)
Player/Identity
| Function | Parameters | Return | Description |
|---|---|---|---|
vRP.Passport(source) | source | Passport|false | Gets player Passport |
vRP.Source(Passport) | Passport | source|nil | Gets source from Passport |
vRP.Datatable(Passport) | Passport | table|false | Character in-memory data |
vRP.Inventory(Passport) | Passport | table | Character inventory |
vRP.Identity(Passport) | Passport | table|false | Character data (name, name2, bank, phone, etc.) |
vRP.FullName(source) | source | string|false | Character full name |
vRP.Players() | — | table | Returns Sources (Passport→source) |
vRP.Kick(source, Reason) | source, string | — | Kicks the player |
vRP.Teleport(source, x, y, z) | source, coords | — | Teleports the player |
vRP.GetEntityCoords(source) | source | vector3 | Player coordinates |
vRP.ModelPlayer(source) | source | string | Ped model (mp_m/mp_f) |
Money
| Function | Parameters | Return | Description |
|---|---|---|---|
vRP.GetBank(source) | source | number | Bank balance |
vRP.GiveBank(Passport, Amount) | Passport, number | — | Adds money to bank |
vRP.RemoveBank(Passport, Amount) | Passport, number | — | Removes money from bank |
vRP.PaymentBank(Passport, Amount) | Passport, number | bool | Pays with bank (checks balance) |
vRP.PaymentMoney(Passport, Amount) | Passport, number | bool | Pays with cash |
vRP.PaymentFull(Passport, Amount) | Passport, number | bool | Tries cash, then bank |
vRP.PaymentDirty(Passport, Amount) | Passport, number | bool | Pays with dirty money |
vRP.WithdrawCash(Passport, Amount) | Passport, number | bool | Bank withdrawal |
vRP.PaymentGems(Passport, Amount) | Passport, number | bool | Pays with gems |
vRP.GetCoins(Passport) | Passport | number | Gets coins |
vRP.AddCoins(Passport, Amount) | Passport, number | bool | Adds coins |
vRP.RemCoins(Passport, Amount) | Passport, number | bool | Removes coins |
Inventory
| Function | Parameters | Return | Description |
|---|---|---|---|
vRP.GiveItem(Passport, Item, Amount, Notify, Slot) | ... | — | Gives item (no durability) |
vRP.GenerateItem(Passport, Item, Amount, Notify, Slot) | ... | — | Gives item (with durability/charges) |
vRP.TakeItem(Passport, Item, Amount, Notify, Slot) | ... | bool | Removes item (returns success) |
vRP.RemoveItem(Passport, Item, Amount, Notify) | ... | — | Removes item (no return) |
vRP.ItemAmount(Passport, Item) | Passport, string | number | Item amount |
vRP.ConsultItem(Passport, Item, Amount) | ... | bool | Checks if has amount |
vRP.InventoryWeight(Passport) | Passport | number | Current weight |
vRP.GetWeight(Passport) | Passport | number | Max weight |
vRP.SetWeight(Passport, Amount) | Passport, number | — | Adds to max weight |
vRP.MaxItens(Passport, Item, Amount) | ... | bool | Checks item max limit |
vRP.ClearInventory(Passport) | Passport | — | Clears inventory |
Groups/Permissions
| Function | Parameters | Return | Description |
|---|---|---|---|
vRP.HasPermission(Passport, Permission, Level) | ... | bool | Checks direct permission |
vRP.HasGroup(Passport, Permission, Level) | ... | bool | Checks group (includes parents) |
vRP.HasService(Passport, Permission) | ... | bool | Checks if in service |
vRP.SetPermission(Passport, Permission, Level, Mode) | ... | — | Sets permission |
vRP.RemovePermission(Passport, Permission) | ... | — | Removes permission |
vRP.ServiceToggle(Source, Passport, Permission, Silenced) | ... | — | Toggles service |
vRP.NumPermission(Permission, Level) | ... | table, number | Players in service |
vRP.CheckGroup(Passport, Type) | ... | bool | Checks group by type |
vRP.HasAction(Passport) | Passport | bool | Checks police action |
vRP.SetAction(Passport, Status) | ... | — | Sets action status |
Survival
| Function | Parameters | Description |
|---|---|---|
vRP.UpgradeHunger(Passport, Amount) | ... | Increases hunger |
vRP.DowngradeHunger(Passport, Amount) | ... | Decreases hunger |
vRP.UpgradeThirst(Passport, Amount) | ... | Increases thirst |
vRP.DowngradeThirst(Passport, Amount) | ... | Decreases thirst |
vRP.UpgradeInfection(Passport, Amount) | ... | Increases infection |
vRP.DowngradeInfection(Passport, Amount) | ... | Decreases infection |
vRP.Revive(source, Health) | ... | Revives player |
Database
-- Register prepared query
vRP.Prepare("name/query", "SELECT * FROM table WHERE id = @id")
-- Execute query
local result = vRP.Query("name/query", { id = 123 })
Uses oxmysql internally. Parameters with @name.
Persistent Data
-- Server Data (entitydata — global data)
local data = vRP.GetSrvData("UniqueKey")
vRP.SetSrvData("UniqueKey", { field = "value" })
-- Player Data (playerdata — data per player)
local data = vRP.UserData(Passport, "key")
vRP.setUData(Passport, "key", json.encode(data))
Global Utilities
| Function | Description |
|---|---|
parseInt(value) | Converts to integer (min. 0) |
parseFormat(value) | Formats number with thousand separator |
splitString(str, symbol) | Splits string by separator |
SplitOne(name) | First element of split |
sanitizeString(str, chars, allow) | Filters characters |
CompleteTimers(seconds) | Formats full time in HTML |
MinimalTimers(seconds) | Formats summarized time |
CountTable(table) | Counts items in table |
async(func) | Executes asynchronous function |
Client-Server Communication
Notification Events
-- Server-side: simple notification
TriggerClientEvent("Notify", source, "success", "Message.", false, 5000)
-- Types: "success", "important", "negado" (denied)
-- Server-side: item notification
TriggerClientEvent("NotifyItens", source, { "+", "itemIndex", "amount", "Item Name" })
-- "+" for gain, "-" for loss
Important Events
| Event | Side | Description |
|---|---|---|
"Connect" | Server | Player chose character (Passport, Source) |
"Disconnect" | Server | Player disconnected (Passport, Source) |
"CharacterChosen" | Server | Character chosen (Passport, source) |
"vRP:Active" | Client | Player activated (source, Passport, Name) |
Critical Performance Rules (Summary)
ALWAYS follow these rules when writing code:
- Tunnel vs Event: Use
TriggerServerEvent/TriggerClientEventwhen you do NOT need a return. Use Tunnel only when you NEED a return. - Dynamic Sleep: NEVER fixed
Wait(0). Adjust based on state (dist < 20 =0, dist < 50 =500, else =1000+). - Calls in same environment: Call functions directly. NEVER use
TriggerEvent()to call on the same side. - No remote calls in loops: Do not use Tunnel/Events in loops < 5 seconds. Prefer batch or delta.
- Small Payloads: Send only the change, not full data. Limit of ~8KB per event.
- Cache: Use
exports.cacheaside:Get()for repeated database queries. Never query the database in a loop. - SafeEvent (server): Every event that gives money/item/advantage MUST pass through
exports["cerberus"]:SafeEvent(source, "eventName", { time = N }). - SetCooldown (client): Repetitive actions on client (open menu, use item) must use
exports["cerberus"]:SetCooldown("name", ms). - Tables > if/else: For 3+ conditions, use lookup table (O(1)) instead of if/elseif chains.
- Protect nil: Always check variables before concatenating. Use
or ""as fallback.
UI Construction (React + Vite)
Stack: React 18 + TypeScript + Vite + Tailwind CSS + Zustand.
Fundamental Rules:
base: "./"in vite.config.ts (MANDATORY for FiveM)- Use
remfor ALL sizes — NEVERpxfor layout - Media queries in
htmlfont-size to scale with player resolution - Tailwind v4 uses OKLCH and FiveM CEF does not support it. Use Tailwind v3.4.17.
- FORBIDDEN:
backdrop-filter: blur(),filter: blur(),filter: drop-shadow()— cause FPS drop - FORBIDDEN: framer-motion, GSAP, react-spring — heavy animation libs
- Use pure CSS transitions/keyframes for animations
- Independent modules (Notify, Progress) outside VisibilityProvider
- Main interface inside VisibilityProvider with NuiFocus
- Global
overflow: hiddenanduser-select: none isEnvBrowser()for data mocking in dev- Communication:
observe()to listen to NUI,Post.create()to send callbacks
For complete UI guide: ui-guide.md
Additional References
- For UI construction guide (React + Vite + FiveM): ui-guide.md
- For detailed best practices (performance, security, cache): best-practices.md
- For complete and detailed API: reference.md
- For code examples: examples.md
- For resource templates: templates.md
- For patterns and conventions: patterns.md
External Resources (Download)
Use these official repositories when the project mentions dependencies:
cacheaside(in-memory cache):git@github.com:proelias7/cacheaside.gitcerberus(anti-exploit + cooldowns):git@github.com:proelias7/cerberus.git
vRPex Compatibility
The vRP Creative Network has compatibility aliases with classic vRP:
| vRPex (old) | Creative Network (current) |
|---|---|
getUserId | Passport |
getUserSource | Source |
getUserIdentity | Identity |
getUserDataTable | Datatable |
hasGroup | HasGroup |
hasPermission | HasPermission |
giveInventoryItem | GiveItem |
tryGetInventoryItem | TakeItem |
getInventoryItemAmount | ItemAmount |
giveMoney | GiveBank |
tryFullPayment | PaymentFull |
getBankMoney | GetBank |
query / execute | Query |
prepare | Prepare |
ALWAYS use the native Creative Network names (right column), not the aliases.