Skip to content

Instantly share code, notes, and snippets.

@Commoble
Created May 1, 2022 23:45
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Commoble/27bc6c64fc7f1023ea58e4e5aa24feab to your computer and use it in GitHub Desktop.
Save Commoble/27bc6c64fc7f1023ea58e4e5aa24feab to your computer and use it in GitHub Desktop.
Registering and using configured/placed features in Forge for Minecraft 1.18.2
package commoble.featureexamplemod;
import java.util.List;
import net.minecraft.core.Registry;
import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.BlockPileConfiguration;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import net.minecraft.world.level.levelgen.placement.InSquarePlacement;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.BiomeLoadingEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.RegistryObject;
@Mod(FeatureExampleMod.MODID)
public class FeatureExampleMod
{
public static final String MODID = "featureexample";
private static final DeferredRegister<ConfiguredFeature<?,?>> CONFIGURED_FEATURES =
DeferredRegister.create(Registry.CONFIGURED_FEATURE_REGISTRY, MODID);
public static final DeferredRegister<PlacedFeature> PLACED_FEATURES =
DeferredRegister.create(Registry.PLACED_FEATURE_REGISTRY, MODID);
private static final String TNT_PILE_NAME = "tnt_pile";
// your ConfiguredFeature RegistryObject fields must use <?,?> as the generic params for technical reasons
private static final RegistryObject<ConfiguredFeature<?,?>> CONFIGURED_TNT_PILE =
CONFIGURED_FEATURES.register(TNT_PILE_NAME,
// ConfiguredFeature takes a feature type and a featureconfig.
// You generally can't static init featureconfigs ahead of time, as they
// very often have hard references to blocks (such as this one does).
// The feature type defines the generation logic, the feature config is extra data used by that logic.
// Feature.BLOCK_PILE generates blocks in a pile, it takes a BlockPileConfiguration.
() -> new ConfiguredFeature<>(Feature.BLOCK_PILE,
// BlockPileConfiguration takes a blockstate provider, we use one that always provides TNT.
new BlockPileConfiguration(BlockStateProvider.simple(Blocks.TNT))));
// A PlacedFeature is a configured feature and a list of placement modifiers.
// This is what goes into biomes, the placement modifiers determine where and how often to
// place the configured feature.
// Each placed feature in any of the biomes in a chunk generates in that chunk when the chunk generates.
// When a feature generates in a chunk, the chunk's local 0,0,0 origin coordinate is given to the
// list of placement modifiers (if any).
// Each placement modifier converts the input position to zero or more output positions, each of which
// is given to the next placement modifier.
// The ConfiguredFeature is generated at the positions generated after all placement modifiers have run.
private static final RegistryObject<PlacedFeature> PLACED_TNT_PILE =
PLACED_FEATURES.register(TNT_PILE_NAME,
() -> new PlacedFeature(CONFIGURED_TNT_PILE.getHolder().get(),
// InSquarePlacement.spread() takes the input position
// and randomizes the X and Z coordinates within the chunk
// PlacementUtils.HEIGHTMAP sets the Y-coordinate of the input position to the heightmap.
// This causes the tnt pile to be generated at a random surface position in the chunk.
List.of(InSquarePlacement.spread(), PlacementUtils.HEIGHTMAP)));
public FeatureExampleMod()
{
IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus();
IEventBus forgeBus = MinecraftForge.EVENT_BUS;
CONFIGURED_FEATURES.register(modBus);
PLACED_FEATURES.register(modBus);
forgeBus.addListener(this::onBiomeLoading);
}
// BiomeLoadingEvent can be used to add placed features to existing biomes.
// Placed features added in the BiomeLoadingEvent must have been previously registered.
// JSON features cannot be added to biomes via the BiomeLoadingEvent.
private void onBiomeLoading(BiomeLoadingEvent event)
{
event.getGeneration().addFeature(Decoration.VEGETAL_DECORATION, PLACED_TNT_PILE.getHolder().get());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment