Write Python-like code, compile it, then put datapack.zip in the world's datapacks folder. Run /reload in game.
def init(): runs once on load. Code outside a def runs every tick.
Who: me, players, all, nearest, or near(zombie, distance=8).
Where: here, below, above, rel(0,-1,0), pos(10,64,0).
What: write ids directly. diamond_block compiles as minecraft:diamond_block.
give(me, diamond, 3) title(me, "Wave 1") effect(me, speed, seconds=10) summon(zombie, here)
Indent under with or if. These compile to Minecraft execute commands.
with as_players():
if block_is(below, gold_block):
tell(me, "on gold!")
raycast is built in. It casts from eyes or feet. Inside the block, here is the block position being aimed at; use offset to move along the look ray. through can be one block, a tag, or a list.
with as_players():
with raycast(max=40, offset=-1,
through=[air, cave_air, water]):
setblock(here, glowstone)
raycast_miss runs only if no solid block is hit before max range.
with as_players():
with raycast_miss(max=20):
summon(lightning_bolt, here)
raycast_entity finds the first matching entity near the ray. Inside the block, me is the hit entity and here is the ray position. Set stop_at_blocks=false for through-wall checks.
with as_players():
with raycast_entity(entities(zombie), radius=1):
effect(me, glowing, seconds=2)
raycast_entity_miss runs at max range when no entity is found.
sleep(20) waits 20 ticks. sleep("3s") waits 3 seconds. It schedules the rest of the function for later, so the game keeps running. Use it at top level, in def, or in with; avoid it inside if.
Assign values with normal Python-style syntax:
points = 0 # int - LIVE ready = true # bool - LIVE pi = 3.14 # float - constant name = "Hero" # string- constant spawn = vec3(0,64,0) # vec3 - constant
Live int/bool variables use scoreboards and can change while the pack runs:
points = points + 10 points = points * 2
Constants are fixed when you compile. Use them for config, names, and positions:
setblock(spawn, beacon) greeting = "Hi " + name
Lists stay static unless you mutate them. Static lists compile directly into commands, which is the fastest path:
pass_blocks = [air, cave_air, water]
with as_players():
with raycast(through=pass_blocks):
setblock(here, glowstone)
If you call a mutating method, the list becomes dynamic and is stored in storage. Dynamic setup usually belongs in def init():
def init():
pass_blocks = [air, cave_air, water]
pass_blocks.append(glass)
pass_blocks.insert(1, lava)
pass_blocks.remove_at(0)
pass_blocks.pop_end()
count = len(pass_blocks)
Use persist before the name when a dynamic list should survive reloads. Put the starting value in def init(); it is only applied the first time.
persist pass_blocks
def init():
pass_blocks = [air, cave_air, water]
with as_players():
if block_is(below, gold_block):
pass_blocks.pop_end()
Top-level assignments run every tick and will reset a dynamic list every tick, just like other top-level code.
Use f"..." strings when a message needs a variable value:
tell(me, f"Score: {points}")
actionbar(me, f"{name} has {points}!")
say() cannot show live variables; use tell() or actionbar().
Put color and style tags inside an f"..." string before the text they should affect:
tell(me, f"{gold}{bold}Score: {points}")
actionbar(me, f"{red}Low HP! {reset}{hp}/20")
title(me, f"{aqua}Wave {wave}")
Works in tell, title, actionbar, and item name/lore.
give(me, diamond_sword,
name=f"{aqua}{bold}Frostbite",
lore=[f"{gray}Frozen blade", f"{gold}+5 style"])
Colors: black, dark_blue, dark_green, dark_aqua, dark_red, dark_purple, gold, gray, dark_gray, blue, green, aqua, red, light_purple, yellow, white.
Styles: bold, italic, underlined, strikethrough, obfuscated. Aliases: underline, strike, magic. Use {reset} to go back to the command's default style.
Live variables reset on reload unless you mark them with persist before first use:
persist coins # kept across reloads
def init():
coins = 0 # first load only
tries = 0 # resets on reload
with as_players():
if block_is(below, gold_block):
coins = coins + 1
Only int/bool variables can persist.
give accepts common item fields directly: name, color, lore, enchant, unbreakable, model, attributes, and more. Use components={...} for raw item components.
give(me, diamond_sword,
name="Frostbite", enchant={sharpness:5},
model="my_pack:frostbite", unbreakable=true)
model sets the modern item_model component, which is the normal way to give an item a custom model in 26.1-26.2. For advanced item model predicates, use structured custom_model_data with strings, floats, flags, or colors:
give(me, stick,
custom_model_data={strings:["wand"]})
setblock accepts state={...} for block states, data={...} for block entity data, and command= for command blocks.
setblock(below, chest,
data={Items:[{slot:0, id:"minecraft:diamond", count:5}]})
raw_command("...") emits a Minecraft command unchanged, without the leading slash. It is a fallback, not the recommended way to write packs. If you need it because a command is missing, comment on the Reddit feedback post.
raw_command("weather clear")
Edits autosave in this browser.
Reset to Example restores the starter script.
Start typing for autocomplete; use the arrow keys and Enter.
Click a function for its signature and an example.
Edit the code, then click "Compile and Download" to get datapack.zip.