Getting started
This page takes you from an empty folder to a running mode. For a deeper, rules-and-all walkthrough see Build your first mode.
Prerequisites
- A FiveM server already running the engine resource and its dependencies
(
ui,spawnmanager,lobby,baseevents). routingBucketsleft at its default (true) inengine/shared/config.lua. This is required — see the golden rule.
1. Create the resource
A mode is just a resource that depends on both sdk (the contract/registry) and
engine (the runtime). The minimum is a manifest and one server script.
[modes]/mode_mygame/
├── fxmanifest.lua
└── server/
└── main.luafxmanifest.lua:
fx_version 'cerulean'
game 'gta5'
author 'You'
description 'mode: My Game'
version '0.1.0'
dependencies { 'sdk', 'engine' }
-- The SDK's shared helpers + descriptor builder + LuaCATS types, included into your
-- VM so the descriptor below validates at load and your editor autocompletes it.
shared_scripts {
'@sdk/shared/kit.lua', -- validation primitives the contract uses (load first)
'@sdk/shared/criteria.lua', -- the criterion contract `defineMode` delegates to (required)
'@sdk/shared/descriptor.lua', -- defineMode + the RfxMode types
}
server_script 'server/main.lua'The dependencies { 'sdk', 'engine' } line guarantees both the SDK (the
contract/registry) and the engine (the runtime) are present.
2. Write the descriptor
The descriptor is a plain Lua table wrapped in defineMode — which validates it
at load (a malformed descriptor aborts here with a precise message, not silently
at runtime) and fills defaults. A mode declares its structure (teamCount ×
perTeam — teams are anonymous, no names/colors/models) and a declarative
rules block that runs on the engine's rules runtime — no functions required.
-- [modes]/mode_mygame/server/main.lua
local MODE = defineMode{
id = 'mygame', -- must be unique across all modes
apiVersion = 1, -- descriptor contract version you target
label = 'My Game',
teamCount = 2, -- 2 anonymous teams...
perTeam = 2, -- ...of 2 players (2v2)
minToStart = 1, -- 1 per team starts the round
maxRound = 5, -- best of: first to 5 round wins
-- Behaviour: a declarative `rules` block, auto-run on the engine's rules runtime.
rules = {
structure = 'rounds', -- elimination rounds
phases = { live = 150, post = 5 },
roundEnd = { 'elimination', 'timeLimit' }, -- team wipe OR the live timer ends a round
win = { roundWins = 5 },
},
-- The kit is symmetric (same for every combatant).
armor = 100,
loadout = { { 'WEAPON_CARBINERIFLE', 150 }, { 'WEAPON_PISTOL', 100 } },
}Maps are not part of the mode: battlegrounds from the shared pool declare a
modes.mygame block (spawn arrays indexed by team number) — see the
battleground SDK. See the
Mode descriptor reference for every field, its type,
default, and scope.
3. Register it
Wait until the SDK resource has started, then register the descriptor with the SDK — which the engine mirrors and runs. The SDK tags the descriptor with your resource name automatically, and drops the mode if your resource stops.
CreateThread(function()
while GetResourceState('sdk') ~= 'started' do Wait(100) end
exports.sdk:registerMode(MODE)
end)4. Run it
Add the resource to your server.cfg (after the SDK and the engine) and start the
server:
ensure sdk
ensure engine
ensure mode_mygameOn a successful registration the SDK prints:
[sdk] mode registered: mygame (My Game) from mode_mygame5. Test it in-game
- Connect. You spawn in the lobby (bucket 0).
- Press M to open the main menu (NUI).
- Pick My Game in the mode rail — it opens the mode's cover (hero, live badges, your record). Hit Play casual to reach the casual arena browser, then create an arena (pick map / loadout / best-of) or join an open one. (Ranked slots, if any, are joined straight from the cover.)
- Bring in enough clients to fill it (or, as an admin with
rfx_labon, run/rfx lab startto force a solo round). The arena auto-launches the moment it's full — there's no ready-up — and the round opens live immediately: on a battleground with groundspawns(all the base duel arenas) each player starts standing on their spot; on one with onlyareas, they parachute in. - Press Esc → Leave (or
/leave) to return to the lobby.
If your mode never appears in the menu, check the server console for the
mode registered line and confirm dependencies { 'sdk', 'engine' } is in your
manifest.
Next steps
- Build your first mode — the same flow with the rules explained.
- Choosing how to drive a mode — a
rulesblock, a customtick, or a registered nativedriver.