Scripting in JavaScript

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.

Using natives

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();

Using Node.js APIs

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.

Using exports

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()
});

TypeScript support

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.

Exports typings

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 {}

Gotchas

Thread affinity

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.

Functions in JavaScript

  • on (alias: addEventListener, AddEventHandler)
  • onNet (alias: addNetEventListener)
  • RegisterNetEvent (alias: RegisterServerEvent)
  • emit
  • emitNet (alias: TriggerClientEvent, TriggerServerEvent)
  • addRawEventListener (alias: addRawEventHandler)
  • removeEventListener
  • setTick
  • clearTick

See Scripting reference for example usage of these functions.