Compile a tiny MDL language or Python API into a Minecraft datapack (1.21+ ready).
Project description
Minecraft Datapack Language (MDL)
A tiny compiler that lets you write Minecraft datapacks in a simple language (.mdl) or via a clean Python API, and then compiles to the correct 1.21+ datapack folder layout (singular directories) automatically.
- ✅ Handles the directory renames from snapshots 24w19a (tag subfolders) and 24w21a (core registry folders) for you.
- ✅ Easy hooks into
minecraft:tickandminecraft:loadvia function tags. - ✅ Creates tags for
function,item,block,entity_type,fluid, andgame_event. - ✅ VS Code extension for syntax highlighting, linting, and quick compile.
Default pack_format is 48 (Java 1.21). Set
--pack-format 47to emit the legacy plural layout for older versions.
Install
Option A — from PyPI (recommended for users)
Global, isolated CLI via pipx:
python3 -m pip install --user pipx
python3 -m pipx ensurepath # reopen terminal
pipx install minecraft-datapack-language
mdl --help
Virtualenv (if you prefer):
python3 -m venv .venv
source .venv/bin/activate # Windows: .\.venv\Scripts\Activate.ps1
pip install minecraft-datapack-language
Option B — from source (for contributors)
# inside the repo
python -m pip install -e .
Update
- pipx:
pipx upgrade minecraft-datapack-language - pip (venv):
pip install -U minecraft-datapack-language - Pin a version:
pipx install "minecraft-datapack-language==1.1.0"
CLI
mdl new my_pack --name "My Pack" --pack-format 48
mdl check my_pack/mypack.mdl
mdl build --mdl my_pack/mypack.mdl -o dist --wrapper mypack --pack-format 48
# → dist/mypack/... and dist/mypack.zip
Build a whole folder of .mdl files
mdl build --mdl src/ -o dist
# Recursively parses src/**/*.mdl, merges into one pack (errors on duplicate functions).
Validate a folder (JSON diagnostics)
mdl check --json src/
The .mdl language
Grammar you can rely on (based on the parser)
- pack header (required once):
pack "Name" [description "Desc"] [pack_format N]
- namespace (selects a namespace for following blocks):
namespace "example"
- function (colon + indented commands, 4-space indents only):
function "hello": say hi tellraw @a {"text":"ok","color":"green"} - function calls (one function invoking another with fully qualified ID):
function "outer": say I will call another function function example:hello - hooks (namespaced ids required):
on_load "example:hello" on_tick "example:hello"
- tags (supported registries:
function,item,block,entity_type,fluid,game_event):tag function "minecraft:tick": add "example:hello"The parser accepts an optionalreplaceflag on the header (e.g.tag function "minecraft:tick" replace:) but replacement behavior is controlled by the pack writer. - comments start with
#. Hashes inside quoted strings are preserved. - whitespace: empty lines are ignored; indentation must be multiples of four spaces (tabs are invalid).
Inside a function block, every non-empty line is emitted verbatim as a Minecraft command—no extra parsing.
FULL example (nested calls + multi-namespace)
# mypack.mdl — nested and multi-namespace demo
pack "Minecraft Datapack Language" description "Nested + Namespaces" pack_format 48
# === First namespace ===
namespace "example"
function "inner":
say [example:inner] This is the inner function
tellraw @a {"text":"Running inner","color":"yellow"}
function "outer":
say [example:outer] This is the outer function
# "nested" call into inner (composition)
function example:inner
tellraw @a {"text":"Back in outer","color":"aqua"}
# Run outer once on pack load
on_load "example:outer"
# === Second namespace ===
namespace "util"
function "helper":
say [util:helper] Helping out...
tellraw @a {"text":"Util helper called","color":"green"}
function "boss":
say [util:boss] Calling outer, then helper
# cross-namespace calls with fully-qualified IDs
function example:outer
function util:helper
tellraw @a {"text":"Boss finished!","color":"red"}
# Run boss every tick
on_tick "util:boss"
# Tag example for demonstration (tick also includes boss)
tag function "minecraft:tick":
add "util:boss"
What this demonstrates
- Nested-like function composition via the
function <ns:id>command. - Multiple namespaces (
example,util) calling each other with fully-qualified IDs. - Lifecycle hooks (
on_load,on_tick) using namespaced function IDs. - Function tagging to participate in vanilla tags (
minecraft:tick).
Python API equivalent
from minecraft_datapack_language import Pack
def build_pack():
p = Pack(name="Minecraft Datapack Language",
description="Nested + Namespaces",
pack_format=48)
ex = p.namespace("example")
ex.function("inner",
'say [example:inner] This is the inner function',
'tellraw @a {"text":"Running inner","color":"yellow"}'
)
ex.function("outer",
'say [example:outer] This is the outer function',
'function example:inner',
'tellraw @a {"text":"Back in outer","color":"aqua"}'
)
# Hooks
p.on_load("example:outer")
util = p.namespace("util")
util.function("helper",
'say [util:helper] Helping out...',
'tellraw @a {"text":"Util helper called","color":"green"}'
)
util.function("boss",
'say [util:boss] Calling outer, then helper',
'function example:outer',
'function util:helper',
'tellraw @a {"text":"Boss finished!","color":"red"}'
)
# Tick hook + a function tag example
p.on_tick("util:boss")
p.tag("function", "minecraft:tick", values=["util:boss"])
return p
Build it:
python - <<'PY'
from my_pack_module import build_pack
from minecraft_datapack_language.cli import main as M
# write to dist/ with a wrapper folder name 'mypack'
p = build_pack()
M(['build', '--py-object', 'my_pack_module:build_pack', '-o', 'dist', '--wrapper', 'mypack', '--pack-format', '48'])
PY
VS Code
Open vscode-extension/, then:
npm i
# Press F5 to launch the Extension Dev Host
- Highlights
.mdl - Runs
mdl checkon save and shows inline diagnostics - MDL: Build current file prompts for output folder and optional wrapper
- MDL: Check Workspace validates the whole workspace
CI & Releases
- CI runs on push/PR across Linux/macOS/Windows and uploads artifacts.
- Release is triggered by pushing a tag like
v1.0.0or via the Release workflow manually. - Versions are derived from git tags via setuptools-scm; tag
vX.Y.Z→ package versionX.Y.Z.
Local release helper
# requires GitHub CLI: gh auth login
./scripts/release.sh patch "Fixes"
./scripts/release.sh minor "Features"
./scripts/release.sh major "Breaking"
./scripts/release.sh v1.2.3 "Exact version"
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file minecraft_datapack_language-4.3.0.tar.gz.
File metadata
- Download URL: minecraft_datapack_language-4.3.0.tar.gz
- Upload date:
- Size: 50.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e0ad1fe61d9a3e9901b90db428759f5266001413e20df55fe4ef97ad66ef1ea
|
|
| MD5 |
7a914424e95a9d2541652551500b066f
|
|
| BLAKE2b-256 |
412e7b58287efe09bdb69dff11a24d103bd2e201f368b099d5773dfbf093eb4a
|
File details
Details for the file minecraft_datapack_language-4.3.0-py3-none-any.whl.
File metadata
- Download URL: minecraft_datapack_language-4.3.0-py3-none-any.whl
- Upload date:
- Size: 26.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab66bffd2dc2de02e210e2b6e7bb4e894889dc0d61b641e5a661024f14bcb496
|
|
| MD5 |
19be1b182779d82d7d5ad25078413646
|
|
| BLAKE2b-256 |
06700f1d7cd4e075ba438e9194842ac6d067c573ca666073a892640a9c8b3f2d
|