I'm trying to add a custom tree to my mod. I'm using the following method to register the tree:
//// == ElderTree.java == ////
public class ElderTree extends Tree {
@Nullable
@Override
protected ConfiguredFeature<BaseTreeFeatureConfig, ?> getTreeFeature(Random randomIn, boolean largeHive) {
return (ConfiguredFeature<BaseTreeFeatureConfig, ?>) ModFeatures.ELDER_TREE.get();
}
}
//// == ModFeatures.java == ////
// [...]
public static final Lazy<ConfiguredFeature<? extends IFeatureConfig, ?>> ELDER_TREE = register("elder_tree", () ->
Feature.TREE.withConfiguration(Configs.ELDER_TREE_CONFIG)
.withPlacement(Features.Placements.HEIGHTMAP_PLACEMENT)
.withPlacement(Placements.ELDER_TREE_PLACEMENT)
);
// [...]
public static final class Configs {
public static final BaseTreeFeatureConfig ELDER_TREE_CONFIG;
// [...]
static {
ELDER_TREE_CONFIG = new BaseTreeFeatureConfig.Builder(
new SimpleBlockStateProvider(ModBlocks.ELDER_LOG.get().getDefaultState()),
new SimpleBlockStateProvider(ModBlocks.ELDER_LEAVES.get().getDefaultState()),
// Radius | Offset | Height
new BlobFoliagePlacer(FeatureSpread.create(2), FeatureSpread.create(0), 3),
// Base height | Height Rand A | Height Rand B
new StraightTrunkPlacer(4, 2, 0),
new TwoLayerFeature(1, 0, 1)
)
.setIgnoreVines()
.build();
}
// [...]
}
But whenever I try to grow a sapling or generate a new world, Minecraft crashes with the following exception:
[13:25:21] [Server thread/FATAL] [minecraft/ThreadTaskExecutor]: Error executing task on Server
java.lang.ClassCastException: net.minecraft.world.gen.feature.DecoratedFeatureConfig cannot be cast to net.minecraft.world.gen.feature.BaseTreeFeatureConfig
at net.minecraft.block.trees.Tree.attemptGrowTree(Tree.java:28) ~[forge:?] {re:classloading}
at team.mixxit.allotment.blocks.ModSapling.placeTree(ModSapling.java:50) ~[?:?] {re:classloading}
at team.mixxit.allotment.blocks.ModSapling.grow(ModSapling.java:71) ~[?:?] {re:classloading}
at net.minecraft.item.BoneMealItem.applyBonemeal(BoneMealItem.java:73) ~[forge:?] {re:classloading}
at net.minecraft.item.BoneMealItem.onItemUse(BoneMealItem.java:36) ~[forge:?] {re:classloading}
at net.minecraftforge.common.ForgeHooks.onPlaceItemIntoWorld(ForgeHooks.java:613) ~[forge:?] {re:classloading}
at net.minecraft.item.ItemStack.onItemUse(ItemStack.java:191) ~[forge:?] {re:classloading}
at net.minecraft.server.management.PlayerInteractionManager.func_219441_a(PlayerInteractionManager.java:359) ~[forge:?] {re:classloading}
at net.minecraft.network.play.ServerPlayNetHandler.processTryUseItemOnBlock(ServerPlayNetHandler.java:986) ~[forge:?] {re:classloading}
at net.minecraft.network.play.client.CPlayerTryUseItemOnBlockPacket.processPacket(CPlayerTryUseItemOnBlockPacket.java:45) ~[forge:?] {re:classloading}
at net.minecraft.network.play.client.CPlayerTryUseItemOnBlockPacket.processPacket(CPlayerTryUseItemOnBlockPacket.java:12) ~[forge:?] {re:classloading}
at net.minecraft.network.PacketThreadUtil.lambda$checkThreadAndEnqueue$0(PacketThreadUtil.java:19) ~[forge:?] {re:classloading}
at net.minecraft.util.concurrent.TickDelayedTask.run(TickDelayedTask.java:20) ~[forge:?] {re:classloading}
at net.minecraft.util.concurrent.ThreadTaskExecutor.run(ThreadTaskExecutor.java:139) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.util.concurrent.RecursiveEventLoop.run(RecursiveEventLoop.java:22) ~[forge:?] {re:classloading}
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:758) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:159) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.util.concurrent.ThreadTaskExecutor.driveOne(ThreadTaskExecutor.java:109) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.server.MinecraftServer.driveOneInternal(MinecraftServer.java:741) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.server.MinecraftServer.driveOne(MinecraftServer.java:735) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.util.concurrent.ThreadTaskExecutor.driveUntil(ThreadTaskExecutor.java:122) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.server.MinecraftServer.runScheduledTasks(MinecraftServer.java:721) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.server.MinecraftServer.func_240802_v_(MinecraftServer.java:667) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.server.MinecraftServer.lambda$startServer$0(MinecraftServer.java:233) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_241] {}
It seems that ConfiguredFeature#withPlacement(ConfiguredPlacement<?>) is the culprit, as it adds a DecoratedFeatureConfig to the feature. What is the proper way to add a placement rule to a tree?