Containers & Bags
Containers & Bags
Every place items can sit is the same kind of object: a container with an id, a slot count, a weight ceiling and a version. A player's pockets, a police stash, a car boot and a backpack lying in the road are all the same code path.
Container types
| Type | Id shape | Notes |
|---|---|---|
player |
player:ABC12345 |
Pockets. Slots and weight from Config.Player |
stash |
stash:police_armory |
Fixed in the world, optionally job-gated. A personal (owned) one is stash:<id>:<citizenid> |
trunk |
trunk:XYZ789 |
Per-plate, reachable from outside the car. Capacity per model |
glovebox |
glove:XYZ789 |
Per-plate, reachable while seated |
wear |
wear:ABC12345 |
Worn clothing — see Clothing & Wear |
container |
container:01J8MHKQX2 |
A bag item's own inside |
drop |
drop:1755913211_4 |
Items on the ground |
Bags are real inventories
A backpack is an item you can carry and a container you can open. It has its own id, its own slots, and it survives being dropped, traded or stored.
Two rules make this honest rather than a duplication exploit:
A bag weighs what it holds. Put 5 kg into a backpack and the backpack now weighs 5 kg plus its own mass, immediately, everywhere it is counted.
Bags do not nest. A container cannot go inside another container. This is the oldest inventory dupe there is, and it is refused at the engine's rule layer rather than patched at each call site.
Panels close when they must
If a bag you have open leaves your possession — dropped, traded, given away — the panel closes for everyone looking at it, immediately. The check runs on commit, not only when somebody tries to touch something, so there is no window in which a stale panel is still writable.
Distance is checked on commit too. Stray more than a metre past Config.OpenRadius (3 m) from a stash and the server forgets the opening, so the next move in or out of it is refused.
Drops
Anything thrown or dropped becomes a drop container in the world, shown by a red marker as in ox (Config.Drop.prop.enabled = true puts a bag on the ground instead). Open the inventory beside one and it is the right-hand panel. Drops are real containers — they can be looted by anyone, and every pickup is a ledger row — but they live in memory only: a pile nobody has used for five minutes is cleared, and none survive a restart.
Config.Drop = { slots = 50, maxWeight = 30000 }
A pile that already holds something refuses what would take it past 30 kg; an empty pile takes its first stack whatever it weighs.
Weight and slots
Both limits are enforced server-side on every move. A move that would breach either does not partially apply — the whole transaction is refused and the interface says which limit stopped it.
Config.Player = { slots = 50, maxWeight = 30000 }
Vehicle capacity is set per model in Config.Vehicle.trunk.models, using ox's per-class sizes (keyed by model because the class native exists only on the client); an unlisted model gets trunk.default, and every glovebox is Config.Vehicle.glovebox. Stash capacity is per stash, set where the stash is registered.