--- name: minecraft-datapack description: "Create, edit, and debug vanilla Minecraft 26.x and 1.21.x datapacks, including functions, advancements, recipes, loot tables, predicates, tags, and pack metadata. Use when the deliverable is a datapack file tree without Java or loader APIs." --- # Minecraft Datapack Skill Inspect `pack.mcmeta` and the target Minecraft version before editing. Preserve an existing target unless migration is requested; metadata numbers alone do not make older command or registry schemas compatible. Check the edited files with the bundled validator and test in-game when available. ## Skill Scope ### Routing Boundaries - `Use when`: the deliverable is datapack files (`pack.mcmeta`, `data/...`) and `.mcfunction`/JSON content. - `Do not use when`: the request is command-only snippets not tied to a datapack file tree (`minecraft-commands-scripting`). - `Do not use when`: the request requires loader APIs, Java code, or runtime mod behavior (`minecraft-modding`). --- ## Pack Metadata | Minecraft Version | Preferred `pack` metadata | |-------------------|---------------------------| | 1.21 / 1.21.1 | `pack_format: 48` | | 1.21.2 / 1.21.3 | `pack_format: 57` | | 1.21.4 | `pack_format: 61` | | 1.21.5 | `pack_format: 71` | | 1.21.6 | `pack_format: 80` | | 1.21.7 / 1.21.8 | `pack_format: 81` | | 1.21.9 / 1.21.10 | `min_format: [88, 0]`, `max_format: [88, 0]` | | 1.21.11 | `min_format: [94, 1]`, `max_format: [94, 1]` | | 26.1 | `min_format: [101, 1]`, `max_format: [101, 1]` | | 26.2 | `min_format: [107, 1]`, `max_format: [107, 1]` | Use `pack_format` for a legacy-only target through data pack format 81. Starting with data pack format 82 in 1.21.9, define both explicit `min_format` and `max_format` values. A range that includes a legacy format below 82 must also retain `pack_format` and `supported_formats`; do not include `supported_formats` for a modern-only range. For a legacy-compatible range, `supported_formats` may be one integer, a two-integer inclusive range, or an object with integer `min_inclusive` and `max_inclusive` fields. For exact patch targeting, use `[major, minor]` arrays for both `min_format` and `max_format`, including `.0` versions such as `[88, 0]`. A single integer is equivalent to `[major, 0]` for `min_format`, while a single integer in `max_format` allows any minor version on that major line. Do not write decimal JSON numbers such as `94.1`. Keep `pack.mcmeta` exact for the patch you target instead of trying to span the multiple Minecraft releases with one metadata block. --- ## Directory Layout ``` my-datapack/ ├── pack.mcmeta └── data/ ├── / ← use your pack's name (e.g., mypack) │ ├── function/ │ │ ├── main.mcfunction │ │ └── tick.mcfunction │ ├── advancement/ │ │ └── custom_advancement.json │ ├── recipe/ │ │ └── custom_recipe.json │ ├── loot_table/ │ │ └── custom_loot.json │ ├── predicate/ │ │ └── is_night.json │ ├── item_modifier/ │ │ └── add_name.json │ └── tags/ │ ├── block/ │ │ └── climbable.json │ ├── entity_type/ │ │ └── bosses.json │ └── function/ │ └── custom_flow.json ← manually invoked tag └── minecraft/ └── tags/function/ ├── load.json ← engine tag; runs on /reload └── tick.json ← engine tag; runs every game tick ``` --- ## `pack.mcmeta` ### 1.21.8 and earlier ```json { "pack": { "pack_format": 81, "description": "My Custom Datapack v1.0" } } ``` ### Deliberate legacy-to-modern compatibility range Use this form only when the pack actually supports both sides of the format-82 boundary. Mojang requires the retained legacy fields for this range. ```json { "pack": { "pack_format": 81, "supported_formats": [81, 88], "min_format": [81], "max_format": [88], "description": "My compatible datapack" } } ``` ### 1.21.9 / 1.21.10 ```json { "pack": { "min_format": [88, 0], "max_format": [88, 0], "description": "My Custom Datapack v1.0" } } ``` ### 1.21.11 ```json { "pack": { "min_format": [94, 1], "max_format": [94, 1], "description": "My Custom Datapack v1.0" } } ``` ### 26.2 ```json { "pack": { "min_format": [107, 1], "max_format": [107, 1], "description": "My Custom Datapack v1.0" } } ``` --- ## Function Tags (load / tick) The engine recognizes the `minecraft:load` and `minecraft:tick` tags, so these files must use the `minecraft` namespace. A `load.json` or `tick.json` in a custom namespace is a valid custom tag name, but it has no automatic behavior. ### `data/minecraft/tags/function/load.json` ```json { "values": [ ":setup" ] } ``` ### `data/minecraft/tags/function/tick.json` ```json { "values": [ ":tick" ] } ``` ### `data//function/setup.mcfunction` ```mcfunction # Runs once on /reload scoreboard objectives add deaths deathCount scoreboard objectives add kills playerKillCount tellraw @a {"text":"[MyPack] Loaded!","color":"green"} ``` ### `data//function/tick.mcfunction` ```mcfunction # Runs every tick — KEEP THIS SHORT # Only put fast, targeted operations here execute as @a[scores={deaths=1..}] run function mypack:on_death_check ``` --- ## Commands and Function Syntax ### Execute subcommands (datapack-specific patterns) ```mcfunction # Chained execute — common datapack pattern for conditional per-player logic execute as @a[gamemode=!spectator] at @s if block ~ ~-1 ~ #minecraft:logs run give @s minecraft:apple # store result into score (bridge between NBT world and scoreboard state) execute store result score @s mypack.health run data get entity @s Health # in: run logic in another dimension execute in minecraft:the_nether run say This runs in the Nether ``` ### Storage NBT (datapack-specific global state) ```mcfunction # Storage is the datapack-native key-value store — persists across /reload data modify storage mypack:data config.difficulty set value "hard" data get storage mypack:data config.difficulty # Copy live entity data into storage for macro use or cross-function state data modify storage mypack:log last_player_pos set from entity @s Pos ``` For full command syntax, selectors, and scoreboard operations see the [Minecraft Wiki — Commands](https://minecraft.wiki/w/Commands) reference. The `minecraft-commands-scripting` skill covers command-only work in depth. --- ## Macros (1.20.2+) Macro functions let you pass dynamic arguments to a function. ### Define a macro function (`data/mypack/function/greet.mcfunction`) ```mcfunction # Macro argument: $(name) $tellraw @a {"text":"Welcome $(name)!","color":"gold"} $scoreboard players set $(name) points 0 ``` ### Call with `run function` + `with` ```mcfunction # Pass values from storage data modify storage mypack:tmp input set value {name:"Steve"} function mypack:greet with storage mypack:tmp input # Pass values from entity NBT function mypack:greet with entity @p {} # Pass value from block NBT function mypack:greet with block 0 64 0 {} ``` --- ## Registry data examples Read [references/data-examples.md](references/data-examples.md) when authoring advancements, recipes, loot tables, predicates, or tags. Load only the relevant section and keep existing namespaces and version targets. ## Worldgen Overrides ### Override biome noise (`data/minecraft/worldgen/noise_settings/overworld.json`) Edit inside an existing copy — do NOT create from scratch without the full JSON. Get the vanilla version from the Minecraft jar: `jar xf minecraft.jar data/`. ### Override a biome's spawn costs ```json { "spawn_costs": { "minecraft:zombie": { "energy_budget": 0.12, "charge": 0.7 } } } ``` --- ## Installation & Testing Place the pack folder or ZIP under the world's `datapacks/` directory, with `pack.mcmeta` at its root. Then use these in-game commands: ```text /datapack list /datapack enable "file/my-datapack" /datapack disable "file/my-datapack" /reload ``` ### Development workflow 1. Edit `.mcfunction` or `.json` files 2. Run the bundled validator to catch JSON and path errors before loading: ```bash ./scripts/validate-datapack.sh --root /path/to/datapack ``` 3. If errors, fix and re-validate until clean 4. Run `/reload` in-game (or `/minecraft:reload` if a mod intercepts it) 5. Test with target command (e.g., `/function mypack:setup`, trigger an advancement) 6. Check `latest.log` for runtime errors (missing references, bad selectors) --- ## Common Errors | Error | Cause | Fix | |-------|-------|-----| | `Unknown or invalid command` | Syntax error in function | Check whitespace, selector, trailing space | | `Datapack did not load` | Invalid JSON in any file | Validate with `jq . < file.json` | | `pack metadata mismatch` | Wrong `pack_format` or `min_format` / `max_format` values | Update `pack.mcmeta` for the exact 1.21.x patch | | Function not running on tick | Missing engine tick tag or wrong namespace | Check `data/minecraft/tags/function/tick.json` | | Macro error | `$` line but no `with` | Provide `with storage/entity/block` | ## Validator Script Use the bundled validator script before shipping a datapack update: ```bash # Run from the installed skill directory (for example `.codex/skills/minecraft-datapack`): ./scripts/validate-datapack.sh --root /path/to/datapack # Strict mode treats warnings as failures: ./scripts/validate-datapack.sh --root /path/to/datapack --strict ``` What it checks: - JSON validity for `pack.mcmeta` and `data/**/*.json` - Legacy pluralized path mistakes for loot tables, functions, and block/item/function tags - `data/minecraft/tags/function/load.json` and `tick.json` references resolve to local `.mcfunction` files - custom-namespace `load.json` and `tick.json` names, which are valid but do not run automatically --- ## References - Minecraft Wiki — Data Pack: https://minecraft.wiki/w/Data_pack - Minecraft Java Edition 1.21.9 release notes: https://www.minecraft.net/en-us/article/minecraft-java-edition-1-21-9 - Minecraft Wiki — Function: https://minecraft.wiki/w/Function_(Java_Edition) - Minecraft Wiki — Commands: https://minecraft.wiki/w/Commands - Pack format history: https://minecraft.wiki/w/Pack_format - NBT format: https://minecraft.wiki/w/NBT_format - Predicate conditions: https://minecraft.wiki/w/Predicate - Loot table format: https://minecraft.wiki/w/Loot_table