DenizenMC

Custom Commands

Build real commands with tab completion, arguments, cooldowns and limits, in a few lines of YAML.

Every top-level key in any file inside plugins/Lightning/commands/ becomes a command. They're registered as real Brigadier commands, the same system vanilla uses, so players get proper tab completion, and wrong input is underlined in red before they even press enter.

Your first command

commands/server.yml
discord:
  description: Get the Discord link
  aliases: [dc]
  actions:
    - "<spark:prefix> Join us at discord.gg/example"

That's a complete command. Restart your server once and /discord (or /dc) is ready. Everything below is optional.

Options

OptionWhat it does
enabledfalse turns the command off without deleting it
descriptionShown in /help
aliasesOther names for the command
permissionWho can use it. Players without it won't see it in tab completion either
senderplayer, console or any (the default)
cooldownTime between uses, like 30s, 5m or 12h
limitHow many times it can be used, see Cooldowns and limits
usageReplaces the usage line Lightning builds for you
argumentsWhat the command takes
messagesThis command's own cooldown, limit, usage, players or console message
subcommandsCommands inside this one
actionsWhat it does, top to bottom

Arguments

A list, in the order players type them:

arguments:
  - name: target
    type: player
  - name: amount
    type: number
    min: 1
    max: 64
    default: 1
FieldWhat it does
nameWhat it's called. Use it as {name} in actions
typeOne of the types below, word if you leave it out
defaultUsed when the player leaves it out, which makes it optional
optionaltrue makes it optional without a default. It's empty when left out
min, maxFor number and decimal. The player's game refuses anything outside
optionsFor choice, the allowed values
TypeTakes
playerAn online player, with names suggested
numberA whole number
decimalAny number
booleantrue or false
wordOne word
textEverything left on the line, so it has to come last
worldA loaded world, with names suggested
choiceOne of options, which are suggested

There's a short way to write arguments too, with the name and the type on one line:

arguments:
  - target: player
  - reason: text
  - mode: [easy, normal, hard]

A list as the type makes it a choice. Use the full form when you need min, max or default.

Optional arguments go last

Put optional arguments after the required ones. If something's out of order or misspelled, the console tells you exactly which argument of which command.

Subcommands

kit:
  description: Grab a kit
  sender: player
  subcommands:
    starter:
      limit: 1
      actions: [...]
    daily:
      cooldown: 24h
      actions: [...]

/kit on its own shows Usage: /kit <starter|daily>. Subcommands follow their parent's sender unless they set their own, and can use every other option, including their own subcommands.

Cooldowns and limits

cooldown: 12h
# once, ever
limit: 1
# three times a day
limit:
  amount: 3
  reset: day

cooldown is the wait between two uses. limit caps how many uses fit in a window: reset can be never, hour, day, week, month, or a time like 6h. Both are tracked per player and per subcommand, and they survive restarts.

Skipping the wait

lightning.bypass skips cooldowns and limits. Nobody has it by default, ops included, so give it out on purpose.

Actions

actions:
  - "<spark:prefix> Welcome back, {player}!<sound:entity.player.levelup>"
  - console: "give {player} diamond"
  - wait: 2s
  - "<actionbar:'<gold>+1 diamond'>"
ActionWhat it does
"text"A message to whoever ran the command. Sparks, bolts, faces, <center> and placeholders all work
message: "text"The same, written out
console: "command"Runs a command as the console
player: "command"Runs a command as the player
broadcast: "text"A message to everyone. Each reader sees their own placeholders and sparks
broadcast with permission:Only players with that permission
wait: 2sPauses, then carries on
if: with then: and else:Runs one or the other
chance: 10% with then: and else:The same, by chance
pick: with a listRuns one of the options at random. Each option can be a line or a whole list of actions
stop: trueEnds the command right there

{player} is whoever ran the command, {world} and {uuid} are theirs too, and every argument is {its name}. then and else take one line or a list, and can hold more ifs.

Checks

- if: "%vault_eco_balance% >= 1000 and has vip.perks"
  then: "<gold>Welcome back, big spender."
  else: "<gray>Welcome back."
FormMeaning
a >= b, <=, >, <Number comparisons
a == b, a != bNumbers compare as numbers, anything else as text, ignoring case
has some.permissionThe player has it
not ...The opposite
and, orCombine checks

Messages per command

Any command can swap the general messages from config.yml for its own:

kit:
  subcommands:
    starter:
      limit: 1
      messages:
        limit: "<spark:prefix> You already grabbed your starter kit."

Available: cooldown (with <time>), limit, usage (with <usage>), players and console.

Safe by default

Whatever a player types into an argument is treated as plain data, never as instructions:

  • No tags. A /report reason of <red>spam shows the tag as text. It never turns red.
  • No placeholders. A player typing %player_ip% sees exactly that, nothing gets filled in.
  • No selectors. @ is removed before arguments go into a console or player command, so /give {target} can never become @a.
  • No double filling. A player typing {target} gets exactly that, it's never filled in a second time.
  • Real players only. player arguments only accept players who are online.

Reloading

Changing what a command says or does applies with /lightning reload.

New commands need a restart

A brand new command, or changed arguments, need a full restart. Players only receive the command list when they join. If the name is already taken by another plugin, the console says so, and the command still works as /lightning:name.

A few to copy

report:
  description: Report a player to staff
  sender: player
  cooldown: 1m
  arguments:
    - name: target
      type: player
    - name: reason
      type: text
  actions:
    - "<spark:prefix> Thanks, staff will look into it."
    - broadcast: "<spark:alert>Report</spark> {player} reported {target}: {reason}"
      permission: server.staff

Coming soon

More argument types are on the way: items, amounts like 10k, and durations like 1h.

Did this page help?

Last updated on