Running a server
World generation
On this page
The server makes its own world the first time it starts, and generates new terrain as players
explore it, the same way the game does. Out of the box this needs no settings: an empty server
folder gets a fresh world from server.properties, and every chunk nobody has visited yet is
generated from the world's seed when somebody first comes near it.
This page covers how a new world is made, the settings that change generation, and how to build a world ahead of time (pre-generation) so players never wait on new terrain.
How a new world is made
When the server starts and there is no world in the folder level-name names (world by
default), it makes one before it opens the port, from these server.properties keys:
| Key | Default | What it decides |
|---|---|---|
level-name | world | The folder the world lives in, beside server.properties |
level-seed | empty | The seed. A whole number is used as it is; any other text is turned into a number the way the game does it, so a word seed gives the same world it would in the game; empty picks one at random |
level-type | minecraft:normal | The kind of overworld: minecraft:normal, minecraft:flat, minecraft:large_biomes, minecraft:amplified, minecraft:single_biome_surface or minecraft:debug_all_block_states. The old names default and largebiomes work too. Anything else logs a warning and makes a normal world |
generator-settings | {} | For a flat world only: its layers, biome and structures, as the game's flat-world JSON. Settings that cannot be read give the game's default flat world |
generate-structures | true | Whether villages, temples, strongholds and other structures are placed |
initial-enabled-packs | vanilla | The datapacks the new world starts with |
initial-disabled-packs | empty | Built-in packs to leave off |
The server then finds a spawn point as the game does, which generates and saves the few chunks
around it, and logs made a new world at <folder>, spawn (x, y, z).
These keys are read only when a world is made. Changing level-seed or level-type later does
nothing to the world that exists; to get a different world, stop the server and move the old world
folder away (or use a world reset, below).
When you start the server for the first time at a terminal with no server.properties, it asks a
few questions, the seed among them. Press Enter to leave the seed empty for a random one.
Turning generation on and off
Generation is on by default. Settings live in rustmc.yml, beside server.properties:
worldgen:
# Whether a chunk that is not on disk is generated from the world's seed. false leaves
# unexplored chunks empty (the same as the --no-generate flag).
generate-chunks: true
# The generator plugin new chunks are made with, by name: which version of the game's world
# generation shapes terrain, biomes, decoration and structures. `null` is the newest compiled
# into this build, the version this server speaks. --generator on the command line overrides it.
# A name this build does not have stops the server at startup with the list of names it does.
# Chunks already saved are never regenerated.
generator: null
With generate-chunks: false (or the --no-generate flag) the server serves the world exactly as
it is on disk: anything past what has been explored is empty, and nothing new is ever added. Use it
for a finished map, or for a world you have pre-generated to its border. With generation off:
- A missing world is not made. The server stops at startup, saying there is no world there.
- A world reset that a plugin asked for is not carried out.
- In-game pre-generation is refused.
Choosing a generator
worldgen.generator picks which version of the game's world generation shapes new chunks. A
standard build has two:
| Name | Terrain of |
|---|---|
vanilla-26.2 | Minecraft 26.2 |
vanilla-26.3 | Minecraft 26.3, the version this server speaks |
null means the newest one in the build. Some builds made for a particular gamemode carry that
gamemode's own map generator as well (for example rusty-island); those are never the default. If
you name a generator the build does not have, the server stops at startup and lists the names it
does have. The --generator <name> flag overrides the file.
Pin the generator if you care about seams. The choice is not stored in the world. Chunks
already saved stay as they are forever, and only new chunks use the generator you have now. If you
leave it at null and later update to a build whose newest generator is a later game version, new
terrain is generated by that version, and you may see a seam where old chunks meet new ones. Setting
generator: vanilla-26.3 keeps every new chunk on the same version until you decide to change it.
The chunk settings
These only change how hard the server works and how much memory it keeps. They never change what a chunk looks like.
chunks:
# Threads that may build chunks at once. null asks the machine (its available parallelism, at
# most 16). The --builders flag wins over this.
builders: null
# Memory for encoded chunk packets kept for reuse, in MiB.
chunk-cache-mib: 128
# Memory for region-file data kept in memory, in MiB.
region-cache-mib: 64
# Memory for decoded chunk columns kept to be read again, in MiB. Nothing depends on a column
# staying here: one that falls out is read back from its region file.
column-cache-mib: 16
| Key | Default | Meaning |
|---|---|---|
chunks.builders | null | Threads that may generate chunks at once. null uses the number of cores the machine reports, at most 16. A number you set is used as given, from 1 to 64 |
chunks.chunk-cache-mib | 128 | Memory for chunk data already prepared for sending, kept so the next player who needs it gets it without the work being done again |
chunks.region-cache-mib | 64 | Memory for world-file data read from disk |
chunks.column-cache-mib | 16 | Memory for chunks read from disk and kept in case they are read again |
Set builders yourself if you limit the server's cores. On Windows, a server pinned to a few
cores with a processor affinity setting still sees every core in the machine, so it would start more
builder threads than it can run. Set builders to the number of cores you gave it.
Pre-generation
Generating terrain is the most expensive thing the server does. A handful of players exploring in different directions can keep every core busy, and anyone walking into new land waits for it to appear. Pre-generation builds the world ahead of time, so exploring only reads chunks from disk. There are two ways to do it.
While the server runs: the Chunky plugin
The Chunky plugin from the rustmc plugin suite pre-generates a square or circle of any world while the server is running, without slowing play down. The server builds the chunks on threads of its own, away from the game tick, and writes each one to disk before counting it done. The plugin slows down whenever the server is busy, and a task picks up where it left off after a restart.
/chunky start overworld circle 0 0 5000
/chunky progress
The commands need operator level 3. The server's side of it:
- At most half of the server's chunk builders work on pre-generation (at least one, at most eight), so players' own views always have builders free.
- A world the server does not write (a read-only server) cannot be pre-generated, and neither can
one with
generate-chunks: false. - While saving is off (
/save-off), pre-generation pauses: nothing new is built, and what was already built waits until saving is back on. - Nothing beyond the game's world edge, 30 million blocks out, is built.
Offline: the pregenerate program
pregenerate is a separate program, built along with the server: cargo build --release -p rustmc-server puts it beside rustmc-server. It builds a square of one dimension as fast as the
machine allows, and also prepares each chunk's network data so the server can send it to players
without building it first. It is the right tool for a big world before launch, and it is a job of
hours, not minutes: one measured run built about 277,000 chunks in just under six hours.
pregenerate <world folder> <radius in blocks> [--threads N] [--generator NAME]
[--dimension overworld|the_nether|the_end] [--no-packets]
[--compression N | --no-compression]
To use it:
-
Start the server once so it makes the world, then stop it.
pregeneratereads the seed from the world, so it cannot start from an empty folder; it fails with "this world cannot generate". -
With the server stopped, run it against the world folder. The radius is in blocks from 0, 0 (not from spawn) and covers a square, the same shape a world border has:
pregenerate world 5000 --generator vanilla-26.3It prints a line as each region file is finished, with the rate and the time left.
-
Repeat with
--dimension the_netherand--dimension the_endif you want those built too. The overworld is the default. -
Start the server.
| Option | Default | Meaning |
|---|---|---|
--threads N | every core | Worker threads. Each works on its own region file |
--generator NAME | the newest in the build | Which generator builds the chunks. It does not read rustmc.yml, so pass the same name as your worldgen.generator |
--dimension | overworld | Which dimension to build |
--no-packets | off | Build terrain only, and skip the prepared network data |
--compression N | 256 | The compression threshold the prepared data is made for |
--no-compression | off | Prepare the data uncompressed |
An interrupted run is resumed by running the same command again: chunks already on disk are skipped. The program exits with an error if any region failed, and lists up to ten of them.
The prepared data must match the server. It is made for one compression threshold. If your
server.properties sets network-compression-threshold to something other than 256, pass the same
number with --compression, or --no-compression if it is negative. Data made for another
threshold is not used: the server simply builds those chunks' network data itself, so you lose the
speed but nothing breaks.
How natural changes are controlled
Grass and mycelium spreading, mushrooms spreading, crops growing, snow and ice melting, water
freezing and snow settling all happen on the game's random ticks, near players. There is no
rustmc.yml setting for them; they follow the game's own rules:
| Game rule | Default | Effect |
|---|---|---|
random_tick_speed | 3 | How many random ticks each section of a chunk gets per tick. 0 stops all of these changes, snow and freezing included; higher values speed them up |
spread_vines | true | Whether vines grow |
max_snow_accumulation_height | 1 | How many layers of snow can build up while it snows, from 0 to 8 |
Set them with /gamerule, for example /gamerule random_tick_speed 0. How far from players this
happens follows the simulation distance: simulation-distance in server.properties, or
worlds.<dimension>.simulation-distance in rustmc.yml for one world. Plugins can also stop
these changes in places they protect, such as claimed land.
Resetting the world
A gamemode with wipes can ask for the world to be made fresh on the next start. This is off until you allow it:
world-reset:
# Lets a plugin have the world reset the next time the server starts (the schedule_world_reset
# host call, for a gamemode with wipes): before the world opens, its directory is renamed aside
# with the time in its name and a fresh world is made with a new seed. Nothing is deleted, but
# everything in the world -- builds, player inventories, the End -- starts again. Off, the call
# is refused, and a reset already asked for is left undone and said so at every start.
allow-plugins: false
When a reset happens, the old world folder is renamed to <world>-reset-<yyyymmdd>-<hhmmss> beside
it, and a new world is made with the seed the plugin asked for, or a random one. It never reuses
level-seed, which would make the same world again. Delete the old folder yourself once you are
sure you do not need it. Restarting covers how a
reset is asked for and how to take one back.
To start over by hand, stop the server and move or delete the world folder. The next start makes a
new one from server.properties.
Limits
- Generation follows the chosen generator's version of the game. Chunks saved earlier are never regenerated, by any setting.
pregeneratedoes not read the world's datapacks. If datapacks change your world's terrain, pre-generate with the Chunky plugin instead, which uses the running server.pregeneratebuilds a square around 0, 0. For a circle, or another centre, use Chunky.- A world with anti-xray on does not use the prepared network data, so
--no-packetssaves disk there at no cost. - The prepared network data roughly doubles a world's size on disk. Backups leave it out, because the server can make it again.
Security
- Allowing world resets lets a plugin end the world the next time the server starts. Only allow it for a gamemode that is meant to wipe. The old world is kept, not deleted, so a reset can be undone by moving the folders back.
/chunkyneeds operator level 3, because a large task uses disk and CPU for hours.- Run
pregenerateonly while the server is stopped. The two would otherwise write the same world files.
From docs/world-generation.md in the RustMC repository at bbd81209ad.