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.
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