Essential Library

Essential Library Essential Library
  • Essential Library
  • Essential Library

This item is free.

Add to Basket

House X Studios — Core Library

A lightweight, framework-agnostic core library for FiveM resources. hx-lib provides a single unified API (hx.*) on top of QBox, QBCore, and ESX, plus batteries-included modules for callbacks, logging, localization, map entities (blips, peds, markers), and a bundled NUI component kit.


Features

  • Multi-framework bridge — auto-detects QBox, QBCore, or ESX at runtime; your code calls one API regardless of the active framework.

  • Client ↔ server callbacks — promise-free callback system with automatic timeout cleanup.

  • Leveled logger — colored console output with debug / info / warn / error levels, runtime-adjustable.

  • Localization — JSON locale files with printf-style formatting and automatic English fallback.

  • Map entity managers — create and auto-clean blips, peds, and interactive markers; everything is tracked and removed on resource stop.

  • Bundled NUI kit — alerts, context menus, notifications, dialogs, skill checks, interaction prompts, action bars, list menus, and radial menus, with two themes.

  • Self update check — compares the running version against the latest GitHub release.

  • Drop-in imports — pull the library into any resource with a single @hx-lib/imports/*.lua line.


Requirements

  • A recent FiveM artifacts build (Lua 5.4 support required).

  • One of the supported frameworks installed and started:

Framework

Detected resource

Inventory used

QBox

qbx_core

ox_inventory

QBCore

qb-core

framework default

ESX

es_extended

ESX built-in

hx-lib works without a framework loaded, but hx.Bridge.* calls will be unavailable and a warning is logged on start.


Installation

  1. Drop the hx-lib folder into your server resources directory.

  2. Start hx-lib before any resource that depends on it. Add it high in your server.cfg, immediately after your framework:

    ensure qbx_core      # or qb-core / es_extended
    ensure ox_inventory  # if using QBox
    ensure hx-lib
    
  3. Import the library in your own resource (see Quick Start).


Framework Support

The active framework is detected automatically by checking resource state, in this order: QBox → QBCore → ESX.

hx.Bridge.GetFramework()   --> 'qbox' | 'qbcore' | 'esx' | nil
hx.Bridge.Is('qbox')       --> boolean

All hx.Bridge.* functions below present the same signature on every framework, so your resource code never branches on framework type.


Quick Start

Add the imports you need to your resource's fxmanifest.lua. These lines load hx-lib's modules into your resource's Lua state, exposing the global hx table.

-- your_resource/fxmanifest.lua
shared_scripts {
    '@hx-lib/imports/shared.lua',
}

client_scripts {
    '@hx-lib/imports/client.lua',
    'client/main.lua',
}

server_scripts {
    '@hx-lib/imports/server.lua',
    'server/main.lua',
}

Then use it anywhere:

-- server/main.lua
RegisterCommand('paycheck', function(source)
    local name = hx.Bridge.GetName(source)
    hx.Bridge.AddMoney(source, 'bank', 500, 'paycheck')
    hx.Bridge.Notify(source, ('%s received $500'):format(name), 'success')
    hx.Log.Info('myresource', 'Paid %s', name)
end)
-- client/main.lua
local blip = hx.Blip.Create({
    coords = vec3(441.0, -982.0, 30.6),
    sprite = 60, color = 29, scale = 0.9,
    label = 'Police Station',
})

API Reference

Availability legend:  server ·  client ·  shared

hx.Bridge — framework abstraction

**Server **

Function

Returns

Description

GetPlayer(source)

player object

Raw framework player object.

GetIdentifier(source)

string|nil

Citizen ID / license identifier.

GetName(source)

string

"Firstname Lastname" (or "Unknown").

GetJob(source)

table|nil

Normalized job (see below).

GetMoney(source, type)

number

type is 'cash', 'bank', etc.

AddMoney(source, type, amount, reason)

boolean

RemoveMoney(source, type, amount, reason)

boolean

Notify(source, msg, type?, duration?)

type defaults to 'inform'.

AddItem(source, item, count, metadata?)

boolean

metadata honored on QBox (ox_inventory).

RemoveItem(source, item, count, metadata?)

boolean

HasItem(source, item, count?)

boolean

count defaults to 1.

GetInventory(source)

table

Normalized job shape returned by GetJob:

{
    name      = 'police',
    label     = 'Police',
    grade     = 3,          -- numeric level
    gradeName = 'sergeant',
    onDuty    = true,
    isBoss    = false,
}

**Client **

Function

Returns

Description

GetPlayerData()

table

Raw framework player data.

GetJob()

table|nil

Same normalized shape as server.

Notify(msg, type?, duration?)

Local notification.

-- Server
if hx.Bridge.HasItem(source, 'lockpick', 1) then
    hx.Bridge.RemoveItem(source, 'lockpick', 1)
    hx.Bridge.AddMoney(source, 'cash', 250, 'sold-loot')
end

-- Client
local job = hx.Bridge.GetJob()
if job and job.name == 'police' and job.onDuty then
    hx.Bridge.Notify('Welcome on duty, officer.', 'success')
end

Money types: ESX maps 'cash' to its 'money' account internally, so use 'cash' / 'bank' everywhere for portability.


hx.Callback — client/server callbacks

Request data from the server and get the result in a callback. Pending requests time out after Config.CallbackTimeout (default 10s) and are cleaned up automatically.

-- Server: register
hx.Callback.Register('myresource:getBalance', function(source, account)
    return hx.Bridge.GetMoney(source, account)
end)

-- Client: trigger
hx.Callback.Trigger('myresource:getBalance', function(balance)
    print('Bank balance:', balance)
end, 'bank')

Side

Function

Description

Register(name, handler)

handler(source, ...) returns the value sent back to the client. Errors are caught and logged; the client receives nil.

Trigger(name, cb, ...)

Sends a request; cb(result) fires when the server responds.


hx.Log **— leveled logger **

hx.Log.Debug('myresource', 'value = %s', someValue)
hx.Log.Info('myresource', 'Started')
hx.Log.Warn('myresource', 'Low on %d items', count)
hx.Log.Error('myresource', 'Failed: %s', err)

hx.Log.SetLevel('debug')   -- runtime override
  • Levels: debug (1) → info (2) → warn (3) → error (4). Messages below Config.LogLevel are suppressed.

  • Output format: [hx] [LEVEL] [resource] message, color-coded by level.

  • Messages are formatted with string.format (safely — bad args won't error).


hx.Utils **— helpers **

Function

Signature

Description

Trim(s)

string

Strip leading/trailing whitespace.

Split(s, sep)

table

Split string by separator.

Round(num, decimals?)

number

Round to N decimals (default 0).

DeepCopy(orig)

table

Recursive table copy.

Contains(tbl, val)

boolean

Value membership test.

TableLength(tbl)

integer

Count keys (non-sequential safe).

Format(str, ...)

string

string.format that returns the raw string instead of erroring on bad args.

RandomString(length?)

string

Alphanumeric, default length 8.

Merge(t1, t2)

table

Shallow merge; t2 overrides t1.


hx.Locale **— localization **

hx.Locale.T('welcome_message', playerName)   -- formatted, with args
hx.Locale.SetLocale('en')
hx.Locale.GetLocale()                          --> 'tr'
  • Loads locales/.json on demand. Ships with tr (default) and en.

  • Missing key → falls back to English → falls back to the key itself.

  • Supports string.format substitution when args are passed.


hx.Version **— update checker **

hx.Version.Check('my-shop', '1.2.0', 'https://github.com/hx-studios/hx-shop')

Queries the GitHub latest release API and logs whether your resource is current or outdated. Controlled by Config.VersionCheck. hx-lib runs this against itself on startup.


hx.Blip **— client **

local id = hx.Blip.Create({
    coords     = vec3(441.0, -982.0, 30.6),
    sprite     = 60,
    color      = 29,
    scale      = 0.9,        -- optional, default 0.8
    label      = 'Police',
    shortRange = true,       -- optional, default true
})

hx.Blip.Remove(id)
hx.Blip.RemoveAll()
hx.Blip.GetAll()   --> { blipHandle, ... }

All blips are tracked and removed automatically when the resource stops.


hx.Ped **— client **

local ped = hx.Ped.Create({
    model       = 's_m_y_cop_01',
    coords      = vec4(441.0, -982.0, 30.6, 90.0),
    freeze      = true,   -- default true
    invincible  = true,   -- default true
    blockEvents = true,   -- default true
    scenario    = 'WORLD_HUMAN_GUARD_STAND',  -- OR:
    anim        = { dict = 'amb@world_human_...', name = 'idle_a' },
})

hx.Ped.Remove(ped)
hx.Ped.RemoveAll()
hx.Ped.GetAll()

Validates and streams the model with a timeout, applies sensible defaults (frozen, invincible, no ambient AI), then releases the model. Tracked and auto-removed on resource stop.


hx.Marker **— client **

Draws a marker and fires interaction callbacks based on player distance. The render loop sleeps when no marker is nearby.

local id = hx.Marker.Create({
    coords          = vec3(441.0, -982.0, 30.6),
    type            = 1,                              -- marker type, default 1
    scale           = vec3(1.0, 1.0, 1.0),
    color           = { r = 255, g = 0, b = 0, a = 100 },
    rotate          = false,
    bobUpAndDown    = false,
    distance        = 10.0,                           -- draw distance
    interactDistance = 1.5,                           -- enter/inside trigger range
    onEnter  = function(id, marker) end,
    onInside = function(id, marker) end,              -- every frame while inside
    onExit   = function(id, marker) end,
})

hx.Marker.Remove(id)
hx.Marker.RemoveAll()

hx.UI — bundled NUI

A complete NUI component kit rendered by hx-lib's own UI page (web/index.html). Blocking components return their result via Citizen.Await, so you can call them synchronously inside a thread. Two themes are available: v1 (sharp) and v2 (rounded, default — set in Config.UI.Theme).

Important: hx.UI is not exposed through @hx-lib/imports/client.lua. The NUI page is owned by the hx-lib resource, so hx.UI.* runs inside hx-lib's own client context (see the bundled /hx:ui test commands). External resources that need this UI should drive it from hx-lib rather than calling hx.UI directly. See Notes & Caveats.

Function

Blocking

Returns

Alert(data)

yes

boolean confirmed

Context(data)

yes

number|nil 1-based index

Menu(data)

yes

number|nil 1-based index

Radial(data)

yes

number|nil 1-based index

Dialog(data)

yes

table|nil field values

SkillCheck(data)

yes

boolean success

Notify(data)

no

ShowInteract(data) / HideInteract()

no

ShowActionBar(data) / HideActionBar()

no

CloseContext() / CloseMenu() / CloseRadial()

no

SetTheme('v1'|'v2')

no

-- Confirm dialog
if hx.UI.Alert({ title = 'Delete?', description = 'This cannot be undone.' }) then
    -- confirmed
end

-- Input form
local values = hx.UI.Dialog({
    title  = 'Register Vehicle',
    fields = {
        { type = 'text',   name = 'plate', label = 'Plate' },
        { type = 'number', name = 'price', label = 'Price', min = 0, max = 100000 },
    },
})
if values then print(values.plate, values.price) end

-- Notification (fire-and-forget)
hx.UI.Notify({ title = 'Saved', message = 'Vehicle stored.', type = 'success' })

-- Skill check
local ok = hx.UI.SkillCheck({ difficulty = 'medium', current = 1, total = 3 })

Built-in test commands (registered by modules/client/ui_test.lua): run /hx:ui in the F8 console for the full list — /hx:alert, /hx:context, /hx:dialog, /hx:menu, /hx:radial, /hx:skillcheck, /hx:notify, /hx:interact, /hx:actionbar, /hx:theme.


Configuration

Edit shared/config.lua:

hx.Config = {
    Debug         = false,     -- debug mode
    LogLevel      = 'info',    -- 'debug' | 'info' | 'warn' | 'error'
    DefaultLocale = 'tr',      -- default language
    VersionCheck  = true,      -- enable GitHub version check
    NotifyDuration = 5000,     -- default notification duration (ms)
    CallbackTimeout = 10000,   -- callback timeout (ms)

    Brand = {
        Name   = 'hx Studios',
        Color  = '^5',         -- console color code (cyan)
        Prefix = '[hx]',
    },

    UI = {
        Theme = 'v2',          -- 'v1' (sharp) | 'v2' (rounded)
    },
}

Localization

Locale files live in locales/ as flat JSON key→string maps:

{
  "lib_loaded": "Library loaded | Framework: %s | v%s",
  "version_outdated": "Outdated! Current: %s, Latest: %s"
}

%s / %d placeholders are filled by the args passed to hx.Locale.T(key, ...). Add a new language by dropping locales/.json and setting Config.DefaultLocale (or calling hx.Locale.SetLocale).


Exports

-- Server: get the full hx table from another resource
local hx = exports['hx-lib']:Gethx()

This export is server-side only. On the client, access hx via the global created by @hx-lib/imports/client.lua.


Project Structure

hx-lib/
├── fxmanifest.lua
├── init.lua                  # global hx table + namespaces + framework state
├── imports/
│   ├── shared.lua            # @hx-lib/imports/shared.lua
│   ├── client.lua            # @hx-lib/imports/client.lua
│   └── server.lua            # @hx-lib/imports/server.lua
├── shared/
│   ├── config.lua
│   ├── utils.lua
│   └── locale.lua
├── bridge/
│   ├── loader.lua            # framework detection
│   ├── client/{qbox,qbcore,esx}.lua
│   └── server/{qbox,qbcore,esx}.lua
├── modules/
│   ├── client/{logger,callback,blip,ped,marker,ui,ui_test}.lua
│   └── server/{logger,callback,version}.lua
├── client/main.lua           # ready flag + cleanup on stop
├── server/main.lua           # ready flag + self version check + Gethx export
├── locales/{tr,en}.json
└── web/                       # NUI (index.html, css, js)


Notes & Caveats

  • Load order matters. hx-lib must start before dependent resources, and your framework (and ox_inventory for QBox) must start before hx-lib.

  • hx.UI import gap. imports/client.lua loads logger, callback, blip, ped, and marker — but not ui. The UI module is only loaded in hx-lib's own client state (via fxmanifest modules/client/*.lua), because the NUI page belongs to hx-lib. External client scripts including the import get every module except hx.UI.

  • Test commands ship enabled. modules/client/ui_test.lua registers /hx:* commands and is loaded unconditionally (not gated behind Config.Debug). Remove or gate it for production.

  • Inventory backends differ. QBox uses ox_inventory (metadata supported); ESX uses its built-in inventory (no metadata param). Keep item calls portable by not relying on metadata unless you target QBox.


License

© House X Studios. All rights reserved unless a license file states otherwise.

Preview

Added As Secondary Media