Skip to content

Biome Sources

A BiomeSource dictates how biomes occupy regions in a world. These work in tandem with ChunkGenerators to produce a dimension’s terrain.

A fixed source places the same biome across the entire world. It’s the simplest source to build and a fine fit for flat worlds, void worlds, or any dimension where biome variety does not matter.

Examples.java Java
import dev.wyck.biome.Biomes;
import dev.wyck.biome.CustomBiome;
import dev.wyck.keys.ResourceKey;
import dev.wyck.worldgen.biome.BiomeSource;

// a registered custom biome
CustomBiome biome = CustomBiome.builder()
  .resourceKey(ResourceKey.of("test", "biome"))
  .fogColor("#DB00FD")
  .skyColor("#2F46FF")
  .register();

// fixed over a custom biome
BiomeSource custom = BiomeSource.fixed(biome);

// or a vanilla biome
BiomeSource vanilla = BiomeSource.fixed(Biomes.PLAINS);

// or by key
BiomeSource byKey = BiomeSource.fixed(ResourceKey.of("minecraft", "desert"));

A multi-noise source distributes biomes the way the vanilla overworld does: each biome is placed at a point in a six-axis climate space (temperature, humidity, continentalness, erosion, depth, weirdness) plus a fitness offset, and the generator picks whichever biome’s point is closest for a given location.

ExamplePlugin.java Java
import dev.wyck.biome.Biomes;
import dev.wyck.biome.CustomBiome;
import dev.wyck.keys.ResourceKey;
import dev.wyck.worldgen.biome.BiomeSource;
import dev.wyck.worldgen.climate.ClimatePoint;
import dev.wyck.worldgen.climate.ClimateParameter;
import org.bukkit.plugin.java.JavaPlugin;

public class ExamplePlugin extends JavaPlugin {
  @Override
  public void onEnable() {
      CustomBiome biome = CustomBiome.builder()
          .resourceKey(ResourceKey.of("test", "biome"))
          .fogColor("#DB00FD")
          .skyColor("#2F46FF")
          .register();

      ClimatePoint withArgsClimate = ClimatePoint.of(1.8f, 1.2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);

      ClimatePoint zeroBuilderClimate = ClimatePoint.builder()
          .temperature(ClimateParameter.point(-0.8f))
          .humidity(ClimateParameter.point(-0.5f))
          .build();

      ClimatePoint builderClimate = ClimatePoint.builder()
          .temperature(ClimateParameter.point(0.0f))
          .humidity(ClimateParameter.point(0.0f))
          .build();

      BiomeSource source = BiomeSource.multiNoise()
          .add(ResourceKey.of("minecraft", "plains"), withArgsClimate) // wins in hot, wet regions
          .add(biome, zeroBuilderClimate) // wins in cold, dry regions
          .add(Biomes.JUNGLE, builderClimate) // fills everywhere else
          .build(); // Done!
  }
}

BiomeSource exposes ready-made multi-noise presets that mirror how Minecraft populates each dimension, plus theEnd() for the End’s radial layout.

Examples.java Java
import dev.wyck.worldgen.biome.BiomeSource;

BiomeSource overworld = BiomeSource.overworld(); // the vanilla overworld climate distribution
BiomeSource nether = BiomeSource.nether(); // the vanilla nether biomes
BiomeSource end = BiomeSource.theEnd(); // the End's central-island + outer-islands layout

A checkered column source lays biomes out in a repeating checkerboard, cycling through the biomes you give it. Datapack developers use it for debugging biome-specific generation because every biome is guaranteed to appear in a predictable grid.

The size controls how wide each cell is: 0 makes each cell a single chunk, and every increment doubles the width, valid values are 062.

Examples.java Java
import dev.wyck.biome.Biomes;
import dev.wyck.worldgen.biome.BiomeSource;

BiomeSource checkered = BiomeSource.checkeredColumn()
  .biome(Biomes.PLAINS)
  .biome(Biomes.DESERT)
  .biome(Biomes.JUNGLE)
  .size(2) // each cell is 4 chunks wide (0 -> 1, 1 -> 2, 2 -> 4, ...)
  .build();

Once built, you can pass the biome source to a generator and the generator to a LevelCreator.

ExamplePlugin.java Java
ChunkGenerator generator = NoiseBasedChunkGenerator.of(source, Noise.overworld());

World world = LevelCreator.builder()
  .levelKey(ResourceKey.of("test", "example"))
  .generator(generator)
  .create();