Skip to content

Cells and the road to many nodes

WIP: not implemented yet or partly. Follow: #181, #351

The target is ten thousand players in one dimension

Section titled “The target is ten thousand players in one dimension”

The goal is ten thousand players in one dimension with the unmodified vanilla client.12 Nobody has published that many interacting players in one continuous space, so this is a goal and not a promise.

The tick is not what limits the number. The binding limit is how many players see each other, because a moving player costs each viewer roughly 200 to 250 bytes per second before compression. The client also drops its world on a transfer. So the plan is to spread the players over one dimension and to bound the number that each client sees.

The design rests on four ideas, and each is a small crate in the mcrs_engine_* family.

Part Crate What it does
Cell mcrs_engine_cell Owns a box of hot space. Only the owner changes the chunks in its box.
Link mcrs_engine_link Connects two parts. Messages go in and messages come out, and no part reads the state of another part.
Muxer mcrs_engine_muxer The gateway for clients. It owns the connections, decides what each client gets, and encodes a change once for all viewers of a tile.
Data layer mcrs_engine_store Holds the versioned chunks of cold space.

A cell also holds a halo, which is a copy of the columns of its neighbours within two columns. With the halo a cell never changes a column it does not own. Where the far end of a link runs is called its placement, and the placement is Inline, Thread or Remote.

Do not confuse a cell with a shard. A cell is a unit of placement, a shard is the unit of causality described in the sharding note, and one cell holds many shards.

Cells are not what makes a tick parallel, because inside one cell each domain already uses every core, as How a tick runs in parallel shows. Cells exist for balance and for placement: a cell can move to another thread, process or machine.

This list follows section 11 of docs/cells.md, “Where the code is today”, checked against the test tick_determinism.rs.

  • A world has one cell, or a static division into several. The cells of all worlds tick in lockstep, either inline or each on a thread. The server settings choose this with worlds, cells and muxer in crates/mcrs_minecraft_server_settings/src/server_settings.rs.
  • A muxer stage runs on a link from the host. The host talks to each dimension over a link, with one input and one output per tick.
  • An in-memory data layer serves cold columns, with generation and light stages on a thread.
  • A player moves to another cell at the end of the tick in which it stands in a column of that cell. There is no hysteresis yet, and no entity other than a player crosses.
  • There is no disk under the data layer, because the server does not write chunks to disk yet.3
  • Split and merge of cells by cost. The design is a k-d division on X and Z, with moves at a tick boundary and a hysteresis of about 8 blocks.
  • Placement::Remote, which means a cell in another process, together with an edge as its own process that holds every connection. This part is split into separate tasks: shards that run in parallel, and the steps of distribution from a link between processes to a coordinator.1456
  • The replication tiers for entities in docs/replication.md, which is also a design note.

All of this is optional. The design asks that a user can drop cells, the muxer and the data layer and write a server on one thread, with the game logic depending only on kernels and a world-view trait. Layers and crates explains what a kernel is.

Between that and the full layout there is a middle mode: the full engine with one cell per world and every link inline. It is deterministic, and it is the mode of the tests.

Next: Roadmap.

  1. WIP#181 The direction: one dimension on many nodes for thousands of players. ↩ ↩2 ↩3

  2. Partial#351 The decision that ten thousand players are spread over one dimension. ↩

  3. WIP#78 Tracks saving changed chunks back to region files. ↩

  4. WIP#160 Shards form, merge and split, and run in parallel. ↩

  5. WIP#162 The first distribution task: an opt-in plugin group behind a link trait. ↩

  6. WIP#167 The last distribution task: a coordinator with an ownership map and load balancing. ↩

Sources and verification

Verified: 26.4-snapshot-7, 51d45c26a, 2026-11-09

Tracking: #181, #351