Configuring
Per-command rules
Every one of the 139 commands has its own block in its module's file, and every block takes the same fourteen options. Most commands use three of them.
commands:
defaults:
enabled: true
warmup-seconds: 0
cooldown-seconds: 0
price: 0.0
worlds: [ ]
sound:
key: ui.button.click
volume: 0.5
pitch: 1.2
particle:
name: ''
count: 0
spread: 0.4
height: 1.8
speed: 0.02
home:
warmup-seconds: 3
cooldown-seconds: 30
price: 50.0
worlds: [ '!event' ]
sound:
key: entity.enderman.teleport
volume: 0.7
pitch: 1.2
particle:
name: PORTAL
count: 45
height: 2.0
speed: 0.04A command only writes down what it does differently. Everything it leaves out comes from
defaults, which is why the shipped files are readable: most commands are three lines.
The options#
| Option | What it does |
|---|---|
enabled |
false makes the command answer that it is switched off. The enabled at the top of the file does the same for every command in it. |
warmup-seconds |
Stand still this long before the teleport happens. Only means anything for commands that teleport. |
cooldown-seconds |
How long before the same player may use it again. Starts only once the command actually succeeded. |
price |
What it costs. 0 is free. Charged only on success. |
worlds |
Where it works. Empty is everywhere. |
sound |
Played to whoever ran it. |
particle |
Shown where it happened. |
messages |
Lines this command says instead of the ones in the messages folder. |
permission |
The node the command takes, in place of its own. |
permission-message |
What somebody without that node is told. |
requires |
What has to be true before it runs. |
on-success |
Actions once it has worked. |
on-fail |
Actions when it is refused. |
log |
true writes every use into the staff log. |
Warmups#
warmup-seconds: 3The player stands still for three seconds and then arrives. Moving or taking damage cancels it, and nothing is charged for a cancelled teleport.
Two settings in modules/teleport.yml apply to every warmup in the plugin, whichever command
started it:
teleport:
cancel-on-move: true
cancel-on-damage: true
warmup-countdown: truewarmup-countdown shows the seconds left in the action bar.
chorus.teleport.instant skips every warmup.
Cooldowns#
cooldown-seconds: 30Per player, per command. It starts when the command succeeds, not when it is typed, so a command that refused costs nothing. Cooldowns survive a disconnect: leaving and rejoining does not clear one.
chorus.bypass.cooldown ignores all of them.
Prices#
price: 50.0Taken through whatever economy is in use, and only when the command actually goes through.
A /home that was cancelled halfway through its warmup is free. A /sethome that was refused
because the player was at their limit is free.
With no economy at all, every price is ignored rather than refusing the command.
chorus.bypass.price never pays.
For /sethome there is a second charge in modules/homes.yml:
homes:
price-per-home: 0.0Added to the price for every home the player already has, so the fifth home costs more than the first. Moving a home you already have is never surcharged.
Worlds#
One list does both jobs. A name on its own is the only place the command works; a name
with ! in front is the one place it does not.
worlds: [ ] everywhere, which is the default
worlds: [ world, world_nether ] only in those two
worlds: [ '!event' ] everywhere except the event world
worlds: [ '!world_nether', '!world_the_end' ] the overworld onlyNames are compared without case. A refusal wins over an allowance for the same world, so a list that says both leaves the command off there.
chorus.bypass.worlds ignores the whole thing.
What it is for: no /home in the arena, no /tpa in the event world, no /back out of the
nether — without a second plugin and without taking the command away from everybody.
Mind the quotes. YAML reads a bare ! at the start of a value as a type tag, so '!event'
has to be quoted.
Sounds#
sound:
key: entity.enderman.teleport
volume: 0.7
pitch: 1.2| Key | Range |
|---|---|
key |
A Minecraft sound name. Empty for silence. |
volume |
0 to 10. It doubles as how far away others hear it. |
pitch |
0.5 to 2. Higher is squeakier. |
A name the client does not know simply plays nothing, so a typo can never break anything and a sound that only exists on newer versions is safe to use.
Ones that come up often:
ui.button.click a quiet tick, the default
entity.enderman.teleport a teleport
entity.experience_orb.pickup money, or a message arriving
entity.player.levelup something was created
block.note_block.bass a refusal
block.note_block.pling a setting changed
block.lever.click a toggle
entity.villager.trade mailParticles#
particle:
name: PORTAL
count: 45
spread: 0.4
height: 2.0
speed: 0.02| Key | What it does |
|---|---|
name |
A Bukkit particle name. Empty for none. |
count |
How many. 0 means none. |
spread |
How far they scatter sideways, in blocks. |
height |
How tall the burst is, in blocks. |
speed |
How fast they drift. Keep it small. |
Mojang renamed several of these over the years, so both the old and the new spelling are accepted and the right one is picked for whichever version you run.
Safe on every supported version:
PORTAL REVERSE_PORTAL FLAME SOUL_FIRE_FLAME CLOUD END_ROD DRAGON_BREATH
HEART CRIT ELECTRIC_SPARK GLOW NOTE SNOWFLAKE ASHA teleport shows its particles twice: once where the player left from and once where they arrive.
Messages#
Lines this command says instead of the ones in the messages folder, by the same keys. A blank one silences that line for this command alone.
fly:
messages:
error.no-permission: '<red>Buy VIP to use /fly.'
cooldown.wait: ''Written either as a dotted key or as nested blocks; both reach the same line.
A messages block in defaults applies to every command in that file, and a command may add
to it or rewrite one of its lines.
These are the server's own words, so they are the same in every language. A line that has
to change per language belongs in messages/, not here — see
Messages and translations.
Permissions#
commands:
fly:
permission: vip.fly
permission-message: '<red>Flying is a VIP perk. <gray>/store'permission replaces the node a command takes to be used at all. The nodes for the extras
keep their own names: /fly <player> still needs chorus.utility.fly.others, and the bypass
nodes are untouched.
permission: '' opens the command to everyone.
/commands follows it, so a player is shown the commands they may actually run under the new
node.
permission-message is a shortcut for writing error.no-permission into the command's own
messages block. When both are written, permission-message wins.
Only on a command. In defaults it would hand every command in the file the same node,
which is never what anybody means, so it is ignored there and said so in the console.
Requirements#
What has to be true before the command runs at all. The same five types kits use:
commands:
home:
requires:
- 'playtime: 3600'
- condition: 'placeholder: %player_level% >= 10'
deny: '<red>Come back at level 10.'| Type | Passes when |
|---|---|
permission: <node> |
The player has the node |
placeholder: <comparison> |
The comparison holds. Anything PlaceholderAPI knows, with >=, <=, ==, !=, >, < or contains |
money: <amount> |
Their balance is at least that |
playtime: <seconds> |
They have played at least that long on this server |
kit: <name> |
They have taken that kit at least once. Needs the kits module |
They are checked in order and the first one that fails stops the command. A deny line is
what that player is told; %player%, %command% and anything PlaceholderAPI knows work in
it. Without one they get error.command-requirement from messages/core.yml, which ships as
You cannot use /%command% yet.
Checked after the permission and the world, and before anything is charged, so a player who is turned away here has not paid for it.
The console always passes.
A command's own list replaces the one in defaults rather than adding to it, so a command
can be exempted from a server-wide requirement by writing an empty list.
Actions#
Things to do once a command has worked, or when it has been refused. Written the same way as a kit's claim and fail actions:
commands:
spawn:
on-success:
- 'title: <gold>Welcome back;<gray>to spawn'
- 'sound: entity.player.levelup 1 1.4'
on-fail:
- 'actionbar: <red>Not now'| Action | What it does |
|---|---|
message: <text> |
Sends the player a line |
broadcast: <text> |
Sends everyone a line |
actionbar: <text> |
Shows the line above their hotbar |
title: <title>;<subtitle> |
Shows a title. The subtitle is optional |
sound: <key> [volume] [pitch] |
Plays a sound to them |
console: <command> |
Runs a command as the server |
player: <command> |
Runs a command as the player, with their own permissions |
close |
Closes whatever screen they have open |
on-success runs once the command has really worked — the moment the cooldown starts and
the price is taken. For a teleport that is on arrival, not when it was typed.
on-fail runs when the command is refused: no permission, the wrong world, a requirement, the
cooldown or the price. Not when the arguments are wrong, which is a usage line rather than a
refusal.
%player% and %command% work in every action, and so does anything PlaceholderAPI knows.
There is no %args%. An action cannot see what the player typed after the command, on
purpose: a console line that could be handed a second argument is a console line a player can
steer.
console runs as the server. On Folia it runs on the global thread, a tick later.
Only players run them — the console runs none of them. A line the plugin does not understand is skipped and named in the console when the file is read.
The log#
commands:
gamemode:
log: trueEvery use goes into the staff log with whatever was typed after the command, and reads in
/stafflog as:
▪ Steve used /gamemode » creative (2m 5s ago)Written when the command runs, once the permission, the world and the requirements have passed. A use with the wrong arguments is written too. So are console uses.
Needs staff-log.enabled: true in config.yml, which is how it ships.
Switching things off#
Three levels, from widest to narrowest:
# The whole module, in its file
enabled: false
# One command
commands:
tpaall:
enabled: falseA command that is off answers with the message from messages/core.yml rather than pretending not
to exist, and it disappears from /commands. Its aliases are given back to the server.
A worked example#
Homes that take three seconds, cost money, are not allowed in the nether, and get slower the more you own:
# modules/homes.yml
homes:
default-limit: 3
price-per-home: 250.0
commands:
home:
warmup-seconds: 5
cooldown-seconds: 60
price: 25.0
worlds: [ '!world_nether', '!world_the_end' ]
sethome:
price: 500.0
cooldown-seconds: 30Then let a rank out of it:
lp group vip permission set chorus.bypass.cooldown
lp group vip permission set chorus.home.limit.10