EndCore Framework

Registering commands

Add chat commands with encore.addCommand, with typed parameters, usage messages, aliases, ACE-restricted admin commands and chat suggestions.

encore.addCommand registers a chat command and does the tedious parts for you. It parses and checks arguments before your handler runs, shows the player a usage message when they get it wrong, grants ACE permissions for restricted commands, and only suggests a command in chat to players who are allowed to use it.

For the commands EndCore itself ships, see Commands.

Signature

lua
encore.addCommand(names, properties, handler)
ArgumentTypeMeaning
namesstring or string[]The command name, or a list of names. Every name in the list registers the same command, so extra names act as aliases
propertiestableHelp text, restriction and parameters (below)
handlerfunction(source, args, raw)Runs after the arguments parse. args is keyed by parameter name. raw is the full command line as typed

Properties

KeyTypeSideMeaning
helpstring?bothShown in the chat suggestion
restrictedstring, string[] or falseserver onlyACE principal or principals allowed to run it, for example 'group.admin'
paramsCommandParam[]?bothParameters, in order

Parameters

Each entry in params is { name, type?, help?, optional? }.

typeParses asNotes
'string' (or omitted)the raw wordAny other type name is also kept as a raw string
'number'tonumber(word)A word that isn't a number is rejected
'playerId'a server idOn the server, me means the caller (not from the console), and the id must belong to a connected player
'longString'the rest of the lineEvery remaining word from this position, joined with single spaces. Put it last

Set optional = true for parameters players may leave out. A missing optional parameter is nil in args.

What players see

Arguments are parsed before your handler is called. If they don't parse, the handler doesn't run and the player gets an error notification titled /<name>:

ProblemMessage
A required parameter is missingUsage: /setjob <target> <job> [grade]
A value doesn't parse"abc" is not a valid grade. Usage: /setjob <target> <job> [grade]
A playerId isn't online (server)No player online with ID 42

In the usage string, required parameters are shown as <name> and optional ones as [name]. When the command runs from the server console (source 0), the message prints to the console instead.

If your handler throws, the error is logged as /<name> errored: ... and the command system carries on.

Restricted commands

On the server, setting restricted:

  1. Registers the command as restricted, so FiveM checks the ACE command.<name> before running it.
  2. Runs add_ace <principal> command.<name> allow for each principal you list.
  3. Sends the chat suggestion only to players for whom IsPlayerAceAllowed(player, 'command.<name>') is true. Suggestions are re-sent to each player as they join, and to everyone about a second after new commands are registered.

You can grant a restricted command to more principals in server.cfg:

cfg
add_ace group.moderator command.givexp allow

Client commands

On the client, encore.addCommand registers an unrestricted command and adds a chat suggestion. restricted is ignored, because a player controls their own client.

On the client, playerId parameters take a number only; me is not accepted.

Warning

A client command is a convenience, not a permission check. If it triggers anything on the server, the server must validate the request as if the command didn't exist.

Security

  • Put anything that changes money, items, jobs or other players in a server command with restricted.
  • A playerId parameter proves the id belongs to a connected player. It doesn't prove the caller may act on that player.
  • number parameters accept negatives and decimals. Check the range before using them, for example with encore.math.clamp.
  • longString values are typed by the player. Display them as text only.

Examples

Admin command with an alias

lua
-- server/commands.lua
encore.addCommand({ 'givexp', 'gxp' }, {
    help = 'Give survivor XP',
    restricted = 'group.admin',
    params = {
        { name = 'target', type = 'playerId', help = 'Player ID, or "me"' },
        { name = 'amount', type = 'number' },
        { name = 'reason', type = 'longString', optional = true },
    },
}, function(source, args)
    local amount = math.floor(encore.math.clamp(args.amount, 1, 100000))
    encore.party.shareXP(args.target, amount, args.reason or 'Admin grant')
    encore.notify(source, { description = ('Gave %d XP'):format(amount), type = 'success' })
end)

Several principals

lua
encore.addCommand('clearzone', {
    help = 'Clear zombies around you',
    restricted = { 'group.admin', 'group.moderator' },
    params = { { name = 'radius', type = 'number', optional = true } },
}, function(source, args)
    local radius = encore.math.clamp(args.radius or 50, 5, 300)
    TriggerEvent('my-admin:clearZombies', source, radius)
end)

Client command

lua
-- client/main.lua
encore.addCommand('compass', {
    help = 'Say which way you are facing',
}, function()
    local heading = GetEntityHeading(PlayerPedId())
    encore.notify({ description = 'Facing ' .. encore.getCardinalDirection(heading) })
end)