Functions
A Function body is code that compiles to a .mcfunction file. It mixes raw commands, which start with /, with statements that compile to commands. The Functions guide explains each part at length, and How functions compile shows what it becomes.
/** The state of a siege, kept in storage. */
Type SiegeState {
wave: int = 0
boss_alive: bool = false
}
Storage game: SiegeState
const max_wave = 10
const boss = @e[tag=siege.boss, limit=1]
const wave_mobs = [zombie, skeleton, spider, creeper]
Function next_wave {
if (game.wave >= max_wave) {
tell(@a, "{gold}**Victory!**{/} The banner holds.")
return
}
game.wave += 1
for mob in wave_mobs {
/execute at @e[tag=siege.spawn] run summon ${mob} ~ ~ ~ {Tags:["siege.enemy"]}
}
if (game.wave % 5 == 0 && !exists(boss)) {
/summon wither_skeleton ~ ~ ~ {Tags:["siege.boss"]}
game.boss_alive = true
}
title(@a, "{gold}Wave ${game.wave}", subtitle = "{gray}*hold the line*")
}
Statements
| Write | Does |
|---|---|
/say hi |
a command, checked against the game's command tree |
let n = 3, let ok: bool = n > 2 |
a local variable |
let n = /data get block ~ ~ ~ Items, let ok: bool = /execute if block ~ ~ ~ chest |
a command's result, or for a bool whether it succeeded |
const n = 3 |
a value folded into every use |
n = 1, n += 1, -=, *=, /=, %= |
assignment |
if (c) { } else if (c) { } else { } |
a branch |
while (c) { } |
a loop |
for i in 1..10 { } |
a loop over a range, both ends included |
for x in [a, b, c] { } |
the body once per item, unrolled at compile time |
break, continue, return, return value |
leave a loop or the function |
f(), f(1, 2), other:f() |
a call |
As(@a).At(@s) { } |
the block under execute |
run { } |
an inline function, as a value, such as a custom item's on_right_click |
Values
Function code computes with int (32-bit, wrapping like a scoreboard), bool and string.
| Write | Is |
|---|---|
Global deaths: int = 0 |
one value for the pack, set when it first loads |
Objective kills: deathCount, kills[@s] |
a score per holder: a selector, or a name such as kills["#total"] |
Storage game: SiegeState, game.wave |
a record's field in command storage |
let n = 0 |
a local of the function |
@e[tag=x], exists(sel), count(sel) |
a selector, whether it finds any entity, and how many |
Objective name with no criterion is a dummy score, and a comma list declares several: Objective wins, losses.
Parameters and results
Function classify(x: int): int {
if (x > 100) {
return 2
} else if (x > 0) {
return 1
}
return 0
}
Function report {
let c = classify(150)
/say class ${c}
}
Parameters are int, bool or string, and a function returns int or bool. A function with a return type must return on every path.
Interpolation
${expr} puts a value into a command. A value known at compile time is written in. A run-time value, such as a score or a parameter, turns the line into a macro, and the editor marks it with a macro inlay. In text, ${...} never needs a macro: see Text.
Command templates
A Template that returns Commands writes its body where it is called. Its loops unroll and its ${...} pieces are worked out at compile time, so it costs no function call:
/** Draws a ring of particles around the executor. */
Template particle_ring(p: Id<particle>, radius: float, points: int = 16): Commands {
for i in 0..points - 1 {
let a = i * 360 / points
/particle ${p} ^${radius * cos(a)} ^1 ^${radius * sin(a)}
}
}
Function celebrate {
As(@a).At(@s) {
particle_ring(flame, 2)
}
}
The editor marks each call with an inlined inlay, and hover shows the commands it writes. cos and sin take degrees.
Execute blocks
As, At, Positioned, Rotated, Facing, In, Anchored, Align, On, Summon and Execute("...") chain into an execute command whose run is the block. The guide lists each one.
Events
| Declaration | Runs |
|---|---|
OnLoad { } |
when the pack loads, and on /reload |
OnTick { } |
every tick |
OnFirstJoin { } |
once per player, the first time they join |
OnRespawn { } |
when a player respawns |
OnAdvancement name = Trigger(...) { } |
each time a player meets the trigger, such as PlacedBlock(...) |
The body runs as the player, at their position, except OnLoad and OnTick, which run as the server. The unnamed ones merge: several OnTick blocks in a project become one tick function. A custom item has its own hooks, such as on_right_click and on_hit.
Objective banners
/** Counts every banner a player places. */
OnAdvancement placed_banner = PlacedBlock(location = LocationCheck(predicate = { block = { blocks = #banners } })) {
banners[@s] += 1
}
OnRespawn {
/effect give @s minecraft:regeneration 5 1
}