ATY Scripts Logo
ATY Scripts/Docs/Inventory/Architecture

Architecture

Architecture

The one rule

The client never decides anything. The NUI is a view and an input device. It proposes moves; the server validates, commits and broadcasts the result.

A move the client believes in but the server refuses simply does not happen, and the interface corrects itself from the server's answer rather than from its own optimism.

The transaction engine

Every mutation — a drag, a purchase, a craft, a trade, a pickup, a death drop — goes through the engine in server/core/transaction.lua.

propose  →  VALIDATE  →  commit  →  ledger  →  broadcast

VALIDATE is where every rule lives. Weight, slots, pinning, bag nesting, evidence, licences, carry limits — all of them are checked in one place, on one code path.

This is the single most important design decision in the resource. A rule added to `VALIDATE` holds everywhere at once. A rule added at a call site holds only there, and the next feature that moves items will quietly bypass it — which is exactly how inventories grow dupes.

Concretely, five rules were moved into VALIDATE after being found missing somewhere: evidence, bound items, pinning, carrying a placeable, and carrying a craft result. Each had a path around it before.

Versioned containers

Every container carries a version, and every commit bumps it. A move carries the version the player's screen was showing; if the container has changed since, the move is refused as stale_version and the player is handed the current contents instead of a silently different outcome. Two commits never touch one container at the same time: each locks every container it touches, in a fixed order, for the length of the commit.

This is what keeps two players moving items in a shared stash from overwriting each other.

Layout

shared/config.lua          all settings
data/items.lua             item definitions
data/recipes.lua           crafting recipes

client/                    NUI bridge, markers, targets, mirrors
server/
  core/transaction.lua     the engine — every mutation
  types/*.lua              container behaviours: stash, wear, placeable, …
  api/*.lua                exports and self-tests
  admin.lua                the admin panel's dispatcher
compat/
  qb-inventory/            name proxy
  ox_inventory/            name proxy
ui/                        built NUI (Vue 3 + Vite + Pinia)
web/                       NUI source

The framework bridge

Player data — identity, job, money, needs — is asked of aty_lib, not of QBCore or ESX: client/framework.lua on the client, Utils / modules on the server, and every other file gets the same answer whatever the server runs. Two deliberate exceptions: Qbox, which the bridge does not know by name, is asked through qbx_core directly (see Compatibility), and the qb compatibility layer and the migration tool talk to qb-core by name, because that is their job.

That is why standalone mode is not a special case with its own code path — it is one more answer the bridge can give.

The NUI

Vue 3 with Pinia, built by Vite into ui/. The same built artifact serves the game and the demo on the website; a mock layer stands in for the server when it detects it is running in a plain browser.

NUI messages sent to a page that has not mounted yet are **dropped, not queued**. If you are pushing state to the interface on connect, have the interface ask for it instead — that race is real and it presents as an inexplicably empty panel.
ATY Scripts LogoATY SCRIPTS

Crafting highly optimized FiveM scripts for QBCore & ESX. Maximum performance, precision code, zero lag.

Join Community

Partner

Official partners with Tebex. Secure checkout and Cfx.re Keymaster integration.

Legal

Not affiliated with Rockstar Games, Cfx.re, FiveM, or Take-Two Interactive. Purchases bound by Tebex Terms of Service.

© 2026 ATY SCRIPTS. All rights reserved.