API

World generation

Ores, trees, flowers, structures and biomes that appear by themselves in the world. You declare what and where, and new chunks get it.

Ores

content/ruby_ore.craftCraftScript
block "ruby_ore" { hardness: 3, tool: "pickaxe", tier: "iron" }

ore "ruby_ore" {
    replaces: "stone_and_deepslate"
    size: 9
    per_chunk: 8
    height: [-60, 60]
}
Property Values Default
block the block to place: "mymod:other" the block named like the ore
replaces stone, deepslate, stone_and_deepslate (overworld), netherrack (Nether) or end_stone (End) stone_and_deepslate
size blocks per vein, 1–64 8
per_chunk veins tried per chunk 8
height [min, max], height range [-64, 64]
biomes only in these biomes, by id or by tag every biome where its rock is

Without biomes, the ore appears in every biome of the dimension that replaces belongs to; an end_stone ore, in every biome of the End. The block itself is declared like any other, with its hardness, tool and loot; see Blocks, items and recipes.

content/void_ore.craftCraftScript
ore "void_ore" {
    replaces: "end_stone"
    size: 5
    per_chunk: 6
    height: [10, 80]
    biomes: ["mymod:crystal_glade"]
}

Trees

A tree is a straight trunk with a ball of leaves. Declare the two blocks, then the tree.

content/ruby_tree.craftCraftScript
block "ruby_log" { hardness: 2, tool: "axe", sound: "wood" }
block "ruby_leaves" { hardness: 0.2, transparent: true, sound: "grass" }

tree "ruby_tree" {
    trunk: "ruby_log"
    leaves: "ruby_leaves"
    height: 6
    height_variation: 2
    leaves_radius: 2
    per_chunk: 2
    biomes: ["#minecraft:is_forest", "minecraft:plains"]
}
Property Values Default
trunk the log block, from the mod or the game: "ruby_log", "minecraft:oak_log" —
leaves the leaves block —
height trunk height, in blocks 5
height_variation how much the height varies from tree to tree 2
leaves_radius radius of the ball of leaves, in blocks 2
per_chunk trees tried per chunk 1
biomes biomes where it appears, by id or by tag —

Biomes are listed by id (minecraft:plains) or by tag (#minecraft:is_forest), mixed freely. Trunk and leaves can be blocks of the mod or of the game.

Plants and patches

A plant is a block drawn as two crossed images, like a flower: nothing collides with it and light goes through. Its texture is textures/block/ruby_flower.png, with a transparent background.

content/ruby_flowers.craftCraftScript
block "ruby_flower" { plant: true, hardness: 0 }

patch "ruby_flowers" {
    block: "ruby_flower"
    biomes: ["#minecraft:is_overworld"]
    rarity: 4
    size: 32
    spread: 7
}

A patch scatters plants over the world:

Property Values Default
block the plant block —
biomes biomes where it appears, by id or by tag —
rarity one patch every this many chunks 4
size plants each patch tries to place 32
spread farthest distance from the center of the patch, in blocks 7

Plants are placed only in the air, on the overworld's ground (grass, dirt, moss and mud). For plants on other ground, on walls or hanging from ceilings, write a feature: see Generation by code.

Structures

A structure is a building you make yourself:

  1. Build it in the game.
  2. Save it with a structure block.
  3. Copy the .nbt file into the mod's structures/ folder: next to the scripts in a CraftScript mod, or in assets/<mod id>/structures/ in a Kotlin or Java jar.

Then declare it:

content/ruby_shrine.craftCraftScript
structure "ruby_shrine" {
    file: "ruby_shrine"
    biomes: ["#minecraft:is_overworld"]
    spacing: 24
    separation: 8
    buried: false
}
Property Values Default
file name of the .nbt file, without extension the first variant, or the structure's name
biomes biomes where it appears, by id or by tag —
spacing about one structure every this many chunks 24
separation never closer than this many chunks; smaller than spacing 8
buried true sinks it into the ground, for ruins false
offset_y blocks up from the surface it stands on; negative sinks it 0
adapt_ground true fills the ground under it and clears it around; false places it as it is true
heights [min, max]: at a random height in this range wherever the surface is, instead of on the surface (a house in the sky) on the surface

Find it with /locate structure <mod id>:ruby_shrine and place it with /place structure <mod id>:ruby_shrine.

Variants, replacements and decay

One structure can come from several files, and its blocks can change as it is placed. This makes ruins that are never quite the same:

content/old_ruins.craftCraftScript
structure "old_ruins" {
    variants: [{ file: "ruins_small", weight: 3 }, "ruins_tower"]
    biomes: ["#minecraft:is_forest"]
    spacing: 20
    separation: 6
    offset_y: -2
    skip: ["minecraft:air"]
    replace: [{ block: "minecraft:stone_bricks", with: "minecraft:cracked_stone_bricks", chance: 0.3 }]
    decay: { left: 0.8, blocks: ["minecraft:stone_bricks", "minecraft:cracked_stone_bricks"] }
}
Property Values Default
variants files it is one of: names, or { file, weight }; one is picked at random, by weight just file, weight 1
skip blocks of its files that aren't placed. "minecraft:air" keeps the world's blocks where the file has air —
replace [{ block, with, chance }]: a block of its files becomes another at that chance (more than 0, up to 1) chance 1
decay { left, blocks }: only left (0–1) of blocks (ids or tags) is kept; without blocks, of any block all is kept

Structures of joining pieces

A village or a dungeon is made of pieces that join: a street leads to a house, a corridor to a room. Each piece is a file with the game's jigsaw blocks in it, and each jigsaw block names the pool the next piece comes from, as <mod id>:<pool>. Declare the pools; the structure starts from the first one.

content/hamlet.craftCraftScript
structure "hamlet" {
    biomes: ["minecraft:plains"]
    spacing: 34
    separation: 8
    depth: 6
    pools: [
        { name: "hamlet/square", pieces: [{ file: "hamlet/square" }] },
        { name: "hamlet/streets", fallback: "hamlet/street_ends",
          pieces: [{ file: "hamlet/street_straight", weight: 3, follows_ground: true },
                   { file: "hamlet/street_corner", follows_ground: true }],
          replace: [{ block: "minecraft:stone_bricks", with: "minecraft:oak_planks", where: "minecraft:water" }] },
        { name: "hamlet/street_ends", pieces: [{ file: "hamlet/street_end", follows_ground: true }] },
        { name: "hamlet/houses", none: 2,
          pieces: [{ file: "hamlet/house_small", weight: 4 }, { file: "hamlet/house_big" }] },
    ]
}
Property Values Default
pools the pools of pieces; the first one is where it starts one piece, from variants or file
depth how many pieces away from the first one it reaches 1

Each pool has:

Key Values Default
name the name its jigsaw blocks use, like hamlet/streets —
pieces [{ file, weight, follows_ground }]. follows_ground: true bends the piece to the ground under it, for streets and paths; false keeps it straight, for houses weight 1, false
features [{ id, weight }]: a feature as a piece, yours or the game's (minecraft:chorus_plant) —
none weight of no piece at all, for an empty plot 0
fallback the pool used where no piece fits, such as a street's end nothing
skip, replace as for a single structure. In a pool, a replacement can add where: only where the world already has that block (a street's bricks over water become planks) —

All pieces stay within 80 blocks of the first one.

Two options are only in Kotlin for now: salt, a number that picks where in its stretch of spacing chunks the structure falls (two structures with the same spacing and salt fall in the same places; without it, one is made from the structure's id), and aboveBottom, how many blocks above the world's bottom its pieces must stay (where one would reach lower, the structure isn't made).

Structures your code builds block by block are on the Generation by code page.

Biomes

A biome of your own takes a share of the places of a game biome. It keeps what grows, lives and is carved there, and brings its own climate and colors.

content/ruby_meadow.craftCraftScript
biome "ruby_meadow" {
    replaces: "minecraft:plains"
    share: 0.5
    temperature: 0.8
    downfall: 0.4
    precipitation: true
    grass_color: "#d05070"
    foliage_color: "#c04060"
    sky_color: "#ff9fb0"
    fog_color: "#ffd0d8"
    water_color: "#ff6080"
    water_fog_color: "#a03050"
}
Property Values Default
replaces the game biome whose places it takes: "minecraft:plains" "minecraft:plains"
share fraction of those places it takes, more than 0 and up to 1 0.5
temperature temperature of the climate 0.8
downfall how much it rains 0.4
precipitation true for rain, false for none true
grass_color grass color, #rrggbb the replaced biome’s
foliage_color leaves color the replaced biome’s
sky_color sky color the replaced biome’s
fog_color fog color the replaced biome’s
water_color water color #3f76e4
water_fog_color color of the fog under water the replaced biome’s

share is spread evenly over the places where the replaced biome would be: 0.5 takes half of them, one in every two. The new biome inherits what grows, lives and is carved there (vegetation, ores, caves, creatures, music) and whatever other mods add to that biome. Colors you leave out stay those of the replaced biome.

Several biomes can replace the same one: they share its places. Find yours with /locate biome <mod id>:ruby_meadow.

Sound, ground and creatures

A biome can also have its own music and air, cover its ground with a block of yours, and choose who lives there:

content/glow_marsh.craftCraftScript
biome "glow_marsh" {
    replaces: "minecraft:swamp"
    share: 0.4
    music: "mymod:music.marsh"
    ambient_sound: "mymod:ambient.marsh_hum"
    particle: { id: "minecraft:glow", chance: 0.005 }
    surface: "mymod:glow_moss"
    spawns: [
        { creature: "minecraft:frog", weight: 10, group: [2, 5] },
        { creature: "mymod:marsh_wisp", weight: 4, group: [1, 2] },
    ]
}
Property Values Default
music a sound id, played as the biome's music the replaced biome’s
ambient_sound a sound that plays on and on there (wind, a hum) the replaced biome’s
particle { id, chance }: a particle floating in its air; chance per spot near the player each tick (0.001 is a few) the replaced biome’s; chance 0.01
surface the block its ground is covered with (the top block of each floor) the dimension's usual ground
spawns [{ creature, weight, group }]: the creatures that live there; when it names any, these and no others the replaced biome’s; weight 10, group [1, 4]
inherits false: only what is given to this biome generates there (its features, its carvers, what mods place in it), not what generates in the replaced biome true
features [{ id, step }]: features that already exist, the game's or of data, placed in it. step is lakes, surface, ores, underground or vegetation —
carvers ids of carvers that hollow its caves, yours or the game's; they run in the order given, before the replaced biome's —

With inherits: false the biome still takes the replaced biome's places, and its creatures and sounds unless you give your own; only what grows and is carved there stops coming along. A ground made block by block and carvers of your own are on the Generation by code page.

Biomes of the End

In the End, a biome takes whole regions, about 200 blocks across, instead of climate places. Replacing minecraft:end_highlands it takes all the island land of its regions (highlands, midlands and barrens); replacing minecraft:small_end_islands, the void between the islands. The central island stays the game's, and the regions are different in every world.

content/crystal_glade.craftCraftScript
biome "crystal_glade" {
    replaces: "minecraft:end_highlands"
    share: 0.3
    sky_color: "#2a1840"
    fog_color: "#3c2a5a"
    surface: "mymod:crystal_moss"
    inherits: false
    features: [{ id: "minecraft:end_gateway_return", step: "surface" }]
}

Good to know

  • Only new chunks. Chunks that were already generated don’t change; only chunks generated after the mod is installed get ores, trees, plants, structures and biomes. Explore new terrain to find them.
  • Missing names are left out. A biome or tag in biomes that doesn't exist (say, another mod's that isn't installed) is skipped, not an error.
  • No ground, no structure. A structure that stands on the surface isn't made where its column has no ground at all, such as the void between End islands.
  • Features, structures, land, biome maps, carvers and grounds written in code are on the Generation by code page.
  • Whole worlds of your own are on the Dimensions page.

In Kotlin

content/World.ktKotlin
ore("ruby_ore") {
    replaces = OreHost.STONE_AND_DEEPSLATE
    size = 9
    perChunk = 8
    minY = -60
    maxY = 60
}

ore("void_ore") {
    replaces = OreHost.END_STONE
    biome("mymod:crystal_glade")
}

tree("ruby_tree") {
    trunk = "ruby_log"
    leaves = "ruby_leaves"
    height = 6
    perChunk = 2
    biome("#minecraft:is_forest")
}

block("ruby_flower") { plant = true }

patch("ruby_flowers") {
    block = "ruby_flower"
    rarity = 4
    biome("#minecraft:is_overworld")
}

structure("old_ruins") {
    variant("ruins_small", weight = 3)
    variant("ruins_tower")
    biome("#minecraft:is_forest")
    spacing = 20
    offsetY = -2
    skip("minecraft:air")
    replace("minecraft:stone_bricks", "minecraft:cracked_stone_bricks", chance = 0.3)
    decay(0.8, "minecraft:stone_bricks", "minecraft:cracked_stone_bricks")
    salt = 120457
}

structure("hamlet") {
    biome("minecraft:plains")
    spacing = 34
    depth = 6
    pool("hamlet/square") { piece("hamlet/square") }
    pool("hamlet/streets") {
        piece("hamlet/street_straight", weight = 3, followsGround = true)
        piece("hamlet/street_corner", followsGround = true)
        fallback = "hamlet/street_ends"
        replace("minecraft:stone_bricks", "minecraft:oak_planks", where = "minecraft:water")
    }
    pool("hamlet/street_ends") { piece("hamlet/street_end", followsGround = true) }
    pool("hamlet/houses") {
        piece("hamlet/house_small", weight = 4)
        piece("hamlet/house_big")
        none = 2
    }
}

biome("glow_marsh") {
    replaces = "minecraft:swamp"
    share = 0.4
    music = "mymod:music.marsh"
    ambientSound = "mymod:ambient.marsh_hum"
    particle("minecraft:glow", chance = 0.005)
    surface = "mymod:glow_moss"
    spawn("minecraft:frog", weight = 10, group = 2..5)
}

biome("crystal_glade") {
    replaces = "minecraft:end_highlands"
    share = 0.3
    surface = "mymod:crystal_moss"
    inherits = false
    feature("minecraft:end_gateway_return", FeatureStep.SURFACE)
}