FiveM supports JavaScript as scripting language.
To use JavaScript, just use .js
in your script filename.
FiveM has the ES2017 standard library built in. FiveM also implements a WHATWG compliant console
API (some
rarely-used methods are not yet implemented).
Note that FiveM (on the client) doesn't include any browser or Node.js-specific API's, such as DOM, localStorage, IndexedDB, WebGL, etc.
Native commands are mapped to global JavaScript functions with names similar to the Lua natives mapping. Definitions for
them are located at path\to\fivem\FiveM.app\citizen\scripting\v8\natives_universal.d.ts
.
For automatic completion of the FiveM API methods and mapped native functions we recommend using the official NPM packages @citizenfx/client and @citizenfx/server, respectively.
Example:
// The native command PLAYER_PED_ID translates to the following:
PlayerPedId();
FiveM includes a customized version of Node.js 16.x on the server. You can simply use require
in server
scripts, and it'll resolve the package either from Node.js built-ins, or the node_modules/
folder in your resource
directory.
To automatically install and update a package.json
with Yarn on launch, make sure the yarn
resource is running
before starting your resource, or preferably add it as a dependency
in your resource manifest.
A proxy object for handling exports. Exports can be called using exports.resourceName.exportName
(or using bracket
syntax: exports['resourceName']['exportName']
), exports can be added using exports('func', () => 42)
.
Example:
exports('myFunc', (arg) => {
console.log(arg);
});
on('onClientGameTypeStart', () => {
exports.spawnmanager.setAutoSpawnCallback(() => {
exports.spawnmanager.spawnPlayer({
x: 686.245,
y: 577.950,
z: 130.461,
model: 'a_m_m_skater_01'
}, () => {
emit('chat:addMessage', {
args: [
'Hi, there!'
]
})
});
});
exports.spawnmanager.setAutoSpawn(true)
exports.spawnmanager.forceRespawn()
});
Definitions for the FiveM JavaScript API are available as TypeScript definition file, which can be
found at path\to\fivem\FiveM.app\citizen\scripting\v8\natives_universal.d.ts
, which will allow your
editor to provide automatic completion of the FiveM API methods and mapped native functions.
For typings use the official NPM packages @citizenfx/client and @citizenfx/server. These packages are also recommended for automatic completion.
The FiveM JavaScript API definitions come with a generic interface for the exports called CitizenExports
. You can extend this interface to add your own typings.
From a TypeScript module file, you could do the following:
declare global {
interface CitizenExports {
resourceName: {
exportName(parameter: unknown): void;
}
}
}
// If you're not importing or exporting anything, you can turn your file into a module by exporting an empty object:
// export {}
In the Node.js runtime, any callbacks that are triggered by Node.js will run on a separate thread hosting the libuv event loop. Since CitizenFX server natives can only be called on the main game thread, trying to invoke any will likely lead to an error saying 'No current resource manager'.
To resolve this, use setImmediate
to schedule a callback to be executed on the main thread if you're intending to call
any server natives.
For example:
const root = GetResourcePath(GetCurrentResourceName());
// wrong
fs.readFile(`${root}/test.txt`, { encoding: 'utf8' }, (err, data) => {
emitNet('chat:addMessage', -1, { // this call will error out due to thread affinity
args: [ data ]
});
});
// right
fs.readFile(`${root}/test.txt`, { encoding: 'utf8' }, (err, data) => {
setImmediate(() => { // the callback will be called next game tick
emitNet('chat:addMessage', -1, {
args: [ data ]
});
});
});
Note that when nesting Node.js callbacks and not using natives in between, you don't need to schedule the code back to the main thread, and it is recommended that you don't do so for the sake of performance.
See Scripting reference for example usage of these functions.