Functions & commands
How .mcfunction files work, the full /execute grammar, storing command output, macros, /return, and /schedule — the executable core of every data pack.
.mcfunction files
A function is a plain-text file of commands executed top-to-bottom. Functions are the backbone of a data pack: they are triggered by /function, by function tags (#minecraft:load, #minecraft:tick), by /schedule, by advancement rewards, and by other functions.
Location & naming
Function files live under the function folder of your namespace. The path (minus the .mcfunction extension) becomes the resource id, with subfolders joined by /:
data/<namespace>/function/<name>.mcfunction # 1.21+ (SINGULAR "function")
data/<namespace>/functions/<name>.mcfunction # 1.20.6 and earlier (plural)
So data/foo/function/summon/pig.mcfunction has the id foo:summon/pig. Namespaces and paths may use only [a-z0-9_.-] (the path also allows /).
File syntax rules
- One valid command per line, WITHOUT the leading forward slash — write
say hi, not/say hi. - Comments begin a line with
#:# this is a comment. - A line may have leading/trailing tabs and spaces around the command.
- Blank lines are allowed and ignored.
- Line continuation 1.20.2+ — a single backslash
\as the last non-whitespace character continues the command on the next line. - Macro lines begin with
$(see Macros).
Example — file + call
data/foo/function/greet.mcfunction
# One command per line, no leading slash, comments with #
say Hello from foo:greet
effect give @a minecraft:glowing 5 0 true
# blank line above is fine; next line uses backslash continuation (1.20.2+)
tellraw @a \
{"text":"Long message split across lines","color":"gold"}
Run it with /function foo:greet.
- The folder is singular
function/in 1.21+ (pack_format48); it was pluralfunctions/through 1.20.6. A 1.21 pack usingfunctions/silently fails to register the function. - Backslash line continuation: 1.20.2+ only.
- Macro (
$) lines: 1.20.2+ only — older versions treat$…as an invalid command and error. - Breaking in 26.2: colour arguments to
team modify <name> colorandwaypoint modify <name> colornow accept only lowercase-with-underscore names.dark_purplevalidates;darkpurpleandDarkPurpleno longer do. The accepted set now matches the colour names used in text components. A pack that built these arguments by concatenation will fail at command-parse time, not silently. (Site: 26.2) - New in 26.2:
unpublish, which closes a player’s published integrated server if one is open. Also in 26.2,execute … link=nonenow treats vexes as owned by their summoning evoker, so alink=nonefilter that previously matched a vex no longer does. (Site: 26.2) - 26.2 also changed
advancement grant/revokeoutput: the result now reports how many advancements changed state across all players, and how many players were affected. Anything parsing that output, or storing it withexecute store result, should be re-checked. (Site: 26.2)
Namespace everything under your own pack id; never write into minecraft: except the #minecraft:load / #minecraft:tick tags (not the functions themselves). Organize with subfolders (main/, api/, impl/, zzz_internal/) — the / in the id is free structure — and keep one logical action per function, calling sub-functions with function / execute … run function for readability and reuse.
The /execute grammar
/execute chains modifier subcommands that mutate the execution context (executor @s, position, rotation, dimension, anchor), optional condition subcommands (if/unless), and terminates in exactly one run <command> — or ends after a final condition, which then reports success/fail. The modern grammar dates from the 1.13 rework (17w45a). The context fields a subcommand can change are the executor, execution position, execution rotation, execution dimension, and execution anchor.
Modifier subcommands
| Subcommand | Grammar | Effect | Forks? | Added |
|---|---|---|---|---|
align | align <axes> | Rounds execution position down to the block grid on the given axes (x/y/z combo, e.g. xz). | no | 1.13 |
anchored | anchored (eyes|feet) | Sets the anchor used by ^ local coords & facing. | no | 1.13 |
as | as <targets> | Changes the executor (@s); does NOT change position. | yes (per entity) | 1.13 |
at | at <targets> | Sets position, rotation, and dimension to the target's. | yes | 1.13 |
facing | facing <pos> or facing entity <targets> (eyes|feet) | Sets rotation to look at a point/entity. | yes (entity form) | 1.13 |
in | in <dimension> | Sets execution dimension (respects overworld/nether coord scaling). | no | 1.13 |
on | on <relation> | Re-targets the executor via a relation: attacker, controller, leasher, origin, owner, passengers, target, vehicle. | yes (passengers) | 1.19.4 (23w03a) |
positioned | positioned <pos> · positioned as <targets> · positioned over <heightmap> | Sets execution position. over uses heightmaps: world_surface, motion_blocking, motion_blocking_no_leaves, ocean_floor. | yes (as) | 1.13; over in 1.19.4 pre1 |
rotated | rotated <yaw> <pitch> · rotated as <targets> | Sets execution rotation. | yes (as) | 1.13 |
summon | summon <entity_type> | Summons a new entity at the execution position and makes it the executor. | no | 1.19.4 (23w06a) |
run | run <command> | Runs the final command in the built context. Only appears once, at the end. | — | 1.13 |
Condition subcommands (if / unless)
All support both if (true → continue/succeed) and unless (negated).
| Condition | Grammar | Added |
|---|---|---|
block | (if|unless) block <pos> <blockPredicate> | 1.13 |
blocks | (if|unless) blocks <start> <end> <destination> (all|masked) — masked ignores air in the source | 1.13 |
data | (if|unless) data (block <pos>|entity <target>|storage <source>) <path> — true if the path exists (matches ≥1) | 1.14 (18w43a) |
entity | (if|unless) entity <selector> — true if ≥1 entity matches | 1.13 |
predicate | (if|unless) predicate <predicate_id> — references a predicate resource by id | 1.15 (19w38a) |
score | (if|unless) score <t> <tObj> (<|<=|=|>=|>) <s> <sObj> or … <t> <tObj> matches <range> | 1.13 |
biome | (if|unless) biome <pos> <biome|#biome_tag> | 1.19.3 (22w46a) |
dimension | (if|unless) dimension <dimension> | 1.19.4 (23w03a) |
loaded | (if|unless) loaded <pos> — true if the chunk is fully (entity-ticking) loaded | 1.19.4 (23w03a) |
items | (if|unless) items (block <pos>|entity <source>) <slots> <item_predicate> | 1.20.5 (24w10a) |
function | (if|unless) function <function|#tag> — runs the function(s); true if any returns non-zero (non-void via /return). Works as a terminal condition like other if/unless checks. | 1.20.2 (23w31a), reintroduced 1.20.3 (23w41a) |
The matches <range> ranges are inclusive: 5 (exactly 5), 1..10, 5.. (≥5), ..5 (≤5). And on versioning — execute if function has existed since 1.20.2 (23w31a); there is no separate 1.21.9 introduction, so treat it as available in every 1.21 version.
Examples
data/foo/function/execute_demo.mcfunction
# Loop over all zombies, at each one's feet check the block below
execute as @e[type=minecraft:zombie] at @s if block ~ ~-1 ~ minecraft:grass_block \
run particle minecraft:flame ~ ~ ~ 0 0 0 0 1
# Relation: give the vehicle of every player glowing
execute as @a on vehicle run effect give @s minecraft:glowing 3 0 true
# 'if items' with an item predicate (both 1.20.5+): any main-hand item with a damage component
execute if items entity @s weapon.mainhand *[minecraft:damage] run say holding a damageable item
on,dimension,loaded,positioned over: 1.19.4.summon: 1.19.4 (23w06a).biome: 1.19.3.if function: 1.20.2 / 1.20.3.if items+ inline predicate objects: 1.20.5.
Order matters: put the cheapest, most-selective condition first (if entity @s[…] before if data …) to short-circuit. execute as … at @s is the canonical "for-each entity, at its position" idiom, and positioned over motion_blocking snaps to the top solid block for surface spawning.
A bare execute … if <cond> (no run) is itself a command whose success drives the enclosing execute store success or another if — a compact way to compose conditions into a 0/1 flag.
execute store result | success
store captures the terminal command's result (its numeric return value) or success (1 if it succeeded, else 0) into a data sink, evaluated AFTER the run command finishes.
execute store (result|success) <sink> … run <command>
Sinks
| Sink | Grammar | Notes |
|---|---|---|
block | store (result|success) block <targetPos> <path> <type> <scale> | Writes into a block entity's NBT. type ∈ byte/short/int/long/float/double; value ×scale. |
bossbar | store (result|success) bossbar <id> (value|max) | Sets a bossbar's current value or max. (Added 18w05a.) |
entity | store (result|success) entity <target> <path> <type> <scale> | Writes into a single entity's NBT (cannot target UUID-sensitive fields on some paths). |
score | store (result|success) score <targets> <objective> | Sets a scoreboard value (integer). |
storage | store (result|success) storage <target> <path> <type> <scale> | Writes into command storage NBT. (Added 19w38a.) |
The store targets are block, bossbar, entity, score, storage — the four NBT-style targets plus score. There is no bunch target; that spelling is a typo for bossbar.
Examples
data/foo/function/store_demo.mcfunction
# Count nearby armor stands into a score
execute store result score #count temp run execute if entity @e[type=armor_stand,distance=..10]
# Read an entity's Y-position (×1) into storage as a double
execute store result storage mypack:tmp pos.y double 1 run data get entity @s Pos[1]
# Store command success (0/1) into a block entity flag
execute store success block ~ ~ ~ CustomFlag byte 1 run scoreboard players test #x obj 1 1
- Core
store: since the 1.13 rework. bossbarsink: 1.13 (18w05a).storagesink: 1.15 (19w38a).
store result runs the command; store success records whether it succeeded — great for turning any conditional into a 0/1 flag. Scale + int truncation lets you do fixed-point math: multiply a float by 100, store as int, for cheap 2-decimal fixed-point. And store result storage … <type> <scale> is the standard bridge from scoreboard → NBT that feeds macros.
Macros 1.20.2+
Macros let a function build commands from runtime data. A macro line starts with $ and contains $(key) placeholders; before each execution the placeholders are substituted from the arguments passed to the function, and the resulting string is parsed as a command at call time. Added in 1.20.2 (23w31a) and unavailable before it.
Syntax
- A macro line must begin with
$as the first character:$say hello $(name). - Placeholder
$(key), wherekeymatches[a-zA-Z0-9_]+. - Non-
$lines in the same file are normal commands and are NOT substituted. - Value conversion: numeric NBT values are inserted as plain text with the type suffix removed (e.g.
10b→10,3.0d→3.0). Compounds/lists are inserted as their SNBT text — so you often must re-add quotes/braces yourself in the template.
Calling forms
function <name> # no args (error if the function has macro lines needing args)
function <name> {key:"value", n:10} # inline SNBT compound as arguments
function <name> with block <sourcePos> [<path>] # args = NBT compound read from a block entity
function <name> with entity <source> [<path>] # args = NBT compound read from an entity
function <name> with storage <source> [<path>] # args = NBT compound read from command storage
The optional [<path>] narrows to a sub-compound of the source. The source compound's top-level keys become the available $(key) names.
Worked example A — inline compound
data/foo/function/spawn.mcfunction
$summon $(mob) ~ ~ ~ {CustomName:'{"text":"$(name)"}'}
Call it with a compound of arguments:
/function foo:spawn {mob:"minecraft:cow", name:"Bessie"}
Worked example B — with storage (scoreboard → macro)
Build the argument compound in the caller, then invoke the macro function in a separate file:
data/example/function/summon/pig.mcfunction
# 1) build the argument compound in storage from scores
execute store result storage example:macro pos.x int 1 run scoreboard players get X pos
execute store result storage example:macro pos.y int 1 run scoreboard players get Y pos
execute store result storage example:macro pos.z int 1 run scoreboard players get Z pos
# 2) call the macro function, feeding storage path pos
function example:summon/pig_macro with storage example:macro pos
data/example/function/summon/pig_macro.mcfunction
$summon minecraft:pig $(x) $(y) $(z) {Tags:["custom_pig"]}
$tellraw @a "Pig summoned at $(x) $(y) $(z)"
You cannot read macro args in the same function that sets them. Arguments are bound when the function … with … call is made, so the setup (store result storage …) and the $ macro lines must live in separate functions — hence the two-file split above.
- The entire feature is 1.20.2+ — no macros in 1.20.1 or earlier.
with (block|entity|storage)and the inline{…}form all arrived together in 23w31a.- Before macros, "dynamic" commands required precomputed lookup tables of
execute if score … run <specific command>for every possible value, or NBT-tree binary-search selectors; macros collapse these to one templated line.
Keep macro functions tiny — one or two $ lines — and put all data-prep in the caller. Macros re-parse the command each call (a small perf cost), so don't macro a line whose values never change. Always sanitize string args that flow into JSON/SNBT (quotes/backslashes) to avoid broken commands or injection when args come from player input (sign text, book, rename).
/return 1.20.3+
/return ends the current function immediately and sets the function's success and result (return value). It is how a function reports a value to execute … run function, execute if function, or return run function.
Syntax & semantics
return <value> # end function, success=true, result = <value> (32-bit int, -2147483648..2147483647)
return fail # end function, success=false, result = 0
return run <command> # run <command>, then end function using THAT command's success & result
- Early exit: everything after
/returnin the function is skipped. - Forking: inside a forking
execute(e.g.as @e … run return …),/returnends the whole function after the first branch that reaches it — a common way to "return the first match." execute if function <f>treats the callee as true when its result is non-zero / non-void; a function that never calls/returnis void (neither true nor false — counts as 0 for sums).
Example
data/foo/function/is_day.mcfunction
execute unless predicate foo:is_daytime run return fail
return 1
data/foo/function/caller.mcfunction
# Use is_day as a boolean:
execute if function foo:is_day run say It is daytime
# Return the first matching entity's Health, short-circuiting a fork:
execute as @e[tag=target] run return run data get entity @s Health
- The
/returncommand shipped in 1.20.3 (pack_format26).return runfirst appeared in 23w31a, was pulled during the 1.20.2 pre-releases, and was restored in 1.20.3 (23w41a);return failwas added in 23w44a. - Treat all three forms of
/returnas 1.20.3+ — no/returnin 1.20.2 or earlier.
Use return fail / return 1 to build reusable boolean helper functions callable from execute if function. return run <command> forwards a command's own result — ideal for wrapping data get, scoreboard players get, or another function so the wrapper transparently yields that value. Guard clauses at the top (execute unless … run return fail) keep the happy path unindented.
/schedule
Delays a function to run later, measured in game time. Schedules survive as pending timers and fire during the scheduled-functions phase of a tick.
schedule function <function> <time> [append|replace]
schedule clear <function>
Arguments
Time — a float with a unit suffix:
t(default) = 1 gametick.s= 1 second = 20 gameticks.d= 1 in-game day = 24000 gameticks (.5d= 12000t).
append vs replace — the mode for stacking timers on the same function id:
replace(default): overwrite the existing pending schedule for that function with the new time — only one pending timer per function.append: add another independent timer, allowing the same function to have multiple pending schedules at different times.
schedule clear <function> removes all pending schedule(s) for that function id.
1t does not always equal exactly one real tick of delay. Called from a #minecraft:tick function it can run within the same tick's processing; called from the scheduled-function phase it lands on the next tick. Don't rely on 1t for exact single-tick precision.
Example — a self-rescheduling clock
data/foo/function/clock.mcfunction
say tick every second
schedule function foo:clock 1s replace
Kick it off once from load with function foo:clock. Using replace prevents timer pile-up if clock is ever triggered twice.
- Added 1.14 (18w43a). Permission level 2.
clearand theappend|replaceargument were added 1.15 (19w38a).
Prefer a replace self-schedule over #minecraft:tick when you need coarse timing (every N ticks/seconds) — far cheaper than running every tick and counting. Use append only when you genuinely want several overlapping timers. Always schedule clear on shutdown/reset routines so stale timers don't fire after a reload — pending schedules persist across /reload unless you clear them.
Recursion & per-entity loops
A function may call itself. Combined with a terminating condition, this gives you loops without a per-tick counter.
Per-entity loop: execute as @e[…] at @s run function … forks the callee once per matching entity, running it in each entity's context. For a value-carrying loop, use a macro counter: pass $(i) in the compound, decrement it into storage, and function self with storage … until a guard fails. Pair a recursive function with execute if for the terminating condition, or with /return to short-circuit on the first match.
data/foo/function/countdown.mcfunction
# Recurse with a scoreboard guard: stop when #i reaches 0
scoreboard players remove #i foo.loop 1
say counting...
execute if score #i foo.loop matches 1.. run function foo:countdown