A server-authoritative inventory system for hexa_core, built around flexible grids, persistent storage, secure transactions, and extensible item behaviour.
Grid Inventory · Stashes · Shops · Drops · Trading · Quick Slots · Persistence
hexa_inventory is the primary inventory system for the Hexa Framework ecosystem.
It provides persistent player inventories and shared containers through a grid-based interface where items can occupy different amounts of space instead of being limited to traditional one-item-per-slot layouts.
The system is designed around three rules:
- The server owns inventory state
- The client never decides whether a transaction is valid
- Inventory behaviour should be configurable without rewriting core logic
Player
│
▼
┌───────────────────────────┐
│ hexa_inventory │
├───────────────────────────┤
│ Player Inventory │
│ Quick Slots │
│ Stashes │
│ Shops │
│ Ground Drops │
│ Trading │
│ Item History │
│ Durability │
│ Grid Validation │
└─────────────┬─────────────┘
│
▼
hexa_core
│
▼
Persistence
Items can occupy one or multiple cells within the inventory.
A normal item may use a single cell:
┌───┐
│ × │
└───┘
1 × 1
while larger items can consume more physical inventory space:
┌───┬───┐
│ │ │
├───┼───┤
│ │ │
└───┴───┘
2 × 2
Item footprints can be configured individually:
config.ItemRules = {
SlotSize = {
['water_bucket'] = {
width = 2,
height = 2,
},
},
}This makes inventory capacity depend on both weight and available grid space.
Inventory state is persisted through hexa_core.
Supported storage includes:
- Player inventories
- Player vault data
- Shared stashes
- Ground drops
The required database tables are managed by the hexa_core schema installer.
users
users_vault
item_drops
No separate manual inventory schema import is required under the normal Hexa installation flow.
Each player has a persistent inventory containing their items, metadata, durability, quantities, and grid positions.
Supported operations include:
- Drag
- Drop
- Swap
- Stack
- Split stack
- Amount entry
- Bulk transfer
- Quick-slot assignment
- Inventory sorting
All moves are validated server-side before inventory state is committed.
Quick slots are separated from the main inventory grid.
By default:
Alt + 1
Alt + 2
Alt + 3
Alt + 4
Alt + 5
can be used to activate quick-slot items.
Items can individually be prevented from entering the quick-slot area:
config.ItemRules = {
DisableQuickSlot = {
'example_item',
},
}This is useful for items that should remain inside normal inventory storage.
Individual item behaviour can be controlled from:
config/items.lua
Example:
config.ItemRules = {
DisableUse = {
'example_item',
},
DisableStack = {
'unique_document',
},
DisableDrop = {
'protected_item',
},
DisableQuickSlot = {
'large_container',
},
SlotSize = {
['water_bucket'] = {
width = 2,
height = 2,
},
},
}This allows behaviour to be changed without modifying inventory internals.
Items listed under DisableDrop cannot be transferred into ground containers.
When a ground drop is open, protected items are visually locked and displayed transparently with a cross.
More importantly, this restriction is enforced again by the server.
Client Request
│
▼
Move Protected Item
│
▼
Server Validation
│
├── Allowed ──► Move
│
└── Blocked ──► Reject
Changing the UI or forging a client event does not bypass the restriction.
Items can be transferred into persistent ground bags.
Ground drops support:
- Persistent contents
- Configurable weight capacity
- Configurable grid capacity
- Server-side item restrictions
- Cleanup countdown
- Cleanup pause while being viewed
- Unlimited capacity mode
Ground bags can be opened but cannot be picked up or carried.
Set either capacity value to -1 to remove that limit.
DropSize = {
maxweight = -1,
slots = -1,
}The UI does not attempt to render an infinite grid.
Instead, unlimited containers dynamically expand as additional inventory space is required.
Resources can create persistent or shared inventory containers through the inventory API.
Example:
exports.hexa_inventory:OpenInventory(
source,
'stash-ranch-1',
{
label = 'Ranch Storage',
maxweight = 500,
slots = 100,
}
)This can be used for systems such as:
- Ranch storage
- Job storage
- Houses
- Warehouses
- Camp storage
- Evidence storage
- Shared faction inventories
Shop inventories are supported through the same inventory interface.
Shop behaviour can be configured in:
config/shops.lua
Supported systems include:
- Shop inventory
- Restocking
- Vending objects
- Item availability
- Configurable inventory behaviour
Players can exchange items through the built-in trading system.
Default command:
/trade
Trades are validated by the server to prevent either client from directly controlling the final inventory state.
Player A
│
▼
Trade Session
▲
│
Player B
│
▼
Server Validation
│
▼
Inventory Commit
The transaction is completed only after server-side validation succeeds.
Inventory changes can be recorded by citizen ID.
History can track events such as:
Received Item
Lost Item
Added Item
Removed Item
Transferred Item
This is useful for debugging gameplay systems and tracing unexpected inventory changes.
Items may carry durability metadata.
The UI can warn players when durability falls below a configurable threshold.
Durability warnings support:
- Configurable threshold
- Visual warning
- Warning sound
- Item-specific durability state
Configuration is located in:
config/features.lua
Open inventories can be sorted by:
- Type
- Rarity
- Name
Default key:
B
Sorting respects item grid dimensions rather than treating every item as a single-slot object.
| Requirement | Description |
|---|---|
hexa_core |
Version 3.x |
oxmysql |
Database communication |
| FXServer / RedM | Server runtime |
Place the resource inside your server resources directory.
The folder name must remain exactly:
hexa_inventory
Example:
resources/
│
└── [hexa]/
├── hexa_core/
└── hexa_inventory/
Add the dependencies before the inventory resource:
ensure oxmysql
ensure hexa_core
ensure hexa_inventoryStartup order:
oxmysql
│
▼
hexa_core
│
▼
hexa_inventory
│
▼
Gameplay Resources
The required tables are managed by the hexa_core schema installer.
users
users_vault
item_drops
Start the server normally and allow hexa_core to handle the base schema.
English is used by default.
To use Thai:
setr hexa_inventory:locale thSet the locale before starting hexa_inventory.
Configuration is separated by responsibility instead of being placed into one oversized file.
| File | Purpose |
|---|---|
config/general.lua |
Inventory size, drops, controls, commands, quick slots, give range, and compatibility |
config/items.lua |
Item use, stack, drop, quick-slot, and grid-size rules |
config/features.lua |
Sorting, durability warnings, item history, and hotbar protection |
config/shops.lua |
Shop, restocking, and vending configuration |
config/cfg.weapons.lua |
Weapon classes, slots, and native weapon behaviour |
| Action | Default |
|---|---|
| Open inventory | I |
| Show hotbar | Z |
| Quick slot | Alt + 1 — Alt + 5 |
| Sort inventory | B |
| Open ground drop | Hold E |
| Open vending object | Hold E |
| Trade with player | /trade |
Bindings can be changed through configuration where supported.
Add an item to a player's inventory.
local stored, dropped = exports.hexa_inventory:AddItem(
source,
'bread',
1,
false,
{},
'reward'
)The result distinguishes between inventory insertion and overflow/drop behaviour:
stored
droppedRemove an item from a player.
local removed = exports.hexa_inventory:RemoveItem(
source,
'bread',
1,
false,
'consume'
)Open another inventory container for a player.
exports.hexa_inventory:OpenInventory(
source,
'stash-ranch-1',
{
label = 'Ranch Storage',
maxweight = 500,
slots = 100,
}
)hexa_inventory includes optional compatibility helpers for resources originally written against RSG or VORP inventory APIs.
This is primarily intended to reduce migration work.
Existing Resource
│
▼
Compatibility API
│
▼
hexa_inventory
│
▼
hexa_core
For native Hexa resources, using the Hexa inventory exports directly is recommended.
Compatibility support includes commonly used RSG-style inventory events and APIs where implemented.
The goal is interface compatibility rather than running the original RSG inventory alongside Hexa.
VORP-shaped helpers include APIs such as:
getUserInventoryItems
getItem
getItemCount
canCarryItem
addItem
subItem
registerUsableItem
registerInventory
openInventory
Compatibility coverage may expand as additional resources and API patterns are tested.
Note
Compatibility helpers do not make hexa_inventory a complete reimplementation of another framework's inventory.
Resources that depend on undocumented internals, direct database access, or unusual framework-specific behaviour may still require adjustments.
Inventory systems are a common exploit target, so important operations are validated on the server.
The client is responsible primarily for interaction and presentation.
CLIENT
│
User Interaction
│
▼
Inventory Request
│
▼
┌──────────────────────────┐
│ SERVER │
├──────────────────────────┤
│ Validate Item │
│ Validate Amount │
│ Validate Source │
│ Validate Destination │
│ Validate Grid Space │
│ Validate Weight │
│ Validate Item Rules │
│ Validate Trade State │
└────────────┬─────────────┘
│
▼
Commit Inventory
│
▼
Synchronise UI
Client-side restrictions are treated as UX.
Server-side validation is treated as authority.
The inventory interface supports:
- Grid-based drag and drop
- Multi-cell items
- Stack splitting
- Amount selection
- Quick slots
- Inventory weight
- Sorting
- Durability indicators
- Locked item states
- Ground inventories
- Stashes
- Shops
- Player trading
- Inventory history
Preview:
Smoke tests are included for inventory behaviour and UI drag logic.
Requirements:
- Lua
- Node.js
Run inventory tests:
lua tests/inventory_smoke.luaRun UI drag tests:
node tests/ui_drag_smoke.jsThese tests are intended to catch basic regressions in inventory logic and client-side grid interactions.
┌─────────────────┐
│ hexa_core │
└────────┬────────┘
│
▼
┌─────────────────┐
│ hexa_inventory │
└────────┬────────┘
│
┌────────────────────────┼────────────────────────┐
│ │ │
▼ ▼ ▼
Player Inventory Stashes Shops
│ │ │
├──────────────┐ │ │
▼ ▼ ▼ ▼
Quick Slots Drops Storage Vendors
│
▼
Trading
Gameplay resources interact with inventory through its public API instead of manipulating persistent inventory state directly.
For new Hexa resources:
local stored, dropped = exports.hexa_inventory:AddItem(
source,
'bread',
1,
false,
{},
'mission_reward'
)Prefer public inventory APIs over:
- Directly editing player inventory tables
- Sending arbitrary inventory mutations from the client
- Writing directly to inventory database columns
- Reimplementing item transfer logic in every resource
Keeping mutations inside the inventory service makes validation, persistence, logging, and compatibility significantly easier to maintain.
hexa_inventory is one resource in the Hexa Framework stack. Each part is its own repository.
| Project | Description |
|---|---|
hexa_core |
Core framework — players, jobs, items, economy, status, callbacks, permissions |
hexa_inventory |
Persistent grid inventory — stashes, shops, ground drops, secure trading (this repository) |
hexa_progbar |
Screen-fixed progress bar — drop-in for ox_lib progressBar |
hexa-bridge |
Compatibility layer for supported RSG and VORP resources |
hexa-docs |
Official documentation and API reference (VitePress) |
rdr2-unpack |
Read a local RDR2 install into open formats — GLB, PNG, .ymap JSON |
txAdmin |
One-click txAdmin recipe that deploys the whole Hexa stack |
Full API reference and installation guides live in hexa-docs → hexa-development.github.io/hexa-docs
This project is derived from RSG Inventory.
The original upstream license and attribution are retained in:
Review the repository license before redistribution or modification.
Built for Hexa Framework
Documentation · เอกสารภาษาไทย · hexa_core · hexa_inventory · hexa_progbar · hexa-bridge · Organization
More than slots. Actual inventory space.
