Advertisement
jayhillx

wisteriatreefeature

Feb 25th, 2025
546
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.69 KB | None | 0 0
  1. package com.dreamlands.common.world.feature.tree;
  2.  
  3. import com.dreamlands.common.block.CloverBlock;
  4. import com.dreamlands.common.block.DreamLeavesBlock;
  5. import com.dreamlands.common.block.WisteriaBlock;
  6. import com.dreamlands.common.world.feature.config.DreamTreeConfiguration;
  7. import com.dreamlands.init.DreamBlocks;
  8. import com.mojang.serialization.Codec;
  9. import net.minecraft.core.BlockPos;
  10. import net.minecraft.core.Direction;
  11. import net.minecraft.tags.BlockTags;
  12. import net.minecraft.util.RandomSource;
  13. import net.minecraft.world.level.LevelAccessor;
  14. import net.minecraft.world.level.WorldGenLevel;
  15. import net.minecraft.world.level.block.state.BlockState;
  16. import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
  17.  
  18. import java.util.ArrayList;
  19. import java.util.List;
  20.  
  21. public class WisteriaTreeFeature extends DreamTreeFeature {
  22.  
  23.     public WisteriaTreeFeature(Codec<DreamTreeConfiguration> codec) {
  24.         super(codec);
  25.     }
  26.  
  27.     @Override
  28.     public boolean place(FeaturePlaceContext<DreamTreeConfiguration> context) {
  29.         WorldGenLevel level = context.level();
  30.         RandomSource random = context.random();
  31.         BlockPos initialPos = context.origin();
  32.         DreamTreeConfiguration config = context.config();
  33.  
  34.         int trunkHeight = config.minimumHeight + random.nextInt(config.additionalHeight);
  35.  
  36.         for (int currentY = 0; currentY <= trunkHeight; currentY++) {
  37.             this.placeTrunk(level, initialPos, random, config, currentY, false);
  38.  
  39.             if (currentY == trunkHeight) {
  40.                 this.generateLeaves(level, initialPos.above(currentY), random, config, 2, 2, 48);
  41.             }
  42.  
  43.             if (currentY == trunkHeight - 4) {
  44.                 Direction direction = Direction.Plane.HORIZONTAL.getRandomDirection(random);
  45.                 this.generateBranch(level, this.getBranchPos(initialPos.above(currentY), direction, random, false), random, config, direction, 3);
  46.  
  47.                 if (trunkHeight > 8) {
  48.                     this.generateBranch(level, this.getBranchPos(initialPos.below().above(currentY), direction.getOpposite(), random, false), random, config, direction.getOpposite(), 2);
  49.                 }
  50.             }
  51.         }
  52.  
  53.         /// place wisteria petals beneath the tree.
  54.         this.placeFallenPetals(level, initialPos, random, 5);
  55.         return level.getBlockState(initialPos.below()).is(BlockTags.DIRT);
  56.     }
  57.  
  58.     protected void generateBranch(LevelAccessor level, BlockPos branchPos, RandomSource random, DreamTreeConfiguration config, Direction direction, int branchLength) {
  59.         BlockPos.MutableBlockPos mutablePos = branchPos.mutable();
  60.         mutablePos.set(branchPos);
  61.  
  62.         BlockPos branchEndPos = branchPos.relative(direction, branchLength).above(2);
  63.         for (int i = 0; i < branchLength - 1; ++i) {
  64.             mutablePos.set(branchPos.relative(direction, i));
  65.             this.placeLog(level, mutablePos, random, config, direction.getAxis());
  66.         }
  67.  
  68.         Direction verticalDirection = branchEndPos.getY() > mutablePos.getY() ? Direction.UP : Direction.DOWN;
  69.         while (true) {
  70.             int distanceToTarget = mutablePos.distManhattan(branchEndPos);
  71.             if (distanceToTarget == 0) {
  72.                 this.placeLog(level, mutablePos.above(), random, config, Direction.Axis.Y);
  73.                 this.generateLeaves(level, mutablePos, random, config, 1, 2, 28);
  74.                 return;
  75.             }
  76.  
  77.             float f = (float) Math.abs(branchEndPos.getY() - mutablePos.getY()) / (float) distanceToTarget;
  78.             boolean flag = random.nextFloat() < f;
  79.             mutablePos.move(flag ? verticalDirection : direction);
  80.             this.placeLog(level, mutablePos, random, config, flag ? verticalDirection.getAxis() : direction.getAxis());
  81.         }
  82.     }
  83.  
  84.     protected void generateLeaves(LevelAccessor level, BlockPos pos, RandomSource random, DreamTreeConfiguration config, int foliageRadius, int foliageHeight, int attempts) {
  85.         List<BlockPos> leavesPositions = new ArrayList<>();
  86.         for (int height = 0; height <= foliageHeight; height++) {
  87.             for (int radius = 0; radius <= foliageRadius; radius++) { /// create the core middle blob of leaves for the tree.
  88.                 for (Direction direction : Direction.Plane.HORIZONTAL) {
  89.                     BlockPos relativePos = pos.above(height).relative(direction, radius);
  90.                     this.placeLeaves(level, pos.above(height), random, config, leavesPositions);
  91.                     this.placeLeaves(level, relativePos, random, config, leavesPositions);
  92.                     this.placeLeaves(level, relativePos.relative(direction.getClockWise()), random, config, leavesPositions);
  93.                     this.placeLeaves(level, relativePos.relative(direction.getCounterClockWise()), random, config, leavesPositions);
  94.                 }
  95.             }
  96.  
  97.             BlockPos.MutableBlockPos mutablePos = pos.mutable();
  98.             for (int i = 0; i < attempts; i++) {
  99.                 int radius = !(height <= 0) && height != foliageHeight ? 2 : 1; /// make random foliage radius wider only in the midsection of the tree.
  100.                 mutablePos.setWithOffset(pos, random.nextInt(foliageRadius + radius) - random.nextInt(foliageRadius + radius), random.nextInt(foliageHeight), random.nextInt(foliageRadius + radius) - random.nextInt(foliageRadius + radius));
  101.  
  102.                 for (Direction direction : Direction.Plane.HORIZONTAL) {
  103.                     if (level.getBlockState(mutablePos.relative(direction)).is(BlockTags.LEAVES)) {
  104.                         this.placeLeaves(level, mutablePos.above(height), random, config, leavesPositions);
  105.                     }
  106.                 }
  107.             }
  108.         }
  109.  
  110.         for (BlockPos leafPos : leavesPositions) { /// place hanging wisteria under the trees leaves.
  111.             this.placeHangingWisteria(level, leafPos, random);
  112.         }
  113.     }
  114.  
  115.     /**
  116.      * temporary fix for placing a tree decorator, this gets all the leaves being placed for the tree to be able to be sorted through.
  117.      */
  118.     private void placeLeaves(LevelAccessor level, BlockPos pos, RandomSource random, DreamTreeConfiguration config, List<BlockPos> list) {
  119.         this.placeLeaves(level, pos, random, config);
  120.         list.add(pos);
  121.     }
  122.  
  123.     private void placeHangingWisteria(LevelAccessor level, BlockPos pos, RandomSource random) {
  124.         BlockPos belowPos = pos.below();
  125.         if (level.getBlockState(belowPos).isAir() && (level.getBlockState(belowPos.below()).isAir() || level.getBlockState(belowPos.below()).is(BlockTags.LOGS))) {
  126.             level.setBlock(belowPos, DreamBlocks.WISTERIA_BLOSSOMS.get().defaultBlockState().setValue(DreamLeavesBlock.DISTANCE, 1), 2);
  127.  
  128.             int length = 2 + random.nextInt(random.nextDouble() < 0.4D ? 2 : 1);
  129.             BlockPos currentPos = belowPos;
  130.             for (int i = 0; i < length; i++) {
  131.                 currentPos = currentPos.below();
  132.                 if (!level.getBlockState(currentPos).isAir()) {
  133.                     if (level.isEmptyBlock(currentPos.above())) {
  134.                         level.setBlock(currentPos.above(), DreamBlocks.WISTERIA.get().defaultBlockState().setValue(WisteriaBlock.AGE, 25), 2);
  135.                     }
  136.                     return;
  137.                 }
  138.                 level.setBlock(currentPos, DreamBlocks.WISTERIA_PLANT.get().defaultBlockState(), 2);
  139.             }
  140.  
  141.             if (level.isEmptyBlock(currentPos.below())) {
  142.                 level.setBlock(currentPos.below(), DreamBlocks.WISTERIA.get().defaultBlockState().setValue(WisteriaBlock.AGE, 25), 2);
  143.             }
  144.         }
  145.     }
  146.  
  147.     private void placeFallenPetals(LevelAccessor level, BlockPos pos, RandomSource random, int radius) {
  148.         for (int x = -radius; x <= radius; ++x) {
  149.             for (int z = -radius; z <= radius; ++z) {
  150.                 for (int y = -radius; y <= radius; ++y) {
  151.                     if (Math.abs(x) < radius && Math.abs(z) < radius && Math.abs(y) < radius) {
  152.                         BlockPos offsetPos = pos.offset(x, y, z);
  153.  
  154.                         if (random.nextDouble() < 0.8D && level.isEmptyBlock(offsetPos) && level.getBlockState(offsetPos.below()).is(BlockTags.DIRT)) {
  155.                             Direction direction = Direction.Plane.HORIZONTAL.getRandomDirection(random);
  156.                             int amount = random.nextInt(4);
  157.  
  158.                             for (int i = 2; i <= amount; ++i) {
  159.                                 level.setBlock(offsetPos, DreamBlocks.WISTERIA_PETALS.get().defaultBlockState().setValue(CloverBlock.AMOUNT, i).setValue(CloverBlock.FACING, direction), 3);
  160.                             }
  161.                         }
  162.                     }
  163.                 }
  164.             }
  165.         }
  166.     }
  167.  
  168. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement