Chapter 44 — Custom Dimensions
What You’ll Build
Way back in Chapter 7, when we listed everything a data pack can configure, one item came with a
promise attached: dimensions. You already know dimensions from playing: the Overworld you spawn
in, the Nether you reach through a portal, the End where the dragon waits. Each one is its own
separate space with its own sky, its own height, its own rules. Chapter 27 even let you reach across
them with execute in. What Chapter 7 promised, and what this chapter delivers, is that a data pack
can add a brand-new dimension of your own: a separate world that didn’t exist before you wrote
a couple of JSON files.
By the end of this chapter you’ll have built a flat void arena in the mypack pack you started
back in Chapter 9: a private, empty, perfectly flat dimension that’s good for a minigame. Players
teleport in, the match happens on a clean slate, and nothing from the Overworld is in the way. You’ll
do it with exactly two files: a dimension type (the physical rules of the space) and a
dimension definition (which links that type to a generator that decides what blocks fill the
world). Then you’ll travel into it with execute in, and as practice you’ll build a second dimension
made of thin floating slabs: a sky world.
Figure (to be captured). a player standing in an empty flat void dimension, flat ground stretching out under a plain sky
Heads up before you start — this dimension needs a reboot, not
/reload. Dimensions live in a dynamic registry (Chapter 7’s word for a registry data packs are allowed to add to). You learned the rule for these back with biomes in Chapter 42: the game only reads dynamic-registry files when a world loads. So after you write these files,/reloadwill not make the new dimension appear. You have to leave the world and open it again. We’ll repeat this at the moment it matters, but keep it in mind so you’re not confused when/reloadseems to do nothing.
What a dimension really is
Here’s the plain definition:
“Dimensions are parallel worlds within a Minecraft world characterized by a way of generation, biomes and structures, and other things unique to one dimension. Each dimension is its own separate 3D space, not affecting other dimensions.”
That last sentence is the key idea for this chapter. A dimension is a separate 3D space, a whole independent block world. Blocks you place in the Nether don’t show up in the Overworld; they’re different spaces that happen to belong to the same saved world. The Overworld, the Nether, and the End are just the three dimensions the game ships with.
And here’s the promise being kept. As the wiki puts it, under “Custom dimensions”:
“Using data packs, it is possible to create custom dimensions and dimension types that have different biomes, world generation and properties from the regular dimensions. (Java Edition only)”
So a data pack can hand the game a new separate space, with its own biomes, its own way of generating terrain, and its own properties like height and lighting. That “(Java Edition only)” note matters: everything in this chapter is a Java Edition feature.
The two files: type and definition
Making a dimension takes two JSON files, and it’s worth being clear from the start about which does what, because the names are similar:
-
A dimension type describes the physical rules of a space: how tall it is, whether it has a sky, how bright the ambient light is, whether time is frozen. Dimension types “define properties of a dimension such as world height build limits, the ambient light, and more.” These files live in the folder
data/<namespace>/dimension_type(note the singular folder name), the same rule you’ve followed since Chapter 9. -
A dimension definition (or just “dimension file”) is the file that creates an actual dimension by pointing at a type and attaching a generator. Dimensions are stored as JSON files within a data pack, at the path
data/<namespace>/dimension/<name>.json. Singular folder again:dimension.
Think of it like a recipe and a finished dish. The dimension type is a reusable description of what
kind of space this is; the dimension definition is the one specific world that uses it and decides
what’s in it. You can have one type and reuse it for several dimensions, the same way the game’s
overworld type is shared.
We’ll write the type first, because the definition refers to it.
The dimension type file
A dimension type is a single JSON object. Here is the whole list of fields it can hold, so you know what each one means before we write the file:
coordinate_scale(number) — “The multiplier applied to coordinates when leaving the dimension.” The Nether’s is 8, which is why one Nether block equals eight Overworld blocks (you met that 8:1 ratio in Chapter 27). Must be between0.00001and30000000.0.has_skylight(true/false) — “Whether the dimension has skylight or not. If set to false, weather is additionally disabled.”has_ceiling(true/false) — “Whether the dimension has a bedrock ceiling,” the way the Nether does. This changes how respawn and mob spawning are calculated.has_ender_dragon_fight(true/false) — “Whether this dimension can have an ender dragon fight.” Leave thisfalseunless you want End-style dragon machinery.ambient_light(number) — “How much light the dimension has. When set to 0, it completely follows the light level; when set to 1, there is no ambient lighting.” In plain terms:0.0means it gets properly dark at night like the Overworld; higher values keep a baseline glow everywhere.has_fixed_time(true/false, optional, defaults tofalse) — “Whether this dimension has fixed time.” With this on, the sun never moves.monster_spawn_block_light_limit(whole number 0–15) — “Block light level must be less than or equal to this value for monsters to spawn.”monster_spawn_light_level(0–15, or an int provider) — sets the spawn-light formula; a plain whole number is the simple form.logical_height(whole number) — “The maximum height to which chorus fruits and Nether portals can bring players within this dimension.” Can’t be greater thanheight.min_y(whole number) — “The minimum height in which blocks can exist within this dimension. Must be between -2032 and 2031 and be a multiple of 16.”height(whole number) — “The total height in which blocks can exist within this dimension. Must be between 16 and 4064 and be a multiple of 16.” (So the highest place you can put a block ismin_y + height - 1.)infiniburn(string) — “A block tag with#. Fires on these blocks burns infinitely.” The Overworld uses the block tag#minecraft:infiniburn_overworld.skybox(string, optional, defaults tooverworld) — “The skybox to use. Can benone,overworld, orend.”cardinal_light(string, optional, defaults todefault) — “Direction of cardinal light affecting blocks. Can bedefaultornether.”default_clock(string, optional) — which world clock the/timecommand uses here.
Under the Hood —
min_yandheightare about block space, not difficulty (skippable). These two are the most important fields to get right, and they trip people up because they interact.min_yis the floor (the lowest Y a block can exist at), andheightis how many blocks of vertical room there are above that floor. The Overworld usesmin_yof -64 andheightof 384, so blocks can exist from Y=-64 up to Y=319. Both numbers must be multiples of 16: pickmin_yandheightfrom the 16-times-table (…-64, -48, -32, -16, 0, 16, 32…) or the game will reject the file.
For the arena we want a small, well-behaved space: a normal sky so players can see, light that gets dark normally, no ceiling, and a modest height range. Here’s the file. Every field name is copied from the list above.
data/mypack/dimension_type/arena.json
{
"ultrawarm": false,
"natural": true,
"coordinate_scale": 1.0,
"has_skylight": true,
"has_ceiling": false,
"has_ender_dragon_fight": false,
"ambient_light": 0.0,
"piglin_safe": false,
"bed_works": true,
"respawn_anchor_works": false,
"has_raids": true,
"logical_height": 256,
"infiniburn": "#minecraft:infiniburn_overworld",
"effects": "minecraft:overworld",
"min_y": -64,
"height": 320,
"monster_spawn_block_light_limit": 0,
"monster_spawn_light_level": 7
}
Where these values come from. The field list above covers the definitions (
coordinate_scale,has_skylight,has_ceiling,has_ender_dragon_fight,ambient_light,has_fixed_time, the twomonster_spawn_*fields,logical_height,min_y,height,infiniburn,skybox,cardinal_light, anddefault_clock). On top of those, each of the three vanilla dimensions (and the Overworld Caves preset) ships with a concrete set of values, and that’s where the extra fields above come from:ultrawarm,natural,piglin_safe,respawn_anchor_works,bed_works, andhas_raids, each true or false per dimension, plus the Overworld’sinfiniburntag (infiniburn_overworld) and itseffects(minecraft:overworld). Every value in the file above is simply the Overworld’s own settings, written out as JSON: itsambient_lightis0.0, itslogical_heightis256, and itscoordinate_scaleis1.0. Tweakheight/min_yto taste within the limits below.
Read down the values: a 1:1 coordinate scale (no Nether-style scaling), a real sky (has_skylight
true), no ceiling, light that fully follows the normal day/night cycle (ambient_light 0.0), a
build range from Y=-64 up to Y=255 (min_y -64 plus height 320, both multiples of 16), and an
infiniburn block tag (the value shown is the Overworld’s). The two monster_spawn fields are set
low so the arena stays calm. That’s a complete, sky-lit, flat-friendly space.
The dimension definition file
Now the file that actually makes the dimension exist. The root object has just two parts:
“
type: dimension type. Can be presetoverworld,the_nether,the_end,overworld_caves, or a custom dimension type”, and “generator: Generation settings used for that dimension.”
So type is the identifier of a dimension type (either a built-in one or the custom one you just
wrote), and generator is a nested object describing how to fill the world with blocks. The
generator has its own type, which is “One of noise, flat, or debug”. Here is what each one does:
noise— “The generator used in all the default dimensions.” This builds real, varied terrain from noise. It’s how the Overworld and Nether are made. It’s complicated, and we’ll describe its shape later in this chapter but save the deep machinery for Chapter 45.flat— “The generator type used for superflat worlds.” Flat layers of your choosing. This is what we’ll use for the arena, because a void is just the simplest possible flat world.debug— a special grid-of-every-block generator with “no additional fields”; not something you’d ship in a real pack.
We want flat. The flat generator takes one extra field, settings, holding the “Superflat settings.”
So what do superflat settings look like? Here’s a complete, real example (it’s the server-config form,
but the JSON shape is the same one the generator uses):
{"biome":"minecraft:plains","layers":[{"block":"minecraft:bedrock","height":1},{"block":"minecraft:dirt","height":2},{"block":"minecraft:grass_block","height":1}]}
That tells us the three field names we need: a biome for the whole world,
and a layers list where each layer is an object with a block and a height. Here’s what they
mean: layers is “interpreted from top to bottom, starting at world bottom”
(so the first layer is the lowest), each layer’s height is “the height of this layer,” and block
is “the block ID.”
A void is the simplest layer list there is. The Superflat page lists a built-in preset called “The Void” whose entire contents are: “Air x1.” So a void dimension is a flat world whose only layer is a single layer of air. Here’s the arena:
data/mypack/dimension/arena.json
{
"type": "mypack:arena",
"generator": {
"type": "minecraft:flat",
"settings": {
"biome": "minecraft:the_void",
"layers": [
{
"block": "minecraft:air",
"height": 1
}
]
}
}
}
Look at how the two files connect. The definition’s "type": "mypack:arena" is the identifier of the
dimension type file you wrote a moment ago: data/mypack/dimension_type/arena.json becomes the ID
mypack:arena, exactly the namespace-and-path naming you’ve used since Chapter 8. The generator is
minecraft:flat, and its settings say: one layer, one block tall, made of air, over the
minecraft:the_void biome. That’s an empty world. The file itself sits at
data/mypack/dimension/arena.json, so the new dimension’s own identifier is mypack:arena too: a
dimension file’s ID and the dimension it makes share a name.
Try It! — give the arena a floor. An all-air void means players fall forever, which is great if your minigame teleports them to a built platform but awkward otherwise. To give the whole dimension a solid floor, change the
layerslist to two layers (bedrock then air), like the void preset with a base:"layers": [ { "block": "minecraft:bedrock", "height": 1 }, { "block": "minecraft:air", "height": 64 } ]Remember layers go bottom-up, so the bedrock is the floor and the 64 layers of air sit on top of it.
Loading it: reboot, then travel in
This is the moment the warning from the start of the chapter pays off. You’ve written both files.
Your instinct, after every chapter so far, is to run /reload. Don’t expect it to work here. As
you learned with biomes in Chapter 42, dimensions are a dynamic registry, and the rule for
those is that the game reads them only when a world loads. So:
- Save both files.
- Quit to the title screen (leave the world entirely).
- Open the world again.
Now mypack:arena exists. To go there, you use the command Chapter 27 introduced: execute in <dimension>. Back then you used it to reach the Nether; it works for any loaded dimension,
including yours. We’ll wrap it in a function so it’s easy to run again.
data/mypack/function/goto_arena.mcfunction
execute in mypack:arena run tp @s 0 65 0
Running this function teleports you into the mypack:arena dimension and drops you at coordinates
(0, 65, 0). (If you took the “give the arena a floor” Try It, you’ll land on or above the bedrock; if
you kept the pure void, you’ll need something to stand on; see “What Can Go Wrong.”) That single
line is the whole journey: execute in switches the execution dimension to yours, and run tp
teleports you there. To get back, point another function at minecraft:overworld the same way.
Figure (to be captured). the chat showing the goto_arena function running, and the player now standing in the new dimension
Noise generators and biome sources
The arena used the flat generator because a void is the cleanest possible example. But the real
worlds (anything with hills, caves, oceans, ores) use the noise generator. You won’t master noise
generation until Chapter 45, but you should understand the shape of a noise dimension now, because
it’s the other half of how dimensions work.
The noise generator takes two extra fields:
settings— “Settings for the noise generator.” This is either the identifier of a noise settings file or an inline settings object. Noise settings are “for generating the shape of the terrain and noise caves, and what blocks the terrain is generated with,” stored atdata/<namespace>/worldgen/noise_settings. There are ready-made vanilla ones you can point at by ID:minecraft:overworld,minecraft:amplified,minecraft:nether,minecraft:caves,minecraft:end, andminecraft:floating_islands.biome_source— “Settings determining the biome layout.” This object has its owntypechoosing how biomes are arranged.
The biome-source type values are:
fixed— “uses one specified biome everywhere.” Its one extra field isbiome: the single biome to use.multi_noise— spreads many biomes across the world using climate noise. It takes either apreset(“The default parameter lists areoverworldandnether”) or an explicitbiomeslist of parameter points.checkerboard— “places biomes in a checkerboard pattern,” from abiomeslist and an optionalscale.the_end— “The biome source used for the End dimension. This biome source has no additional fields.”
So the simplest custom terrain dimension you could build is a noise generator pointed at a vanilla
noise settings preset, with a fixed biome source. Here’s the structure:
data/mypack/dimension/canyon.json
{
"type": "minecraft:overworld",
"generator": {
"type": "minecraft:noise",
"settings": "minecraft:overworld",
"biome_source": {
"type": "minecraft:fixed",
"biome": "minecraft:desert"
}
}
}
This makes a dimension that generates with the Overworld’s terrain shape but is desert everywhere,
using the built-in minecraft:overworld dimension type. Notice we reused a vanilla dimension type
(minecraft:overworld) here instead of writing one. Both files are independent, so you can mix and
match.
The inside of a noise settings file is Chapter 45. A noise settings file contains a “noise router” (a collection of density functions for terrain, biome layout, aquifers, and ore veins) and a “surface rule” (which blocks make the surface). Writing your own noise settings (density functions, the router, surface rules, carvers) is exactly what Chapter 45 covers, so we’ll save the internals for there. For this chapter, always point
settingsat one of the vanilla preset IDs above; don’t hand-write the object.
Practice
1. A sky dimension of floating slabs. Build a second dimension, mypack:sky, that’s a thin
floating platform high in an otherwise empty world: the start of a sky-island minigame. Make a
dimension type for it (you can copy arena.json and rename it), then write the dimension file with a
flat generator whose layers stack a few solid blocks on top of empty space below. Because flat
layers start at the world bottom and the lowest layer fills first, put your solid blocks as the
first layers and leave it at that. Everything above the last layer is open sky:
data/mypack/dimension/sky.json
{
"type": "mypack:sky",
"generator": {
"type": "minecraft:flat",
"settings": {
"biome": "minecraft:plains",
"layers": [
{
"block": "minecraft:stone",
"height": 3
},
{
"block": "minecraft:grass_block",
"height": 1
}
]
}
}
}
That’s a four-block-thick slab (three stone, one grass) over the plains biome, with open air above it
and the void below. Don’t forget the matching data/mypack/dimension_type/sky.json, and reboot the
world before you execute in mypack:sky run tp @s 0 100 0 to visit it.
2. A teleport pair. Write two functions, goto_arena (you already have it) and goto_overworld,
each using execute in <dimension> run tp so a player can hop into the arena and back out. Hook them
up however you like: a Chapter 34 trigger, a dialog button from Chapter 39, or just run them by hand.
3. (Try It, harder) A fixed-biome noise world. Using the canyon.json structure above as a model,
make a noise dimension that generates with minecraft:floating_islands settings and a fixed biome
source set to minecraft:the_end: a custom End-island world reachable from the Overworld. Point its
type at minecraft:the_end so it gets End-style physics.
What Can Go Wrong
/reload did nothing, and the dimension isn’t there. This is the single most common surprise.
Dimensions are a dynamic registry; the game reads them only when the world loads. /reload rebuilds
functions and recipes, but not dimensions. The fix is always the same: quit to the title screen
and reopen the world. If you edit a dimension or dimension-type file later, you reboot again. There’s
no /reload shortcut for these.
The world won’t load, or the dimension is missing after a reboot. Almost always a bad value in the
dimension type. The usual culprits: min_y or height that isn’t a multiple of 16, a height
outside the 16–4064 range, or a logical_height larger than height. Re-check those three numbers
against the rules in the field list. A misspelled field name or a missing comma will do it too, the
same JSON-shape mistakes from Chapter 8.
I teleported in and fell forever. If you kept the pure-air void (one layer of air, no floor) and
teleported a player in with nothing to stand on, they’ll drop through the empty world. Either give the
dimension a floor (the “give the arena a floor” Try It), build a platform with /setblock or /fill
before sending players in, or teleport them onto a structure you’ve placed. A void is meant to be
empty; it’s your job to put something under the players.
Modern Minecraft — you don’t need a mod for this. Older tutorials treat custom dimensions as a Forge/Fabric-only feature, because for years they were. Since the world-generation data-pack system landed, a plain data pack can add dimensions with no mod loader at all: just the two JSON files you wrote in this chapter. If a guide tells you to install a mod to make a new dimension, it’s out of date for current Java Edition.