Skip to content

Server World Configuration

SteelMC world configuration is done through a TOML file located at config/worlds.toml. This page documents all world, domain, world generator and storage options.

OptionTypeDefaultDescription
save_pathString"saves"Root directory for saved worlds
seedString""World generation seed (empty = random)
default_gamemodeString"survival"Default gamemode for new player data
difficultyString"normal"Difficulty for new level data
storage.typeIdentifier"steel:disk"Default world storage backend
player_storage.typeIdentifier"steel:file"Player data storage backend

The values seed, default_gamemode, difficulty and storage are inherited from root to domains and from domains to worlds. They can also be overridden in each place, which gives the server flexible configuration.

Valid gamemodes are survival, creative, adventure and spectator. Valid difficulties are peaceful, easy, normal and hard.

Unfortunately, Mojang is not consistent about using the same terms in their codebase. World, level and map can describe the same thing internally. Steel also adds some Multiverse functionality natively. To describe this clearly, Steel introduced a new term: domains. The glossary also covers dimension and world generator, which are used below.

At least one domain is needed, and exactly one domain needs to be the default.

[domains.minecraft]
default = true
seed = "example seed"
default_gamemode = "survival"
storage.type = "steel:disk"
OptionTypeDefaultDescription
domains.<domain>.worldsArrayNone[REQUIRED] Worlds inside this domain
domains.<domain>.defaultboolfalseWhether this is the default domain
domains.<domain>.seedStringinheritedDomain seed override
domains.<domain>.default_gamemodeStringinheritedDomain gamemode override
domains.<domain>.difficultyStringinheritedDomain difficulty override
domains.<domain>.storageTableinheritedDomain storage override

The domain name must be a valid identifier namespace. global is reserved and cannot be used.

Each domain needs at least one world and exactly one default world.

[[domains.minecraft.worlds]]
name = "overworld"
generator = "minecraft:overworld"
default = true
storage.type = "steel:ram"
OptionTypeDefaultDescription
nameStringNone[REQUIRED] Name of the world inside the domain
generatorIdentifierNone[REQUIRED] World generator to use, options of world generator are in the next section
defaultboolfalseWhether this is the default world of the domain
seedStringinheritedWorld seed override
default_gamemodeStringinheritedWorld gamemode override
difficultyStringinheritedWorld difficulty override
storageTableinheritedWorld storage override
configTable{}Generator-specific config

World names must be valid identifier paths, cannot contain / and must be unique within the domain. The names overworld, the_nether and the_end are special cases used to connect portals (Nether portals and End portals). This allows a single-player playstyle to be created for each player with all three dimensions, so it feels like vanilla single-player.

Steel has these built-in world generators:

GeneratorConfig
minecraft:overworldNo config table accepted
minecraft:the_netherNo config table accepted
minecraft:the_endNo config table accepted
minecraft:flatOptional flat-world config
steel:emptyRequires config.dimension_type

The generators minecraft:overworld, minecraft:the_nether and minecraft:the_end have no config. They produce vanilla-parity worlds for their dimensions.

The world generator minecraft:flat accepts an optional config table. Without it, Steel uses the Overworld dimension, a vanilla-style superflat layer stack and the default structure overrides.

OptionTypeDefaultDescription
layers[].blockIdentifierNone[REQUIRED] Block used by this layer
layers[].heightIntegerNone[REQUIRED] Height of this layer, must be greater than 0
dimension_typeIdentifier"minecraft:overworld"Dimension type used by the flat world
layersArray of layer tablesbedrock 1, dirt 2, grass block 1Blocks generated from bottom to top
featuresBooleanfalseWhether to generate decoration features. true is not implemented yet
lakesBooleanfalseWhether to generate lakes. true is not implemented yet
structure_overridesIdentifier arraystrongholds and villagesStructures allowed in this flat world

The default layers are minecraft:bedrock with height 1, minecraft:dirt with height 2 and minecraft:grass_block with height 1. The default structure_overrides are minecraft:strongholds and minecraft:villages.

Custom layers can be written with repeated layer tables or inline layer tables.

[domains.dev]
default = true
[[domains.dev.worlds]]
name = "flat"
generator = "minecraft:flat"
default = true
[domains.dev.worlds.config]
features = false
lakes = false
structure_overrides = ["minecraft:villages"]
[[domains.dev.worlds.config.layers]]
block = "minecraft:bedrock"
height = 1
[[domains.dev.worlds.config.layers]]
block = "minecraft:grass_block"
height = 3
[domains.flat]
default = true
[[domains.flat.worlds]]
name = "overworld"
generator = "minecraft:flat"
default = true
[[domains.flat.worlds]]
name = "the_nether"
generator = "minecraft:flat"
config.dimension_type = "minecraft:the_nether"
config.layers = [
{ block = "minecraft:bedrock", height = 1 },
{ block = "minecraft:blackstone", height = 2 },
{ block = "minecraft:netherrack", height = 1 }
]
[[domains.flat.worlds]]
name = "the_end"
generator = "minecraft:flat"
config.dimension_type = "minecraft:the_end"
config.layers = [
{ block = "minecraft:bedrock", height = 1 },
{ block = "minecraft:end_stone", height = 3 }
]

The important part of an empty world generator is the config, which defines dimension_type. That field selects the dimension and its properties, such as Y height and fog.

[domains.empty]
default = true
storage.type = "steel:ram"
[[domains.empty.worlds]]
name = "void"
generator = "steel:empty"
default = true
[domains.empty.worlds.config]
dimension_type = "minecraft:overworld"

Steel has these built-in world storage backends. Storage can be set for the full server, per domain and per world. For example, the full server can use RAM storage, one domain can still use disk storage and be saved to disk, and a world in that domain can still use RAM storage. This gives maximum flexibility to configure storage as needed.

StorageConfig
steel:diskOptional config.path, relative to save_path
steel:ramNo config, chunks are not saved

Player storage currently only supports steel:file.

Example disk path override:

[[domains.minecraft.worlds]]
name = "testing"
generator = "minecraft:overworld"
[domains.minecraft.worlds.storage]
type = "steel:disk"
[domains.minecraft.worlds.storage.config]
path = "custom/testing"

This section first shows the default config generated on first start. The second config uses the concepts above to construct a setup with three domains, different gamemodes, storage settings and world generator config.

This is the default config for worlds.toml, which creates a normal survival world.

/config/worlds.toml
# Root defaults inherited by domains and worlds unless overridden.
save_path = "saves"
seed = "my_awesome_seed"
default_gamemode = "survival"
difficulty = "normal"
[storage]
type = "steel:disk"
[player_storage]
type = "steel:file"
[domains.minecraft]
default = true
[[domains.minecraft.worlds]]
name = "overworld"
generator = "minecraft:overworld"
default = true
[[domains.minecraft.worlds]]
name = "the_nether"
generator = "minecraft:the_nether"
[[domains.minecraft.worlds]]
name = "the_end"
generator = "minecraft:the_end"

This has many different settings, which are explained above. Currently, the minecraft domain is on disk, as is the world the_nether from the flat domain. The empty and minecraft domains use survival gamemode, while the flat domain uses creative gamemode.

save_path = "saves"
seed = ""
default_gamemode = "survival"
difficulty = "normal"
[storage]
type = "steel:disk"
[player_storage]
type = "steel:file"
[domains.minecraft]
default = true
[[domains.minecraft.worlds]]
name = "overworld"
generator = "minecraft:overworld"
default = true
[[domains.minecraft.worlds]]
name = "the_nether"
generator = "minecraft:the_nether"
[[domains.minecraft.worlds]]
name = "the_end"
generator = "minecraft:the_end"
[domains.flat]
default_gamemode = "creative"
storage.type = "steel:ram"
[[domains.flat.worlds]]
name = "overworld"
generator = "minecraft:flat"
default = true
[[domains.flat.worlds]]
name = "the_nether"
generator = "minecraft:flat"
config.dimension_type = "minecraft:the_nether"
config.layers = [
{ block = "minecraft:bedrock", height = 1 },
{ block = "minecraft:blackstone", height = 2 },
{ block = "minecraft:netherrack", height = 1 }
]
storage.type = "steel:disk"
[[domains.flat.worlds]]
name = "the_end"
generator = "minecraft:flat"
config.dimension_type = "minecraft:the_end"
config.layers = [
{ block = "minecraft:bedrock", height = 1 },
{ block = "minecraft:end_stone", height = 3 }
]
[domains.empty]
default = false
storage.type = "steel:ram"
[[domains.empty.worlds]]
name = "empty"
default = true
generator = "steel:empty"
[domains.empty.worlds.config]
dimension_type = "minecraft:overworld"

The server validates world configuration on startup:

  • unknown fields are rejected
  • at least one domain must be declared
  • exactly one domain must set default = true
  • each domain must declare at least one world
  • each domain must have exactly one default world
  • domain names must be valid identifier namespaces
  • the domain name global is reserved
  • world names must be valid identifier paths and cannot contain /
  • save_path and storage paths must be clean relative paths
  • generators and storage backends must be known to Steel

If validation fails, the server will exit with an error message.