This repository was archived by the owner on Feb 18, 2024. It is now read-only.
forked from CivClassic/RealisticBiomes
-
Notifications
You must be signed in to change notification settings - Fork 5
Add NMS feature growers #39
Open
rosacarmesin
wants to merge
5
commits into
CivMC:master
Choose a base branch
from
rosacarmesin:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,3 +10,4 @@ dependency-reduced-pom.xml | |
| .gradle | ||
| build | ||
| libs/ | ||
| paper/run | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
188 changes: 188 additions & 0 deletions
188
paper/src/main/java/com/untamedears/realisticbiomes/growth/NMSFeatureGrower.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,188 @@ | ||
| package com.untamedears.realisticbiomes.growth; | ||
|
|
||
| import java.util.Iterator; | ||
| import java.util.Random; | ||
|
|
||
| import org.bukkit.Material; | ||
| import org.bukkit.block.Block; | ||
| import org.bukkit.block.data.type.Sapling; | ||
| import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock; | ||
|
|
||
| import com.untamedears.realisticbiomes.model.Plant; | ||
|
|
||
| import net.minecraft.core.BlockPos; | ||
| import net.minecraft.data.worldgen.features.TreeFeatures; | ||
| import net.minecraft.server.level.ServerLevel; | ||
| import net.minecraft.tags.BlockTags; | ||
| import net.minecraft.world.level.LevelAccessor; | ||
| import net.minecraft.world.level.block.Blocks; | ||
| import net.minecraft.world.level.block.grower.AbstractMegaTreeGrower; | ||
| import net.minecraft.world.level.block.state.BlockState; | ||
| import net.minecraft.world.level.chunk.ChunkGenerator; | ||
| import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; | ||
|
|
||
| public class NMSFeatureGrower extends AgeableGrower { | ||
|
|
||
| public NMSFeatureGrower(Material material) { | ||
| super(material, 1, 1); | ||
| } | ||
|
|
||
| private boolean isMega; | ||
|
|
||
|
|
||
|
|
||
|
|
||
| @Override | ||
| public int getStage(Plant plant) { | ||
| Block block = plant.getLocation().getBlock(); | ||
| if (block.getType() != this.material) { | ||
| return -1; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean setStage(Plant plant, int stage) { | ||
| if (stage < 1) { | ||
| return true; | ||
| } | ||
| Block block = plant.getLocation().getBlock(); | ||
| // Re-Read the block data to make sure it is up to date | ||
| if (!(block.getBlockData() instanceof Sapling||block.getBlockData().getMaterial() == Material.FLOWERING_AZALEA)) { | ||
| return true; | ||
| } | ||
|
|
||
|
|
||
| CraftBlock cBlock = (CraftBlock) block; | ||
| BlockPos pos = cBlock.getPosition(); | ||
| ServerLevel spWorld = cBlock.getCraftWorld().getHandle(); | ||
| BlockState spBlock = cBlock.getNMS(); | ||
|
|
||
| this.growTreeFeature(spWorld, spWorld.getChunkSource().getGenerator(), pos, spBlock, new Random()); | ||
| return true; | ||
| } | ||
|
|
||
| public boolean growTreeFeature( | ||
| ServerLevel world, | ||
| ChunkGenerator chunkGenerator, | ||
| BlockPos pos, | ||
| BlockState state, | ||
| Random random) { | ||
| isMega = false; | ||
| if(placeMegaTree(world, chunkGenerator, pos, state, random)) {return true;}; | ||
| if(isMega) return false; // fail tree growth here if it's a mega tree and it hasn't returned true above | ||
| ConfiguredFeature<?, ?> feature; | ||
| ConfiguredFeature<?, ?> featureSmall; | ||
| //feature holds the default Minecraft tree and featureSmall holds a version with randomHeight set to 0 so that it will grow at minimum height | ||
| switch(state.getBukkitMaterial()) { | ||
| case JUNGLE_SAPLING: | ||
| feature = TreeFeatures.JUNGLE_TREE_NO_VINE.value(); | ||
| featureSmall = RBFeatures.SHORT_JUNGLE.value(); | ||
| break; | ||
| case SPRUCE_SAPLING: | ||
| feature = TreeFeatures.SPRUCE.value(); | ||
| featureSmall = RBFeatures.SHORT_SPRUCE.value(); | ||
| break; | ||
| case OAK_SAPLING: | ||
| feature = this.hasFlowers(world, pos) ? TreeFeatures.OAK_BEES_005.value() : TreeFeatures.OAK.value(); | ||
| featureSmall = this.hasFlowers(world, pos) ? RBFeatures.SHORT_OAK_BEES.value() : RBFeatures.SHORT_OAK.value(); | ||
| break; | ||
| case BIRCH_SAPLING: | ||
| feature = this.hasFlowers(world, pos) ? TreeFeatures.BIRCH_BEES_005.value() : TreeFeatures.BIRCH.value(); | ||
| featureSmall = this.hasFlowers(world, pos) ? RBFeatures.SHORT_BIRCH_BEES.value() : RBFeatures.SHORT_BIRCH.value(); | ||
| break; | ||
| case ACACIA_SAPLING: | ||
| feature = TreeFeatures.ACACIA.value(); | ||
| featureSmall = RBFeatures.SHORT_ACACIA.value(); | ||
| break; | ||
| case FLOWERING_AZALEA: | ||
| feature = TreeFeatures.AZALEA_TREE.value(); | ||
| featureSmall = RBFeatures.SHORT_AZALEA_TREE.value(); | ||
| break; | ||
| case DARK_OAK_SAPLING: //completly unecessary only left this in for the sake of completion tbh | ||
| default: | ||
| return false; | ||
| } | ||
| world.setBlock(pos, Blocks.AIR.defaultBlockState(), 4); | ||
| if (feature.place(world, chunkGenerator, random, pos)) { //attempt to place the normal tree feature | ||
| return true; | ||
| } else if(featureSmall.place(world, chunkGenerator, random, pos)) { //attempt to place the small/short version if the normal fails | ||
| return true; | ||
| } else { | ||
| world.setBlock(pos, state, 4); //replace the sappling if both fail | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| private boolean placeMegaTree(ServerLevel world, ChunkGenerator chunkGenerator, BlockPos pos, BlockState state, Random random) { | ||
| ConfiguredFeature<?, ?> feature; | ||
| ConfiguredFeature<?, ?> featureSmall; | ||
| //feature holds the default minecraft tree and featuresmall holds a version with randomHeight set to 0 so that it will grow at minimum height | ||
| switch(state.getBukkitMaterial()) { | ||
| case JUNGLE_SAPLING: | ||
| feature = TreeFeatures.MEGA_JUNGLE_TREE.value(); | ||
| featureSmall = RBFeatures.SHORT_MEGA_JUNGLE.value(); | ||
| break; | ||
| case SPRUCE_SAPLING: | ||
| feature = TreeFeatures.MEGA_SPRUCE.value(); | ||
| featureSmall = RBFeatures.SHORT_MEGA_SPRUCE.value(); | ||
| break; | ||
| case DARK_OAK_SAPLING: | ||
| feature = TreeFeatures.DARK_OAK.value(); | ||
| featureSmall = RBFeatures.SHORT_DARK_OAK.value(); | ||
| break; | ||
| default: | ||
| return false; | ||
| } | ||
| for (int i = 0; i >= -1; --i) { | ||
| for (int j = 0; j >= -1; --j) { | ||
| if (AbstractMegaTreeGrower.isTwoByTwoSapling(state, world, pos, i, j)) { | ||
| isMega = true; //set ismega so that function above can know when a tree is 2x2 and has failed growth (admitedly this is probs not the best solution) | ||
| BlockState air = Blocks.AIR.defaultBlockState(); | ||
| world.setBlock(pos.offset(i, 0, j), air, 4); //remove saplings | ||
| world.setBlock(pos.offset(i + 1, 0, j), air, 4); | ||
| world.setBlock(pos.offset(i, 0, j + 1), air, 4); | ||
| world.setBlock(pos.offset(i + 1, 0, j + 1), air, 4); | ||
| if (feature.place(world, chunkGenerator, random, pos.offset(i, 0, j))) { | ||
| return true; | ||
| } else if(featureSmall.place(world, chunkGenerator, random, pos.offset(i, 0, j))){ //try placing short tree if normal tree fails | ||
| return true; | ||
| } else { | ||
| world.setBlock(pos.offset(i, 0, j), state, 4); //replace saplings if both fail | ||
| world.setBlock(pos.offset(i + 1, 0, j), state, 4); | ||
| world.setBlock(pos.offset(i, 0, j + 1), state, 4); | ||
| world.setBlock(pos.offset(i + 1, 0, j + 1), state, 4); | ||
| return false ; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| private boolean hasFlowers(LevelAccessor world, BlockPos pos) { //straight up pulled from nms code | ||
| Iterator iterator = BlockPos.MutableBlockPos.betweenClosed(pos.below().north(2).west(2), pos.above().south(2).east(2)).iterator(); | ||
|
|
||
| BlockPos blockposition1; | ||
|
|
||
| do { | ||
| if (!iterator.hasNext()) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this iterator loop be better as a |
||
| return false; | ||
| } | ||
|
|
||
| blockposition1 = (BlockPos) iterator.next(); | ||
| } while (!world.getBlockState(blockposition1).is(BlockTags.FLOWERS)); | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
| @Override | ||
| public boolean deleteOnFullGrowth() { | ||
| return true; | ||
| } | ||
|
|
||
|
|
||
| } | ||
131 changes: 131 additions & 0 deletions
131
paper/src/main/java/com/untamedears/realisticbiomes/growth/RBFeatures.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| package com.untamedears.realisticbiomes.growth; | ||
|
|
||
| import java.util.List; | ||
| import java.util.OptionalInt; | ||
|
|
||
| import com.google.common.collect.ImmutableList; | ||
|
|
||
| import net.minecraft.core.Holder; | ||
| import net.minecraft.data.worldgen.features.FeatureUtils; | ||
| import net.minecraft.util.random.SimpleWeightedRandomList; | ||
| import net.minecraft.util.valueproviders.ConstantInt; | ||
| import net.minecraft.util.valueproviders.UniformInt; | ||
| import net.minecraft.world.level.block.Blocks; | ||
| import net.minecraft.world.level.block.state.BlockState; | ||
| import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; | ||
| import net.minecraft.world.level.levelgen.feature.Feature; | ||
| import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration; | ||
| import net.minecraft.world.level.levelgen.feature.featuresize.ThreeLayersFeatureSize; | ||
| import net.minecraft.world.level.levelgen.feature.featuresize.TwoLayersFeatureSize; | ||
| import net.minecraft.world.level.levelgen.feature.foliageplacers.AcaciaFoliagePlacer; | ||
| import net.minecraft.world.level.levelgen.feature.foliageplacers.BlobFoliagePlacer; | ||
| import net.minecraft.world.level.levelgen.feature.foliageplacers.DarkOakFoliagePlacer; | ||
| import net.minecraft.world.level.levelgen.feature.foliageplacers.MegaJungleFoliagePlacer; | ||
| import net.minecraft.world.level.levelgen.feature.foliageplacers.MegaPineFoliagePlacer; | ||
| import net.minecraft.world.level.levelgen.feature.foliageplacers.RandomSpreadFoliagePlacer; | ||
| import net.minecraft.world.level.levelgen.feature.foliageplacers.SpruceFoliagePlacer; | ||
| import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider; | ||
| import net.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider; | ||
| import net.minecraft.world.level.levelgen.feature.treedecorators.AlterGroundDecorator; | ||
| import net.minecraft.world.level.levelgen.feature.treedecorators.BeehiveDecorator; | ||
| import net.minecraft.world.level.levelgen.feature.treedecorators.LeaveVineDecorator; | ||
| import net.minecraft.world.level.levelgen.feature.treedecorators.TrunkVineDecorator; | ||
| import net.minecraft.world.level.levelgen.feature.trunkplacers.BendingTrunkPlacer; | ||
| import net.minecraft.world.level.levelgen.feature.trunkplacers.DarkOakTrunkPlacer; | ||
| import net.minecraft.world.level.levelgen.feature.trunkplacers.ForkingTrunkPlacer; | ||
| import net.minecraft.world.level.levelgen.feature.trunkplacers.GiantTrunkPlacer; | ||
| import net.minecraft.world.level.levelgen.feature.trunkplacers.MegaJungleTrunkPlacer; | ||
| import net.minecraft.world.level.levelgen.feature.trunkplacers.StraightTrunkPlacer; | ||
|
|
||
| //manage NMS Configured features for RB | ||
| public class RBFeatures { | ||
|
|
||
|
|
||
| private static TreeConfiguration.TreeConfigurationBuilder createStraightBlobTree( | ||
| net.minecraft.world.level.block.Block log, net.minecraft.world.level.block.Block leaves, | ||
| int baseHeight, int radius) { | ||
| return new TreeConfiguration.TreeConfigurationBuilder(BlockStateProvider.simple(log), new StraightTrunkPlacer(baseHeight, 0, 0), BlockStateProvider.simple(leaves), new BlobFoliagePlacer(ConstantInt.of(radius), ConstantInt.of(0), 3), new TwoLayersFeatureSize(1, 0, 1)); | ||
| } | ||
| //tree features: | ||
|
|
||
| //beehive with 5% chance of generating | ||
| private static final BeehiveDecorator BEEHIVE_005 = new BeehiveDecorator(0.05F); | ||
| //Short oak tree feature, short meaning the tree will grow at the smallest size vanilla does | ||
| public static final Holder<ConfiguredFeature<TreeConfiguration, ?>> SHORT_OAK = | ||
| FeatureUtils.register("short_oak", Feature.TREE, createStraightBlobTree | ||
| (Blocks.OAK_LOG, Blocks.OAK_LEAVES, 4, 2).build()); | ||
| //Short birch tree feature | ||
| public static final Holder<ConfiguredFeature<TreeConfiguration, ?>> SHORT_BIRCH = | ||
| FeatureUtils.register("short_birch", Feature.TREE, createStraightBlobTree | ||
| (Blocks.BIRCH_LOG, Blocks.BIRCH_LEAVES, 5, 2).build()); | ||
| //Short oak tree with bees feature, the chance for a beehive is vanilla's 5%, but might be worth adding an adjust to config.yaml maybe ? | ||
| public static final Holder<ConfiguredFeature<TreeConfiguration, ?>> SHORT_OAK_BEES = | ||
| FeatureUtils.register("short_oak_bees", Feature.TREE, createStraightBlobTree | ||
| (Blocks.OAK_LOG, Blocks.OAK_LEAVES, 4, 2).decorators(List.of(BEEHIVE_005)).build()); | ||
| //Short birch tree with bees feature | ||
| public static final Holder<ConfiguredFeature<TreeConfiguration, ?>> SHORT_BIRCH_BEES = | ||
| FeatureUtils.register("short_birch_bees", Feature.TREE, createStraightBlobTree | ||
| (Blocks.BIRCH_LOG, Blocks.BIRCH_LEAVES, 5, 2).decorators(List.of(BEEHIVE_005)).build()); | ||
| //short jungle tree feature | ||
| public static final Holder<ConfiguredFeature<TreeConfiguration, ?>> SHORT_JUNGLE = | ||
| FeatureUtils.register("short_jungle", Feature.TREE, createStraightBlobTree | ||
| (Blocks.JUNGLE_LOG, Blocks.JUNGLE_LEAVES, 4, 2).build()); | ||
| //short spruce, this one is a fair bit longer lmao | ||
| //might also be worth adding options to configure type of grower for each tree instead of hard coding ? | ||
| //idk, I am also lazy and don't wanna wrap my head around how the config parser woks | ||
| public static final Holder<ConfiguredFeature<TreeConfiguration, ?>> SHORT_SPRUCE = | ||
| FeatureUtils.register( | ||
| "short_spruce", Feature.TREE, ( | ||
| new TreeConfiguration.TreeConfigurationBuilder(BlockStateProvider.simple(Blocks.SPRUCE_LOG), | ||
| new StraightTrunkPlacer(5, 0, 0), BlockStateProvider.simple(Blocks.SPRUCE_LEAVES), | ||
| new SpruceFoliagePlacer(UniformInt.of(2, 3), UniformInt.of(0, 2), UniformInt.of(1, 2)), | ||
| new TwoLayersFeatureSize(2, 0, 2))).ignoreVines().build()); | ||
| //short acacia | ||
| public static final Holder<ConfiguredFeature<TreeConfiguration, ?>> SHORT_ACACIA = | ||
| FeatureUtils.register( | ||
| "short_acacia", Feature.TREE, ( | ||
| new TreeConfiguration.TreeConfigurationBuilder(BlockStateProvider.simple(Blocks.ACACIA_LOG), | ||
| new ForkingTrunkPlacer(5, 0 ,0), BlockStateProvider.simple(Blocks.ACACIA_LEAVES), | ||
| new AcaciaFoliagePlacer(ConstantInt.of(2), ConstantInt.of(0)), | ||
| new TwoLayersFeatureSize(1, 0, 2))).ignoreVines().build()); | ||
| //short 2x2 jungle tree | ||
| public static final Holder<ConfiguredFeature<TreeConfiguration, ?>> SHORT_MEGA_JUNGLE = | ||
| FeatureUtils.register( | ||
| "short_mega_jungle_tree", Feature.TREE, ( | ||
| new TreeConfiguration.TreeConfigurationBuilder(BlockStateProvider.simple(Blocks.JUNGLE_LOG), | ||
| new MegaJungleTrunkPlacer(10, 0, 0), BlockStateProvider.simple(Blocks.JUNGLE_LEAVES), | ||
| new MegaJungleFoliagePlacer(ConstantInt.of(2), ConstantInt.of(0), 2), | ||
| new TwoLayersFeatureSize(1, 1, 2))). | ||
| decorators(ImmutableList.of(TrunkVineDecorator.INSTANCE, LeaveVineDecorator.INSTANCE)).build()); | ||
| //short 2x2 spruce tree | ||
| //should 2x2 pine tree also be included ? | ||
| public static final Holder<ConfiguredFeature<TreeConfiguration, ?>> SHORT_MEGA_SPRUCE = | ||
| FeatureUtils.register( | ||
| "short_mega_spruce", Feature.TREE, ( | ||
| new TreeConfiguration.TreeConfigurationBuilder(BlockStateProvider.simple(Blocks.SPRUCE_LOG), | ||
| new GiantTrunkPlacer(13, 0, 0), BlockStateProvider.simple(Blocks.SPRUCE_LEAVES), | ||
| new MegaPineFoliagePlacer(ConstantInt.of(0), ConstantInt.of(0), UniformInt.of(13, 17)), //oh maybe this uniformint is why sometimes it still fails to grow with height restriction even with the other things | ||
| new TwoLayersFeatureSize(1, 1, 2))) | ||
| .decorators(ImmutableList.of(new AlterGroundDecorator(BlockStateProvider.simple(Blocks.PODZOL)))).build()); | ||
| //short 2x2 ofc because that's the only way it grows (normally) dark oak tree | ||
| public static final Holder<ConfiguredFeature<TreeConfiguration, ?>> SHORT_DARK_OAK = | ||
| FeatureUtils.register( | ||
| "short_dark_oak", Feature.TREE, ( | ||
| new TreeConfiguration.TreeConfigurationBuilder(BlockStateProvider.simple(Blocks.DARK_OAK_LOG), | ||
| new DarkOakTrunkPlacer(6, 0, 0), BlockStateProvider.simple(Blocks.DARK_OAK_LEAVES), | ||
| new DarkOakFoliagePlacer(ConstantInt.of(0), ConstantInt.of(0)), | ||
| new ThreeLayersFeatureSize(1, 1, 0, 1, 2, OptionalInt.empty()))).ignoreVines().build()); | ||
| //azalea | ||
| public static final Holder<ConfiguredFeature<TreeConfiguration, ?>> SHORT_AZALEA_TREE = | ||
| FeatureUtils.register( | ||
| "short_azalea_tree", Feature.TREE, ( | ||
| new TreeConfiguration.TreeConfigurationBuilder(BlockStateProvider.simple(Blocks.OAK_LOG), | ||
| new BendingTrunkPlacer(4, 0, 0, 3, UniformInt.of(1, 2)), | ||
| new WeightedStateProvider(SimpleWeightedRandomList.<BlockState>builder() | ||
| .add(Blocks.AZALEA_LEAVES.defaultBlockState(), 3).add(Blocks.FLOWERING_AZALEA_LEAVES.defaultBlockState(), 1)), | ||
| new RandomSpreadFoliagePlacer(ConstantInt.of(3), ConstantInt.of(0), ConstantInt.of(2), 50), | ||
| new TwoLayersFeatureSize(1, 0, 1))).dirt(BlockStateProvider.simple(Blocks.ROOTED_DIRT)).forceDirt().build()); | ||
|
|
||
|
|
||
| } | ||
|
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
small note but does NMS not contain a method to do this for us?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specifically checking nearby for flowers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it does but it's private so I copied it over