Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

XIII · Commands and data packs

Verified against Minecraft 26.2 · Part XIII · a string typed into a chat box becomes a call with typed arguments, on a queue, with a permission attached — and four whole systems are built on top of that and nothing else.

Type a slash. The text turns grey and green and red as you type, a hint appears behind the cursor, and pressing Enter sends the string — the parse the client just did is thrown away. On the server the same string is parsed again, against a tree whose nodes carry permission requirements, and becomes a piece of work on a queue rather than a Java call. Everything else in this part rides that machinery: an advancement is a subscription delivered by a trigger and edited by /advancement, a scoreboard is a number written by /scoreboard or by execute store, a dialog is a data-pack form opened by /dialog, and a game test is a data-pack test run by /test. None of those four needs any of the others. What they need is the parse and the queue, and a reader who has those two can explain any of the four from them.

Counting the nine packages the atlas lists for this part, the way it counts everything else, that is 470 classes and 43,126 lines — of which the command catalogue alone (net/minecraft/server/commands) is 102 classes and 12,800 lines, each of them a thin lambda over machinery some other part of this book owns. So what a command does once dispatched is almost always another part’s page, and Brigadier and commands carries the list of which; the statistics, which are criteria, are in what this book skips.

The shape of the part

Part XIII is a stack of three floors, and for a watcher the dependency runs one way: all four systems on the top floor need both of the floors below, and none of them needs another. The code is less tidy than the lecture order — a selector’s advancements= and scores= options reach straight up into two of the top-floor systems — but nothing on the top floor reaches sideways.

flowchart TB
    subgraph P["PARSE — a string becomes a call"]
        direction LR
        L1["1 · Brigadier and commands"] --- L2["2 · Permissions"] --- L2b["3 · Entity selectors"]
    end
    P --> X
    subgraph X["EXECUTE — the call becomes work on a queue"]
        direction LR
        L3["4 · The execution engine"] --- L4["5 · Functions and macros"]
    end
    X --> U
    subgraph U["WHAT COMMANDS ARE FOR — four systems whose write surface is a command"]
        direction LR
        L5["6 · Advancements"]
        L6["7 · Scores, teams and stored data"]
        L7["8 · Dialogs"]
        L8["9 · Game tests"]
    end

The four pages on the top floor are peers, not a sequence: watch them in any order, or only the ones you care about. The two floors below them are not optional for any of the four.

Before you start

The server tick from Part III, because when turns out to matter twice: command functions run near the top of MinecraftServer.tickChildren, before any level ticks, and the connection phase — where ServerGamePacketListenerImpl.tick calls ServerPlayer.doTick — runs after the levels, which is what puts a periodic advancement trigger one tick behind the packet that should have carried it.

Codecs, NBT and JSON and the data-driven type pattern from Part II. Dialogs and game tests are the pattern’s clearest two instances — a form and a test suite, both reduced to JSON dispatching on a registry of types — and the pattern page is where that argument is made.

The connection from Part IX, for the Netty-thread / server-thread boundary that the command packets cross in two different ways on purpose.

Contexts and predicates from Part VII, if you are here for advancements: a trigger’s conditions are loot conditions, evaluated against a loot context, and that page owns the machine.

Watch in this order

  1. Brigadier and commands — three parsers for one string, and a tab-completion whose fast path never leaves the machine. Also: which sixty-two of the four hundred and fifty-nine argument nodes do leave it, and why they feel like all of them.
  2. Permissions — the biggest API break in the game since the flattening. A permission is no longer an integer, an operator does not have everything, and a permission failure is reported as a typo.
  3. Entity selectors — a selector is a compiled query, and eight of its twenty-one options are not filters but the query plan. Why @p crosses dimensions, why sort=nearest is what takes your limit away, and why one permission is checked twice.
  4. The execution engine — a command engine with no Java recursion. A fan-out that materialises one player at a time, and a /return that deletes work out of a queue rather than unwinding a stack.
  5. Functions and macros — what a .mcfunction file becomes, in two steps, the second of which usually does nothing. The one that fails silently every tick, forever.
  6. Advancements — the game’s general-purpose “tell me when the player does X”, built as a per-player subscription table that shrinks as criteria are met and is rebuilt when one is revoked. The tree is laid out on the server and shipped.
  7. Scores, teams and stored data — one number per thing, one query language for any tag, and the execute store seam that joins them. Why fake players exist.
  8. Dialogs — a data pack puts a form on your screen, possibly before you are in a world at all. The values are read at the moment of the click and not before.
  9. Game tests — the game’s own test suite, as a data pack. The annotations are gone, a batch is an environment, and the shipped jar contains exactly one test.

Reference this part uses

Packets for this part’s own traffic, which is almost all server → client: the scoreboard has five packets and no serverbound counterpart at all. Registries and the data-driven type pattern for the six type registries dialogs and tests dispatch on. Loot context parameter sets for the sets an advancement trigger and an advancement reward run in. Diagram lanes for the abbreviations these figures use, and the glossary for Brigadier, selector head, world-limited, criterion, objective, macro, dialog and game test.


Rules: names, never code · how the system works, not how the code reads · newest version only · every backticked name passes tools/verify_names.py.