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
nether_portal_targetStringautomaticSame-domain world name used by Nether portals from this world
end_portal_targetStringautomaticSame-domain End-dimension world name used by End portals from non-End worlds
configTable{}Generator-specific config

World names must be valid identifier paths, cannot contain / and must be unique within the domain.

Portals are resolved inside the source world’s domain. If no explicit target is configured, Steel uses vanilla conventional world names:

  • Nether portals from the_nether target overworld
  • Nether portals from any other world target the_nether
  • End portals from non-End worlds target the_end
  • End portal returns from End-dimension worlds use the entity or player’s respawn data instead of end_portal_target

The conventional names make a normal overworld, the_nether, and the_end setup work without extra config. If you use different world names, configure explicit targets.

[domains.minecraft]
default = true
[[domains.minecraft.worlds]]
name = "overworld2"
generator = "minecraft:overworld"
default = true
nether_portal_target = "the_nether2"
end_portal_target = "the_end2"
[[domains.minecraft.worlds]]
name = "the_nether2"
generator = "minecraft:the_nether"
nether_portal_target = "overworld2"
[[domains.minecraft.worlds]]
name = "the_end2"
generator = "minecraft:the_end"

Portal target fields take a world name, not a full namespace:path identifier. They cannot point across domains, cannot point to the same world, and must point to a declared world in the same domain. end_portal_target is invalid on worlds using the End dimension, and it must point to a world whose generator uses the End dimension.

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 = ""
default_gamemode = "survival"
difficulty = "normal"
[storage]
type = "steel:disk"
[player_storage]
type = "steel:file"
[domains.minecraft]
default = true
# Worlds may optionally set same-domain `nether_portal_target` and
# `end_portal_target` fields to override the vanilla conventional names.
[[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
  • nether_portal_target and end_portal_target must point to an existing same-domain world and cannot target the source world
  • end_portal_target cannot be set on End-dimension worlds
  • end_portal_target must target an End-dimension world
  • minecraft:flat requires at least one layer, and features = true or lakes = true are not implemented yet

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

SteelMC logo by colonthreeing.