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
- 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.
- 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.
- 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.
- The execution engine — a command engine with
no Java recursion. A fan-out that materialises one player at a time, and
a
/returnthat deletes work out of a queue rather than unwinding a stack. - Functions and macros — what a
.mcfunctionfile becomes, in two steps, the second of which usually does nothing. The one that fails silently every tick, forever. - 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.
- Scores, teams and stored data — one number per
thing, one query language for any tag, and the
execute storeseam that joins them. Why fake players exist. - 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.
- 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.