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

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.

⚠ Version differences
  • The folder is singular function/ in 1.21+ (pack_format 48); it was plural functions/ through 1.20.6. A 1.21 pack using functions/ 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.
πŸ’‘ Best practice

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

SubcommandGrammarEffectForks?Added
alignalign <axes>Rounds execution position down to the block grid on the given axes (x/y/z combo, e.g. xz).no1.13
anchoredanchored (eyes|feet)Sets the anchor used by ^ local coords & facing.no1.13
asas <targets>Changes the executor (@s); does NOT change position.yes (per entity)1.13
atat <targets>Sets position, rotation, and dimension to the target's.yes1.13
facingfacing <pos> or facing entity <targets> (eyes|feet)Sets rotation to look at a point/entity.yes (entity form)1.13
inin <dimension>Sets execution dimension (respects overworld/nether coord scaling).no1.13
onon <relation>Re-targets the executor via a relation: attacker, controller, leasher, origin, owner, passengers, target, vehicle.yes (passengers)1.19.4 (23w03a)
positionedpositioned <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
rotatedrotated <yaw> <pitch> Β· rotated as <targets>Sets execution rotation.yes (as)1.13
summonsummon <entity_type>Summons a new entity at the execution position and makes it the executor.no1.19.4 (23w06a)
runrun <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).

ConditionGrammarAdded
block(if|unless) block <pos> <blockPredicate>1.13
blocks(if|unless) blocks <start> <end> <destination> (all|masked) β€” masked ignores air in the source1.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 matches1.13
predicate(if|unless) predicate <predicate_id> β€” references a predicate resource by id1.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) loaded1.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)
πŸ“Œ Note

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
⚠ Version differences
  • 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.
πŸ’‘ Best practice

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.

🎩 Trick

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

SinkGrammarNotes
blockstore (result|success) block <targetPos> <path> <type> <scale>Writes into a block entity's NBT. type ∈ byte/short/int/long/float/double; value Γ—scale.
bossbarstore (result|success) bossbar <id> (value|max)Sets a bossbar's current value or max. (Added 18w05a.)
entitystore (result|success) entity <target> <path> <type> <scale>Writes into a single entity's NBT (cannot target UUID-sensitive fields on some paths).
scorestore (result|success) score <targets> <objective>Sets a scoreboard value (integer).
storagestore (result|success) storage <target> <path> <type> <scale>Writes into command storage NBT. (Added 19w38a.)
πŸ“Œ Note

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
⚠ Version differences
  • Core store: since the 1.13 rework.
  • bossbar sink: 1.13 (18w05a).
  • storage sink: 1.15 (19w38a).
🎩 Trick

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

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)"
🚧 Workaround

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.

⚠ Version differences
  • 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.
πŸ’‘ Best practice

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

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
⚠ Version differences
  • The /return command shipped in 1.20.3 (pack_format 26). return run first appeared in 23w31a, was pulled during the 1.20.2 pre-releases, and was restored in 1.20.3 (23w41a); return fail was added in 23w44a.
  • Treat all three forms of /return as 1.20.3+ β€” no /return in 1.20.2 or earlier.
πŸ’‘ Best practice

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:

append vs replace β€” the mode for stacking timers on the same function id:

schedule clear <function> removes all pending schedule(s) for that function id.

⚠ Gotcha

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.

⚠ Version differences
  • Added 1.14 (18w43a). Permission level 2.
  • clear and the append|replace argument were added 1.15 (19w38a).
πŸ’‘ Best practice

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.

🎩 Trick

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

Sources