Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lua FiveM QBCore

LuaGround

Test your QBCore scripts without spinning up a FiveM server.

Full QBCore framework mocks • 2,000+ FiveM natives • Zero dependencies • Pure Lua


The Problem

Every QBCore developer knows the pain:

  • Write some code
  • Restart the server
  • Wait for it to load
  • Join with your test character
  • Realize you made a typo
  • Repeat

LuaGround eliminates this cycle entirely.

Run your QBCore resource logic locally. Test player functions, jobs, inventory, money, gangs, and events - all without touching a FiveM server.


Features

  • Full QBCore Mock Framework - Player objects, Functions, Jobs, Gangs, Items, Metadata
  • 2,000+ FiveM Native Mocks - Auto-generated from official FiveM documentation (January 2026)
  • Complete Event System - TriggerEvent, TriggerServerEvent, TriggerClientEvent with tracking
  • Built-in Test Runner - BDD-style describe/it syntax with assertions
  • MySQL Mocks - oxmysql and mysql-async compatible
  • Zero Dependencies - Pure Lua, runs anywhere Lua runs
  • Callback System - Mock QBCore callbacks with custom return values

Quick Start

1. Clone the Repository

git clone https://github.com/YOUR_USERNAME/luaground.git
cd luaground

2. Run Lua

Make sure you have Lua or LuaJIT installed:

# Windows (scoop)
scoop install lua

# Ubuntu/Debian
sudo apt install lua5.4

# macOS
brew install lua

3. Load the Framework

dofile('init.lua')

That's it. You now have access to the full QBCore mock environment.


Usage Guide

Creating a Mock Player

dofile('init.lua')

-- Create a player with default values
local player = QBCore.Player.CreateMockPlayer(1)

-- Or customize the player data
local player = QBCore.Player.CreateMockPlayer(1, {
    citizenid = 'ABC12345',
    charinfo = {
        firstname = 'John',
        lastname = 'Doe',
        birthdate = '1990-01-15',
        gender = 0,
        phone = '555-0100'
    },
    money = {
        cash = 1000,
        bank = 50000,
        crypto = 5
    }
})

Working with Jobs

-- Set a player's job
player.Functions.SetJob('police', 3)

-- Check job info
print(player.PlayerData.job.name)       -- 'police'
print(player.PlayerData.job.label)      -- 'Police'
print(player.PlayerData.job.grade.name) -- 'Sergeant'

-- Check on-duty status
player.Functions.SetJobDuty(true)
print(player.PlayerData.job.onduty)     -- true

Working with Gangs

-- Set a player's gang
player.Functions.SetGang('ballas', 2)

-- Check gang info
print(player.PlayerData.gang.name)       -- 'ballas'
print(player.PlayerData.gang.label)      -- 'Ballas'
print(player.PlayerData.gang.grade.name) -- 'OG'

Money Operations

-- Add money
player.Functions.AddMoney('cash', 500, 'sold-item')
player.Functions.AddMoney('bank', 1000, 'paycheck')

-- Remove money
player.Functions.RemoveMoney('cash', 100, 'purchase')

-- Check balance
print(player.Functions.GetMoney('cash'))  -- 1400
print(player.Functions.GetMoney('bank'))  -- 51000

Inventory Management

-- Add items
player.Functions.AddItem('water', 5)
player.Functions.AddItem('lockpick', 1, nil, { quality = 100 })

-- Remove items
player.Functions.RemoveItem('water', 2)

-- Check inventory
local item = player.Functions.GetItemByName('water')
print(item.amount)  -- 3

-- Check if player has item
local hasItem = player.Functions.HasItem('lockpick')
print(hasItem)  -- true

Metadata

-- Set metadata
player.Functions.SetMetaData('hunger', 80)
player.Functions.SetMetaData('thirst', 65)
player.Functions.SetMetaData('stress', 10)

-- Get metadata
print(player.Functions.GetMetaData('hunger'))  -- 80

Event Testing

-- Trigger events
TriggerServerEvent('myresource:sellItem', 'water', 5)
TriggerClientEvent('myresource:notify', 1, 'Item sold!')

-- Check if events were fired
if TestHelper.wasEventTriggered('myresource:sellItem') then
    local args = TestHelper.getEventArgs('myresource:sellItem')
    print(args[1])  -- 'water'
    print(args[2])  -- 5
end

Mocking Return Values

-- Mock native returns
MockReturnValue['GetEntityCoords'] = vector3(100.0, 200.0, 30.0)
MockReturnValue['GetPlayerPed'] = 12345
MockReturnValue['IsEntityDead'] = false

-- Mock callback returns
MockReturnValue['Callback:qb-inventory:server:GetItemList'] = {
    { name = 'water', amount = 5 },
    { name = 'bread', amount = 3 }
}

-- Mock MySQL returns
MockReturnValue['MySQL:SELECT * FROM players WHERE citizenid = ?'] = {
    { citizenid = 'ABC123', name = 'John Doe' }
}

Writing Tests

LuaGround includes a full test runner with BDD-style syntax.

Basic Test Structure

dofile('init.lua')
dofile('tests/test_helper.lua')

TestHelper.run(function()
    describe('My Resource Tests', function()

        it('should pay player for completing delivery', function()
            TestHelper.reset()

            local player = TestHelper.createMockPlayer(1)
            player.Functions.SetJob('trucker', 0)

            -- Your resource logic
            local payment = 150
            player.Functions.AddMoney('bank', payment, 'delivery-complete')

            -- Assertions
            assert_equal(5150, player.Functions.GetMoney('bank'))
        end)

        it('should remove item when used', function()
            TestHelper.reset()

            local player = TestHelper.createMockPlayer(1)
            player.Functions.AddItem('bandage', 3)

            -- Simulate using item
            player.Functions.RemoveItem('bandage', 1)

            local item = player.Functions.GetItemByName('bandage')
            assert_equal(2, item.amount)
        end)

        it('should fire correct events', function()
            TestHelper.reset()

            TriggerServerEvent('myresource:requestData', 'player_stats')

            assert_true(TestHelper.wasEventTriggered('myresource:requestData'))
            local args = TestHelper.getEventArgs('myresource:requestData')
            assert_equal('player_stats', args[1])
        end)

    end)
end)

Available Assertions

Assertion Description
assert_equal(expected, actual, msg) Check equality
assert_not_equal(expected, actual, msg) Check inequality
assert_true(value, msg) Check truthy
assert_false(value, msg) Check falsy
assert_nil(value, msg) Check nil
assert_not_nil(value, msg) Check not nil
assert_type(type, value, msg) Check type
assert_contains(haystack, needle, msg) Check contains
assert_throws(fn, msg) Check throws error

Running Tests

lua tests/example_test.lua

Or with LuaJIT for better performance:

luajit tests/example_test.lua

Project Structure

luaground/
├── init.lua                 # Main loader - start here
├── builder/
│   └── fetch_fivem.js       # Native generator (Node.js)
├── client/
│   ├── natives.lua          # GTA V natives (~18,000 lines)
│   └── cfx.lua              # CFX client natives
├── server/
│   └── cfx.lua              # CFX server natives
├── fivem/
│   ├── globals.lua          # Vectors, JSON, MySQL, Convars
│   └── events.lua           # Event system mock
├── qbcore/
│   ├── init.lua             # QBCore initialization
│   ├── player.lua           # Player object mock
│   ├── functions_client.lua # Client-side QBCore.Functions
│   └── functions_server.lua # Server-side QBCore.Functions
└── tests/
    ├── test_helper.lua      # Test utilities & assertions
    └── example_test.lua     # Example test suite

Updating Natives

The native mocks are auto-generated from FiveM's official documentation. To pull the latest:

cd builder
node fetch_fivem.js

This fetches from:

  • https://runtime.fivem.net/doc/natives.json - GTA V natives
  • https://runtime.fivem.net/doc/natives_cfx.json - CFX natives

Default Jobs & Gangs

The framework ships with common QBCore jobs and gangs:

Jobs: unemployed, police, ambulance

Gangs: none, ballas, vagos

Add more in qbcore/init.lua:

QBCore.Shared.Jobs['mechanic'] = {
    label = 'Mechanic',
    defaultDuty = true,
    offDutyPay = false,
    grades = {
        ['0'] = { name = 'Trainee', payment = 50 },
        ['1'] = { name = 'Mechanic', payment = 75 },
        ['2'] = { name = 'Senior Mechanic', payment = 100 },
        ['3'] = { name = 'Manager', payment = 150 }
    }
}

Use Cases

  • Unit test your resources before deploying to production
  • CI/CD pipelines - run tests on every commit
  • Rapid prototyping - test logic without server restarts
  • Debug complex systems - isolate and test specific functions
  • Onboard new developers - let them experiment safely

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/sick-feature)
  3. Commit your changes (git commit -m 'Add sick feature')
  4. Push to the branch (git push origin feature/sick-feature)
  5. Open a Pull Request

License

MIT License - see LICENSE for details.


Created by viscosity on behalf of the Black Mesa RP Community

Built with respect for the QBCore Framework and FiveM communities.

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages