Skip to content

Configured Features

A ConfiguredFeature is a feature paired with a configuration. The feature is the algorithm (an ore vein, a tree, a geode) and the configuration would be its parameters such as which ore, how big, etc.

Configured features are not placed in the world on their own. A configured feature describes what to generate and a placed feature formally wraps it with the placement rules that decide where and/or how often it should appear.

To use a configured feature in a biome, wrap it in a placed feature.

The ConfiguredFeatures catalog holds typed references to every configured feature vanilla registrar.

ExamplePlugin.java Java
import me.outspending.biomesapi.wrapper.worldgen.feature.ConfiguredFeature;
import me.outspending.biomesapi.wrapper.worldgen.feature.ConfiguredFeatures;

// a reference straight from the catalog
ConfiguredFeature largeDiamonds = ConfiguredFeatures.ORE_DIAMOND_LARGE;

// or by key
ConfiguredFeature byKey = ConfiguredFeature.reference(ResourceKey.minecraft("ore_diamond_large"));

To author your own configured features, you can extend the CustomFeature class. And pair it with your own configuration context.

Java
import me.outspending.biomesapi.wrapper.worldgen.feature.custom.CustomFeature;
import me.outspending.biomesapi.wrapper.worldgen.feature.custom.PlacementContext;
import org.bukkit.Material;
import org.bukkit.util.BlockVector;
import org.jetbrains.annotations.NotNull;

import java.util.Random;

public class PillarFeature extends CustomFeature<@NotNull PillarFeature.PillarConfig> {

  public PillarFeature() {
      super(PillarConfig::defaults);
  }

  @Override
  public boolean place(PlacementContext<@NotNull PillarConfig> context) {
      PillarConfig config = context.config();
      Random random = context.random();
      BlockVector origin = context.origin();

      int height = config.minHeight() + random.nextInt(config.maxHeight() - config.minHeight() + 1);

      for (int y = 0; y < height; y++) {
          BlockVector pos = new BlockVector(origin.getBlockX(), origin.getBlockY() + y, origin.getBlockZ());
          context.setBlock(pos, config.pillarBlock().createBlockData());
      }

      BlockVector cap = new BlockVector(origin.getBlockX(), origin.getBlockY() + height, origin.getBlockZ());
      context.setBlock(cap, config.capBlock().createBlockData());

      return true;
  }

  public record PillarConfig(Material pillarBlock, Material capBlock, int minHeight, int maxHeight) {
      public static PillarConfig defaults() {
          return new PillarConfig(Material.OBSIDIAN, Material.GLOWSTONE, 4, 9);
      }
  }
}