Jump to content

[1.17.1] How to properly register/use ConfiguredFeature for modded Features


Recommended Posts

Posted

I'm having some troubles creating/attaching a ConfiguredFeature built on top of a modded feature in a modded biome. I had no issues using CF with vanilla features (like Flower placing or Tree placement with mod blocks, for example), however if I want to use my own Feature as well, I get some troubles.

What I've done is this:
I create the Feature like this

// Deferred Register
public static final DeferredRegister<Feature<?>> MOD_FEATURES = DeferredRegister.create(ForgeRegistries.FEATURES, MOD_ID);

// Feature
public static final RegistryObject<Feature<ColumnFeatureConfiguration>> LAVA_ROCK_COLUMNS = register("lava_rock_columns",
            () -> new LavaRockColumnsFeature(ColumnFeatureConfiguration.CODEC));
//LavaRockColumnsFeature is just a class that extends Feature<ColumnFeatureConfiguration>
//to generate basalt columns but with a mod block instead


// Register the Feature
public static <T extends FeatureConfiguration> RegistryObject<Feature<T>> register(String name, Supplier<Feature<T>> featureSupplier) {
        return MOD_FEATURES.register(name, featureSupplier);
}

Then, from the main mod class constructor, I call the register method for the Feature registry

var eventBus = FMLJavaModLoadingContext.get().getModEventBus();
MOD_FEATURES.register(eventBus);

Next I create my ConfiguredFeatures like this

//Generate "Anemone" flowers inside the World
public static final ConfiguredFeature<?, ?> ANEMONE = Feature.FLOWER.configured(
                    (new RandomPatchConfiguration.GrassConfigurationBuilder(
                            new SimpleStateProvider(ModBlocks.ANEMONE.get().defaultBlockState()),
                            SimpleBlockPlacer.INSTANCE)
                    ).tries(2).build())
            .decorated(Features.Decorators.HEIGHTMAP_SQUARE).count(1);

//Generate "Small Lava Rock Columns" in a custom Biome
public static final ConfiguredFeature<?, ?> SMALL_LAVA_ROCK_COLUMNS = 
  ModFeatures.LAVA_ROCK_COLUMNS.get()
  .configured(new ColumnFeatureConfiguration(ConstantInt.of(1), UniformInt.of(1, 4)))
  .decorated(FeatureDecorator.COUNT_MULTILAYER.configured(new CountConfiguration(4)));

Then I register this feature during the FMLCommonSetupEvent by doing this

@Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public final class CommonSetupSubscriber {
	@SubscribeEvent
    public static void onCommonSetup(final FMLCommonSetupEvent event) {
      event.enqueueWork(() -> {
            registerConfiguredFeatures();
        });
  	}
}

private static void registerConfiguredFeatures() {
  Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, new ResourceLocation(MOD_ID, "anemone"), ModConfiguredFeatures.ANEMONE);
  Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, new ResourceLocation(MOD_ID, "small_lava_rock_columns"), ModConfiguredFeatures.SMALL_LAVA_ROCK_COLUMNS);
}

Even without adding the "Small lava rock" configured feature to the custom Biome, if I run the game, I get this error
 

java.lang.NullPointerException: Registry Object not present: mod_id:lava_rock_columns

So I guess the issue is that the ConfiguredFeature is trying to get the Feature from the Registry, but can't find it? So what should be the correct way to register the Feature and/or the Configured Feature?

Don't blame me if i always ask for your help. I just want to learn to be better :)

Posted

The point is that even without adding the CF to a custom Biome the game crashes :/ However, here is how I create the Biome
 

public static Biome volcanicWasteland() {
MobSpawnSettings mobSpawnSettings = new MobSpawnSettings.Builder()
                .addSpawn(MobCategory.MONSTER, new MobSpawnSettings.SpawnerData(EntityType.MAGMA_CUBE, 100, 2, 5))
                .build();
        BiomeGenerationSettings.Builder biomeBuilder = new BiomeGenerationSettings.Builder();
        addDefaultOverworldUnderground(biomeBuilder);
        biomeBuilder.surfaceBuilder(MwConfiguredSurfaceBuilders.VOLCANIC_WASTELAND)
                .addFeature(GenerationStep.Decoration.SURFACE_STRUCTURES, Features.DELTA)
                .addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, Features.SPRING_LAVA_DOUBLE)
                .addFeature(GenerationStep.Decoration.UNDERGROUND_DECORATION, Features.SPRING_DELTA)
                .addFeature(GenerationStep.Decoration.UNDERGROUND_DECORATION, Features.ORE_MAGMA)
                .addFeature(GenerationStep.Decoration.UNDERGROUND_DECORATION, Features.SPRING_CLOSED_DOUBLE);
  //Add custom CF
biomeBuilder.addFeature(GenerationStep.Decoration.SURFACE_STRUCTURES, ModConfiguredFeatures.SMALL_LAVA_ROCK_COLUMNS);
  
        var temperature = 10.0F;
        var ashColor = 0x333333;

        return new Biome.BiomeBuilder()
                .precipitation(Biome.Precipitation.NONE)
                .biomeCategory(Biome.BiomeCategory.DESERT)
                .depth(0.25F)
                .scale(0.1F)
                .temperature(temperature)
                .downfall(0.0F)
                .specialEffects(
                        new BiomeSpecialEffects.Builder()
                                .waterColor(ashColor)
                                .waterFogColor(ashColor)
                                .fogColor(ashColor)
                                .foliageColorOverride(ashColor)
                                .grassColorOverride(ashColor)
                                .skyColor(calculateSkyColor(temperature))
                                .ambientParticle(new AmbientParticleSettings(ParticleTypes.WHITE_ASH, 0.118093334F))
                                .ambientMoodSound(AmbientMoodSettings.LEGACY_CAVE_SETTINGS)
                            .build())
                .mobSpawnSettings(mobSpawnSettings)
                .generationSettings(biomeBuilder.build())
                .build();
}

which I register on the Biome Registry from the main mod constructor

var eventBus = FMLJavaModLoadingContext.get().getModEventBus();

MOD_FEATURES.register(eventBus);
MOD_BIOMES.register(eventBus);

and here is were I store the Biomes

//Registry
public static final DeferredRegister<Biome> MOD_BIOMES = DeferredRegister.create(ForgeRegistries.BIOMES, MOD_ID);
  
//Biomes
public static final RegistryObject<Biome> VOLCANIC_WASTELAND = register("volcanic_wasteland", BiomeUtils::volcanicWasteland);
  
//Register Biome
public static RegistryObject<Biome> register(String name, Supplier<Biome> biomeSupplier) {
  return REGISTRY.register(name, biomeSupplier);
}

Finally, during FMLCommonSetupEvent I add the Biome to the BiomeDictionary

@SubscribeEvent
public static void onCommonSetup(final FMLCommonSetupEvent event) {
  ...
  event.enqueueWork(CommonSetupSubscriber::addVolcanicWastelandBiome);
}

private static void addVolcanicWastelandBiome() {
  var key = ResourceKey.create(ForgeRegistries.Keys.BIOMES, 	Objects.requireNonNull(ForgeRegistries.BIOMES).getKey(ModBiomes.VOLCANIC_WASTELAND.get()));
        BiomeDictionary.addTypes(key, BiomeDictionary.Type.HOT, BiomeDictionary.Type.DRY,
                BiomeDictionary.Type.WASTELAND, BiomeDictionary.Type.DEAD);
        BiomeManager.addBiome(BiomeManager.BiomeType.DESERT, new BiomeManager.BiomeEntry(key, 70));
}

This is the full debug log I have. I noticed that error is actually thrown by another method (the appleForest method is used to create another mod biome). I guess is called when the Mod feature hasn't been registered yet, so it crashes?

 

  Reveal hidden contents

 

Don't blame me if i always ask for your help. I just want to learn to be better :)

Posted

Ok, so adding custom features during the BiomeLoadingEvent (essentialy what I already do for flowers/tree generation) solves the issue. However I'm curious to know more about the json Biomes. Where can I find some details about this system? Will this allow me to add biomes to the game without even writing code (so just the Json file)? I looked on the documentation but found nothing about it :/

Don't blame me if i always ask for your help. I just want to learn to be better :)

Posted

if you add the Biomes via json you need only need a ResourceKey
if you want to add the Biome to the Overworld you still need a RegistryObject

for more information about how to create a json Biome you can look here

Posted

So essentially I need the RegistryObject just for overworld biomes? For instance, if I have a custom dimension or want to add new Biomes to Nether/End I can just register the key and then handle everything via the Json? I assume this excludes features, so if I want my custom feature to be generated inside the Biome I still need to code it like I'm doing now, right? Just I won't need to add it through code in the BiomeLoadingEvent?

Don't blame me if i always ask for your help. I just want to learn to be better :)

Posted
  On 11/10/2021 at 3:11 PM, JimiIT92 said:

So essentially I need the RegistryObject just for overworld biomes?

Expand  

yes since BiomeManager#addAdditionalOverworldBiomes requierd that the Biome is registerd via the RegistryEvent or DeferredRegister

  On 11/10/2021 at 3:11 PM, JimiIT92 said:

For instance, if I have a custom dimension or want to add new Biomes to Nether/End I can just register the key and then handle everything via the Json? I assume this excludes features, so if I want my custom feature to be generated inside the Biome I still need to code it like I'm doing now, right? Just I won't need to add it through code in the BiomeLoadingEvent?

Expand  

yes and yes

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.