Guide
This guide covers 90% of use cases.
Table of contents
First of all, do not forget to import Cubiomes
using Cubiomes
Minecraft versions
To get a Minecraft version, simply use the mcv
keyword (short for Minecraft version).
mcv"1.18"
mcv"1.18.2"
Note that the returned value is mcv"1.18.2"
. This is because Cubiomes.jl focuses only on the latest minor version of Minecraft, meaning mcv"1.18"
is exactly the same as mcv"1.18.2"
. Generally, everything remains the same between minor versions. But to be safe, ensure that the version matches the one you need.
Comparing versions is possible
mcv"beta1.7" < mcv"1.8"
true
However, the main purpose of versions is to link them to a dimension.
Dimension objects
Before generating anything, we often need to get a specific dimension to work with. The three dimensions are:
They are all subtypes of Dimension
. To create a new dimension, link it to a version.
overworld = Overworld(undef, mcv"1.18")
Overworld Dimension (≥1.18, uninitialized)
As suggested by the undef
keyword, the object is currently uninitialized and unusable. We need to assign it a seed.
setseed!(overworld, 999)
Just retype overworld
to see the initialized object. Not shown here because it is quite long.
The seed can be any valid Minecraft seed, i.e., a string or an integer. However, for performance reasons, integers are preferred.
The "!" at the end of setseed!
follows Julia’s convention, indicating that the function modifies the object (overworld
) in place. This prevents the creation of a new object each time a seed is set, allowing reuse of the same overworld
instance. The only thing that cannot be changed is the version. Think of it like the game starting with a specific version, and then you can load different worlds (seeds) in that version as long as you want.
Biome generation
We now have three key pieces of information combined in a single Dimension
object:
- the dimension
- the version
- the seed
Now, we just need to call the getbiome
function, providing our object and a coordinate.
getbiome(overworld, -55, 45, 63)
river::Biome = 0x07
The coordinates can be passed as three numbers or as a tuple (x, z, y):
coord = (-55, 45, 63)
getbiome(overworld, coord)
river::Biome = 0x07
In Cubiomes.jl, the coordinate order is ALWAYS (x, z, y)
. This differs from Minecraft’s order, which is (x, y, z)
.
Biome generation on a world map
Let's generate an empty map with x and z ranging from -200 to 200, and y = 63
.
worldmap = WorldMap(-200:200, -200:200, 63)
401×401×1 OffsetArray(::Array{Biome, 3}, -200:200, -200:200, 63:63) with eltype Biome with indices -200:200×-200:200×63:63:
[:, :, 63] =
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff … BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff … BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
⋮ ⋱ ⋮
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff … BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff … BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff BIOME_NONE::Biome = 0xff
Note that this is a 3D array, even if the size of y
is 1. The y
size can be greater than 1 as well. Some useful utility functions:
coordinates
: returns a collection of coordinates instead of biomes.view2d
: provides a 2D view by removing they
axis when its size is 1. Useful for visualization so that Julia recognizes it as 2D. ⚠ This is a view, meaning modifying one also modifies the other. Usecopy
to create an independent map.to_color
: creates a new map with colors representing biomes (e.g., green for forests).
To visualize our map (completely empty at the moment):
to_color(view2d(worldmap))
If you see a bunch of numbers instead of an image, nothing is wrong. The colors are just not displayed in your environment. You can either:
- Use a Jupyter notebook
- Save the image using
FileIO
andImageIO
:using FileIO; save("worldmap.png", to_color(worldmap))
The map is currently empty. To populate it with biomes from our overworld
object, we would think about simply iterating over all coordinates and assigning the biome to each.
function populate_map!(overworld, worldmap)
for coord in coordinates(worldmap)
worldmap[coord] = getbiome(overworld, coord)
end
return
end
populate_map!(overworld, worldmap)
to_color(view2d(worldmap))

And it works! However, it could be inefficient. Because of how Minecraft generation works, we can optimize the process using algorithms that take advantage of a global world view. For certain dimensions/versions, this can be significantly faster. That's what genbiomes!
is for.
genbiomes!(overworld, worldmap)
to_color(view2d(worldmap))

Let's see the performance difference:
@time populate_map!(overworld, worldmap)
0.639796 seconds
@time genbiomes!(overworld, worldmap)
0.288255 seconds (41 allocations: 4.781 KiB)
A world map acts like a standard array; the only difference is that its indices correspond to Minecraft coordinates.
worldmap[-55, 45]
river::Biome = 0x07
worldmap[-255, 45]
BoundsError: attempt to access 401×401×1 OffsetArray(::Array{Biome, 3}, -200:200, -200:200, 63:63) with eltype Biome with indices -200:200×-200:200×63:63 at index [-255, 45]
The scale object
In getbiome
and genbiomes!
, there is an optional final argument: the Scale
object. A scale can be created using 📏"1:N", where N is a power of 4.
worldmap2 = WorldMap(-50:50, -50:50, 16)
genbiomes!(overworld, worldmap2, 📏"1:4")
to_color(view2d(worldmap2))
The scale determines the size of square/cube regions where only one block from each region is "sampled" and displayed as one pixel. A larger scale results in a more zoomed-out map.
When using a scale, the indices no longer match Minecraft coordinates. Instead, for example, with scale 📏"1:4", they correspond to chunk coordinates.
The first scales are:
📏"1:1"
— Block scale📏"1:4"
— Chunk scale📏"1:16"
,📏"1:64"
,📏"1:256"
,📏"1:1024"
, ...,📏"1:4^k"
for any integerk
In some versions and dimensions, this approach is much faster than simply dividing the coordinates by the scale, since Minecraft's biome generation algorithm inherently divides the world into regions multiple times until reaching scale 📏"1:1"
.
4
This page was generated using Literate.jl.