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

III · The server

Verified against Minecraft 26.2 · Part III · The program that owns the world: one thread, one loop, twenty times a second, from the command line that starts it to the exception that ends it.

Everything a player thinks of as the world — the blocks, the mobs, the weather, the hunger bar — is state owned by one object on one thread, and this part is that thread doing a full lap. Part I named the Server thread; this is the first place you watch it work. A player recognises this part by its clock: nothing in the world happens continuously. A furnace advances in steps of a twentieth of a second, a hopper moves one item per eight of them, and when the console prints Can’t keep up! Is the server overloaded? some of those steps did not happen at all and never will.

The shape of the part

Part III is a line into a loop and out again. Two pages are the loop itself — the server tick and the one step of it that is a whole lecture — and the other three are the beginning, the population and the end.

flowchart LR
    Start["Starting a server: java -jar to the word Done"]
    Tick["The server tick: 50 ms on the Server thread"]
    Level["The level tick: one dimension advances"]
    Players["Players and sessions: who is in the loop"]
    Death["How a server dies: three endings"]
    Start -- "the Server thread is spun, the levels are built" --> Tick
    Tick -- "tickChildren calls ServerLevel.tick, overworld first" --> Level
    Level -- "the packets the tick decided to send" --> Tick
    Tick -- "the connection phase, after the levels" --> Players
    Players -- "a join, a respawn, a disconnect" --> Tick
    Tick -- "the loop's finally, which two of the three endings reach" --> Death

Before you start

Anatomy, and specifically its two loops figure. This part assumes you know that the Server thread is an event loop as well as a game loop, that a packet is decoded on a Netty thread and handled on this one, and that the client’s frame loop is a separate clock. Part II’s codecs and registries are assumed wherever something is written to disk or sent on the wire, and the resource system is assumed once, by starting a server, which runs its staged load for server data.

Two pages from a later part are assumed, and they are cut two different ways. Tickets and loading owns what entity-ticking and block-ticking range mean, and the level tick defines both in one sentence before it uses them, so that one keeps until Part IV. Environment attributes and timelines does not: it owns the per-position system whose cache ServerLevel.tick throws away before it touches anything else — before the border, before the weather — and out of which Level.updateSkyBrightness later reads the sky light rather than deriving it from the time of day. That is the one page worth watching out of order before this part; everything else in Part IV can wait.

Watch in this order

  1. The server tick — one 50 ms lap: the deadline that moves before the work starts, every packet since last time handled at once, every dimension advanced, and the two writes per client the tick leaves behind. “Can’t keep up!” is not a warning that the server is about to skip ticks — it is the skip.
  2. The level tick — one step of that lap, which is the whole world changing: weather, scheduled ticks, mob spawns, random ticks, every entity, every block entity. The block changes go out before the entities move, so a change a piston makes reaches you a tick later than one a player’s command makes — with falling sand the exception that sends its own packet, and a console command the one that is as late as the piston.
  3. Players and sessions — a join from the end of the login handshake to a player standing in a world with chunks on the way, and then the four ways that session changes: death, a dimension, a disconnect, and a debug command that sends the player back to the configuration phase. Dying replaces your player object; the Nether does not.
  4. Starting a serverjava -jar server.jar to the word Done: the EULA, the lock on session.lock, the packs and registries, the thread, the levels. The step that loads the world’s chunks loads none of them on an ordinary world.
  5. How a server dies — three endings compared: /stop, a crash in the tick loop, and the watchdog. A crash saves your world. The watchdog does not.

Reference this part uses

Threads — the Server thread, the worker pool and the dedicated server’s five side threads, with who makes each. Game rules — the rules the tick consults, which is most of them. Packets — everything the tick sends. Diagram lanes.


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