tutorial:trees
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| tutorial:trees [2021/10/01 01:55] – Fixed some errors in the code voleil | tutorial:trees [2022/12/21 01:40] (current) – 1.19.3 haykam | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ===== Adding Trees [1.17] (Advanced) ===== | + | ===== Adding Trees [1.19.2] (Advanced) ===== |
| It is recommended that you learn how to create a [[tutorial: | It is recommended that you learn how to create a [[tutorial: | ||
| Trees are a great way to expand Minecraft' | Trees are a great way to expand Minecraft' | ||
| Beware that this topic is advanced and preferably you should have decent experience with modding world generation in Minecraft before starting. | Beware that this topic is advanced and preferably you should have decent experience with modding world generation in Minecraft before starting. | ||
| + | |||
| + | Firstly, you need to understand that a '' | ||
| + | You need a feature, in our case '' | ||
| ===== Creating a Simple Tree ===== | ===== Creating a Simple Tree ===== | ||
| ==== Architecture ==== | ==== Architecture ==== | ||
| - | Minecraft' | + | Minecraft' |
| Here's an overview: | Here's an overview: | ||
| Line 21: | Line 24: | ||
| ==== Creating the ConfiguredFeature ==== | ==== Creating the ConfiguredFeature ==== | ||
| We don't need to create a new '' | We don't need to create a new '' | ||
| - | Add this into your '' | + | Add this into your '' |
| <code java> | <code java> | ||
| - | public static final ConfiguredFeature< | + | public static final RegistryEntry< |
| // Configure the feature using the builder | // Configure the feature using the builder | ||
| - | | + | new TreeFeatureConfig.Builder( |
| - | | + | |
| new StraightTrunkPlacer(8, | new StraightTrunkPlacer(8, | ||
| - | | + | |
| - | new SimpleBlockStateProvider(RICH_SAPLING.getDefaultState()), | + | |
| new BlobFoliagePlacer(ConstantIntProvider.create(5), | new BlobFoliagePlacer(ConstantIntProvider.create(5), | ||
| new TwoLayersFeatureSize(1, | new TwoLayersFeatureSize(1, | ||
| - | ).build()) | + | ).build())); |
| - | | + | |
| - | .spreadHorizontally() | + | |
| - | .applyChance(3); | + | |
| - | + | ||
| - | </ | + | |
| - | + | ||
| - | Now we just register the '' | + | |
| - | + | ||
| - | <code java> | + | |
| - | @Override | + | |
| - | public void onInitialize() { | + | |
| - | RegistryKey< | + | |
| - | + | ||
| - | Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, | + | |
| - | + | ||
| - | // You should use the VEGETAL_DECORATION generation step for trees | + | |
| - | BiomeModifications.addFeature(BiomeSelectors.foundInOverworld(), | + | |
| - | } | + | |
| </ | </ | ||
| Line 62: | Line 46: | ||
| <code java> | <code java> | ||
| public class RichSaplingGenerator extends SaplingGenerator { | public class RichSaplingGenerator extends SaplingGenerator { | ||
| - | private final ConfiguredFeature< | ||
| - | |||
| - | public RichSaplingGenerator(ConfiguredFeature<?, | ||
| - | this.feature = (ConfiguredFeature< | ||
| - | } | ||
| - | |||
| @Nullable | @Nullable | ||
| @Override | @Override | ||
| - | protected ConfiguredFeature< | + | protected |
| - | return | + | return |
| } | } | ||
| } | } | ||
| Line 98: | Line 76: | ||
| public static void register() { | public static void register() { | ||
| - | Registry.register(Registry.BLOCK, new Identifier(" | + | Registry.register(Registries.BLOCK, new Identifier(" |
| - | Registry.register(Registry.ITEM, new Identifier(" | + | Registry.register(Registries.ITEM, new Identifier(" |
| } | } | ||
| Line 130: | Line 108: | ||
| @Mixin(TrunkPlacerType.class) | @Mixin(TrunkPlacerType.class) | ||
| public interface TrunkPlacerTypeInvoker { | public interface TrunkPlacerTypeInvoker { | ||
| - | @Invoker | + | @Invoker(" |
| static <P extends TrunkPlacer> | static <P extends TrunkPlacer> | ||
| throw new IllegalStateException(); | throw new IllegalStateException(); | ||
| Line 164: | Line 142: | ||
| public List< | public List< | ||
| // Set the ground beneath the trunk to dirt | // Set the ground beneath the trunk to dirt | ||
| - | this.setToDirt(world, | + | setToDirt(world, |
| | | ||
| // Iterate until the trunk height limit and place two blocks using the getAndSetState method from TrunkPlacer | // Iterate until the trunk height limit and place two blocks using the getAndSetState method from TrunkPlacer | ||
| Line 185: | Line 163: | ||
| <code java> | <code java> | ||
| - | public static final TrunkPlacerType< | + | public static final TrunkPlacerType< |
| </ | </ | ||
| Line 242: | Line 220: | ||
| public static final Codec< | public static final Codec< | ||
| fillFoliagePlacerFields(instance) | fillFoliagePlacerFields(instance) | ||
| - | .and(IntProvider.createValidatingCodec(1, | + | .and(IntProvider.createValidatingCodec(1, |
| .apply(instance, | .apply(instance, | ||
| Line 299: | Line 277: | ||
| <code java> | <code java> | ||
| - | public static final FoliagePlacerType< | + | public static final FoliagePlacerType< |
| </ | </ | ||
| Line 351: | Line 329: | ||
| // Our constructor doesn' | // Our constructor doesn' | ||
| public static final Codec< | public static final Codec< | ||
| + | | ||
| + | private RichTreeDecorator() {} | ||
| @Override | @Override | ||
| Line 358: | Line 338: | ||
| @Override | @Override | ||
| - | public void generate(TestableWorld world, BiConsumer< | + | public void generate(TreeDecorator.Generator generator) { |
| // Iterate through block positions | // Iterate through block positions | ||
| - | | + | |
| + | Random random = generator.getRandom(); | ||
| // Pick a value from 0 (inclusive) to 4 (exclusive) and if it's 0, continue | // Pick a value from 0 (inclusive) to 4 (exclusive) and if it's 0, continue | ||
| // This is the chance for spawning the gold block | // This is the chance for spawning the gold block | ||
| Line 381: | Line 362: | ||
| replacer.accept(targetPosition, | replacer.accept(targetPosition, | ||
| } | } | ||
| - | } | + | }); |
| } | } | ||
| } | } | ||
| Line 390: | Line 371: | ||
| <code java> | <code java> | ||
| - | public static final TreeDecoratorType< | + | public static final TreeDecoratorType< |
| </ | </ | ||
| Line 407: | Line 388: | ||
| <code java> | <code java> | ||
| public class RichSaplingGenerator extends SaplingGenerator { | public class RichSaplingGenerator extends SaplingGenerator { | ||
| - | private final ConfiguredFeature< | ||
| - | |||
| - | public RichSaplingGenerator(ConfiguredFeature<?, | ||
| - | this.feature = (ConfiguredFeature< | ||
| - | } | ||
| - | |||
| @Nullable | @Nullable | ||
| @Override | @Override | ||
| - | protected ConfiguredFeature< | + | protected |
| int chance = random.nextInt(100); | int chance = random.nextInt(100); | ||
| | | ||
| // Each tree has a 10% chance | // Each tree has a 10% chance | ||
| - | | + | |
| - | | + | case 10 -> TreeConfiguredFeatures.OAK; |
| - | } else if (chance < 20) { | + | |
| - | return ConfiguredFeatures.BIRCH; | + | case 30 -> TreeConfiguredFeatures.MEGA_SPRUCE; |
| - | } else if (chance < 60) { | + | |
| - | return ConfiguredFeatures.SPRUCE; | + | |
| - | } else if (chance < 40) { | + | |
| - | return ConfiguredFeatures.MEGA_SPRUCE; | + | |
| - | } else if (chance < 50) { | + | |
| - | return ConfiguredFeatures.PINE; | + | |
| - | } else if (chance < 60) { | + | |
| - | return ConfiguredFeatures.MEGA_PINE; | + | |
| - | } else if (chance < 70) { | + | |
| - | return ConfiguredFeatures.MEGA_JUNGLE_TREE; | + | |
| } | } | ||
| - | + | } | |
| - | // If none of that happened (the random value was between 70 and 100), create the actual tree | + | |
| - | return feature; | + | |
| - | } | + | |
| } | } | ||
| </ | </ | ||
| Line 452: | Line 418: | ||
| <code java> | <code java> | ||
| [...] | [...] | ||
| - | .dirtProvider(new SimpleBlockStateProvider(Blocks.IRON_BLOCK.getDefaultState())) | + | .dirtProvider(BlockStateProvider.of(Blocks.IRON_BLOCK)) |
| [...] | [...] | ||
| </ | </ | ||
tutorial/trees.1633053342.txt.gz · Last modified: 2021/10/01 01:55 by voleil