A practical guide to how to install a fuel script on your qbcore fivem server, with implementation decisions, validation steps, and security considerations for a production-minded project.
Overview
Stellar AI can help generate and revise the project files for this workflow. Describe your framework, existing dependencies, and one testable feature, then bring back errors for a focused revision. You remain responsible for running the tests and managing deployment in your own development environment.
Architecture: where a fuel script lives in QBCore
A fuel script typically has three logical components:
- Server authority: manages persistent fuel state, database writes, transaction validation, anti-cheat checks, and RPCs (server events).
- Client presentation: UI, HUD fuel gauges, local interpolation/animation, and local effects (particles, sounds). The client must not be trusted with authoritative state.
- Shared utilities: constants, exported functions, configuration for fuel rates, and helper functions shared between client and server.
Deploy the resource as a separate folder under your server resources (e.g., resources/[vehicle]/qb-fuel). Use fxmanifest.lua to declare client and server scripts and any dependencies like ox_lib.
Installation steps (files, manifests, and resource layout)
Follow these steps to get a fuel resource running:
- Create a resource folder: resources/[vehicle]/qb-fuel/
- Add fxmanifest.lua and split scripts into client.lua, server.lua, and shared.lua or modules/
- Register exports or events for other scripts to query and modify fuel (prefer server exports or server events)
- Ensure your resource lists qb-core as a dependency in fxmanifest:
dependency 'qb-core' - Start the resource in server.cfg:
ensure qb-fuel
Example minimal fxmanifest entries (illustrative):
fx_version 'cerulean'
game 'gta5'
author 'you'
description 'QBCore fuel system'
version '1.0.0'
shared_script 'shared.lua'
server_scripts { 'server.lua' }
client_scripts { 'client.lua' }
dependency 'qb-core'
QBCore implementation: server-side first
Server: authoritative event handling
Never trust the client. Use server-side events and validate every input coming from the client: the player source, vehicle network id, fuel amount, and that the vehicle actually exists and belongs to the server or the player. Use QBCore.Functions.GetPlayer(source) to access player data, then verify funds, inventory items, and position.
// server.lua (simplified)
local QBCore = exports['qb-core']:GetCoreObject()
RegisterNetEvent('qb-fuel:server:Refuel', function(netId, liters)
local src = source
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
-- validate inputs strictly
if type(netId) ~= 'number' or type(liters) ~= 'number' then return end
if liters <= 0 or liters > 100 then return end
-- find the vehicle server-side from network id
local vehicle = NetworkGetEntityFromNetworkId(netId)
if not vehicle or not DoesEntityExist(vehicle) then return end
-- additional validation: player proximity to vehicle
local ped = GetPlayerPed(src)
local px,py,pz = table.unpack(GetEntityCoords(ped))
local vx,vy,vz = table.unpack(GetEntityCoords(vehicle))
local dist = #(vector3(px,py,pz) - vector3(vx,vy,vz))
if dist > 5.0 then return end
-- business logic: deduct money, update fuel in DB/state
local price = math.floor(liters * Config.PricePerLiter)
if player.Functions.RemoveMoney('cash', price) then
-- update persistent fuel state here (save to DB or vehicle meta)
-- emit events/exports for other resources to react
TriggerClientEvent('qb-fuel:client:UpdateFuel', -1, netId, liters)
end
end)
Use server-side timed saves for fuel state instead of saving on every event to reduce DB load; persist on disconnect and at intervals.
Client: UI and local interpolation only
The client should be limited to local visual updates and player interactions (pressing keys, showing UI, handling pumps). When a player requests a refuel action, send an event to the server. Do not allow the client to write persistent fuel directly.
// client.lua (simplified)
RegisterNetEvent('qb-fuel:client:OpenFuelUI', function(netId)
-- show UI and let user pick liters; send request to server
local liters = 20 -- user choice
TriggerServerEvent('qb-fuel:server:Refuel', netId, liters)
end)
RegisterNetEvent('qb-fuel:client:UpdateFuel', function(netId, litersAdded)
-- update local HUD and play animation
end)
Shared: configuration and exports
Place rate constants, petrol pump positions, and helper functions in shared.lua. Export server functions for other trusted server resources rather than exposing raw events to the client.
Security and server validation checklist
Every fuel-related request must check:
- Source authenticity: ensure source exists via QBCore.Functions.GetPlayer(source).
- Type validation: numeric ranges for amounts, valid network IDs.
- Entity validation: DoesEntityExist & proximity check.
- Permission checks: is the player allowed to refuel that vehicle (owner/keys).
- Anti-spam/throttling: rate-limit refuel events per player with server-side timers.
- Persistence validation: confirm DB writes succeed and handle failures gracefully.
ESX and ox_lib notes (migration and interoperability)
If you run ESX instead of QBCore, the server-side patterns are the same but adapt API calls:
- Replace QBCore.Functions.GetPlayer with ESX.GetPlayerFromId(source).
- Use ESX server callbacks and events to coordinate payments and inventory checks.
- For UI and interaction helpers, ox_lib provides native-looking menus and prompts; hook client-side interactions to trigger server events rather than allowing ox_lib to perform state changes client-side.
When making your resource compatible with both frameworks, isolate framework-specific code into adapter modules, e.g., qb_adapter.lua and esx_adapter.lua, and select the proper adapter at startup.
Testing and debugging strategies
Testing should include unit-level server validation, manual QA in a staging server, and automated scenario tests if possible. Focus on:
- Server event fuzzing: send malformed payloads and verify they are rejected.
- Concurrency tests: simulate multiple players refueling the same vehicle to ensure atomic updates.
- Persistence tests: restart the server to confirm fuel state persists and recovers correctly.
- Client synchronization: ensure all nearby players receive fuel updates in a timely manner.
For operational monitoring, hook logs and key metrics (event counts, DB error rates) into a central dashboard. If you use an operations console, register your resource presence and health with tools such as the Stellar AI management app at https://trystellarai.com/app.
For deeper reading on deployment patterns and community posts, see the project blog: https://trystellarai.com/blog.
Roblox/Luau considerations (short)
Although the core of this guide targets FiveM/QBCore, if you are implementing a fuel-like resource in Roblox:
- Always treat the server as authoritative. Use RemoteEvents or RemoteFunctions only to request actions; the server must validate and then update the server state.
- Respect RemoteEvent best practices: validate parameters, check player permissions, and throttle requests to prevent abuse.
- For persistence use DataStore with robust failure handling: wrap DataStore calls in pcall, implement exponential backoff retry, and have clear behavior for save failures (e.g., queue writes and notify administrators).
Deployment and maintenance
Deploy the fuel resource to a staging server before production. When pushing to production:
- Run a database migration that adds fuel storage fields (vehicle meta table or separate table for fuel logs).
- Deploy during low-traffic windows and enable verbose server logging for the first hours.
- Monitor DB error rates and event rejection rates; ensure anti-cheat thresholds are not overly aggressive and block legitimate activity.
Stellar AI can help generate and revise the project files for this workflow. Describe your framework, existing dependencies, and one testable feature, then bring back errors for a focused revision. You remain responsible for running the tests and managing deployment in your own development environment.
Practical checklist
| Task | Why | Completed |
|---|---|---|
| Place resource in resources folder with fxmanifest | Ensures loader recognizes the resource and dependencies load | [ ] |
| Implement strict server-side validation | Prevents client exploitation and data corruption | [ ] |
| Persist fuel state with periodic and disconnect saves | Reduces DB load while ensuring durability | [ ] |
| Test concurrency and persistence in staging | Find race conditions before production | [ ] |
| Integrate logging and monitoring | Quickly identify runtime errors and abuse | [ ] |
| Set rollback plan and migration backup | Safeguard against bad schema changes | [ ] |
Troubleshooting notes
Common issues and quick checks:
- Fuel not persisting: verify DB write code paths are called and that DB transactions succeed. Check server logs for SQL errors.
- Desync between clients: ensure the server broadcasts state changes and clients update HUD on receipt; add sequence numbers to avoid stale updates.
- Players refueling remotely: re-check proximity validation and ensure you use world coords on the server, not client-reported coordinates.