Getting started
MMS is a small language that compiles to Minecraft Java Edition data packs. You declare resources and functions in .mms files, and mms build writes the JSON and .mcfunction files. The target is Minecraft 26.3.
Install
- In the browser: the editor needs no install. Projects are saved in your browser (click the project name to switch between them), and Download pack gives you the data pack as a zip.
- Command line: download
mmsfor your system from the releases page. Or, with Go installed, rungo install github.com/minecraftmetascript/mms/engine/cmd/mms@latest. - VS Code: install the
.vsixfor your system from the same release, such asmms-win32-x64-1.0.0.vsixormms-darwin-arm64-1.0.0.vsix, through Extensions → … → Install from VSIX. It includesmms, so you do not need the command line to use the editor. (The universalmms-1.0.0.vsixdoes not, and runsmmsfrom yourPATHormms.path.)
A first project
mkdir gems && cd gems
mms init -namespace gems
mms init writes mms.json (the namespace, the pack description, the output folder) and a starter file. Its $schema line points at the mms.json schema, so editors with JSON Schema support (VS Code, JetBrains) complete, describe and check every field. The VS Code extension knows the schema even without that line. Every .mms file in the folder belongs to the project. Put this in gems.mms:
/** Gems that drop from the gem chest. */
ItemTag gems = [diamond, emerald, amethyst_shard]
LootTable chests/gems {
pools = [Pool(1..3, #gems)]
}
Recipe gem_block = Shaped(["GG", "GG"], { G = #gems }, emerald_block)
Objective found
Function find {
found[@s] += 1
/loot give @s loot gems:chests/gems
tell(@s, "You have found ${found[@s]} gem chests")
}
Then build:
mms build # writes build/
mms build -world ~/.minecraft/saves/MyWorld # installs into a world
Declarations
Each declaration is Kind name = value, or Kind name { fields } for an object:
- Kinds are PascalCase:
LootTable,DensityFunction,ItemTag. Every resource folder in a data pack has one. The reference lists them all. - Names become ids in the file's namespace:
chests/gemsin namespacegemsisgems:chests/gems, written todata/gems/loot_table/chests/gems.json. - Doc comments (
/** ... */) describe the declaration right below them. See Doc comments.
A Namespace line switches the namespace for the rest of the file:
Namespace minecraft
ItemTag swords = [diamond_sword]
Replacing a vanilla resource like this is allowed. The editor notes that it happens, since vanilla's version is lost.
Doc comments
A comment that starts with /** documents the declaration, let or parameter list that follows it. Only blank space may come between the two. The text is Markdown, and it appears on hover over the name, both where it is declared and wherever it is used: in other files, in calls, in kills[@s] scores, inside commands such as /function gems:find, and in ${...}. Completion and signature help show it too.
Objective found
/**
* Gives a player their reward and counts it.
*
* @param count how many diamonds to give
* @returns the player's new total
* @deprecated use `reward_all`
*/
Function reward(count: int): int {
/** Rewards before this one. */
let before = found[@s]
/give @s diamond ${count}
found[@s] = before + 1
return found[@s]
}
These JSDoc-style tags are understood:
@param name textdocuments a parameter. Hovering the parameter shows its text, and so does signature help while typing that argument.@returns text(or@return) describes the result.@deprecated [text]marks the declaration as deprecated. Every use gets adeprecatedlint warning and is struck through in the editor.@examplestarts a code example, and@see textadds a pointer elsewhere.@label textnames an entry of a template pool'selementslist. A doc comment works above an entry too, and the jigsaw preview and its export show its label (or else the first line of its text) next to the piece. That tells apart one structure listed several times with different processors:elements = [ WeightedElement(50, SinglePoolElement(rigid, StructureFile("structures/road_cap.nbt"), [])), /** @label Worn road cap */ WeightedElement(10, SinglePoolElement(rigid, StructureFile("structures/road_cap.nbt"), road_wear_medium)), ]
Other tags are shown as written. The formatter lines doc comments up with a * on every line and keeps the indentation inside them, so indented code and nested lists survive.
Projects with several files
A project is every .mms file under the folder that holds mms.json, including subfolders. The build output folder, node_modules and any folder whose name starts with . are skipped, at any depth. To limit the project to some files, list glob patterns in sources in mms.json, such as ["src/**/*.mms"].
- One namespace of names. A declaration in any file can be used from any other, and the order of files and declarations does not matter. Declaring the same id twice for one kind is an error that points to the other declaration. Tags are the exception: declarations of the same tag merge, so a tag can be built up across files. Different kinds can share an id, such as a
Recipeand aLootTableboth namedgem_block. - Namespaces per file. Each file starts in the namespace from
mms.json. ANamespaceline changes it for the rest of that file only. - Folders are for you. A file's folder does not change the ids it declares:
LootTable chests/buriedinloot/chests.mmsis still<namespace>:chests/buried. - Editors see the whole project. The language server loads every project file, not only the open ones, so go-to-definition, references and rename work across files. The web editor's sidebar adds, renames and deletes files, and file names can include folders, such as
recipes/crafting.mms.
The treasure and functions-advanced examples are split this way.
Values
- Object literals mirror the JSON:
{ key = value }. Fields are separated by newlines or commas. - Lists are
[a, b, c]. - Enum values are bare words:
action = show_text,color = red. They are written exactly as the game spells them; only ids getminecraft:. - Colors (fields such as
shadow_coloror a biome'swater_color) take"#RRGGBB", or"#AARRGGBB"where the color has an alpha (alpha first, so"#80FF0000"is half-transparent red). The game's own forms work too: an integer, or[r, g, b]/[r, g, b, a]with each part from 0 to 1. MMS writes a"#hex"string as the integer where the game wants one. - Ids can drop
minecraft:. A bare name such asdiamondor#gemsmeans your own declaration if one exists, otherwise the vanilla one. - Helpers build typed objects:
Pool(...)is a loot pool, andNoise(...)is{ type = noise, ... }. Every dispatched type has a helper named after its type, and arguments can be positional or named. See Writing resources and the reference.
Every value is checked against the 26.3 schema as you type. Completion offers the fields, helpers and ids that fit where the cursor is, and hover shows the field's documentation.
Formatting and lint
mms fmt (and format-on-save in the editors) prints every file in one style, so there is nothing to configure. mms check reports errors and lint findings, and mms fix applies the fixes that are always safe. mms test runs the project's Test declarations.
Next
- Writing resources: the shorthand for loot tables, recipes, density functions and more.
- Functions: variables, control flow, calls and strings in function code.
- Tutorial: a custom dimension: a complete worldgen project.
- Language reference: declarations, values, constants and templates, Blueprints, functions, text and tests, each with examples.
Importing
mms import reads a data pack folder or zip and writes one .mms file per resource folder, such as loot_table.mms, using the shorthand wherever it applies. In the browser, use Project ▾ → Import zip…, or paste one JSON file with Paste JSON as MMS….