package net.minecraft.world.level.levelgen.feature; import com.mojang.serialization.Codec; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.GrowingPlantHeadBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.feature.configurations.TwistingVinesConfig; public class TwistingVinesFeature extends Feature { public TwistingVinesFeature(Codec codec) { super(codec); } @Override public boolean place(FeaturePlaceContext context) { WorldGenLevel worldGenLevel = context.level(); BlockPos blockPos = context.origin(); if (isInvalidPlacementLocation(worldGenLevel, blockPos)) { return false; } else { RandomSource randomSource = context.random(); TwistingVinesConfig twistingVinesConfig = context.config(); int i = twistingVinesConfig.spreadWidth(); int j = twistingVinesConfig.spreadHeight(); int k = twistingVinesConfig.maxHeight(); BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); for (int l = 0; l < i * i; l++) { mutableBlockPos.set(blockPos).move(Mth.nextInt(randomSource, -i, i), Mth.nextInt(randomSource, -j, j), Mth.nextInt(randomSource, -i, i)); if (findFirstAirBlockAboveGround(worldGenLevel, mutableBlockPos) && !isInvalidPlacementLocation(worldGenLevel, mutableBlockPos)) { int m = Mth.nextInt(randomSource, 1, k); if (randomSource.nextInt(6) == 0) { m *= 2; } if (randomSource.nextInt(5) == 0) { m = 1; } int n = 17; int o = 25; placeWeepingVinesColumn(worldGenLevel, randomSource, mutableBlockPos, m, 17, 25); } } return true; } } private static boolean findFirstAirBlockAboveGround(LevelAccessor level, BlockPos.MutableBlockPos pos) { do { pos.move(0, -1, 0); if (level.isOutsideBuildHeight(pos)) { return false; } } while (level.getBlockState(pos).isAir()); pos.move(0, 1, 0); return true; } public static void placeWeepingVinesColumn(LevelAccessor level, RandomSource random, BlockPos.MutableBlockPos pos, int length, int minAge, int maxAge) { for (int i = 1; i <= length; i++) { if (level.isEmptyBlock(pos)) { if (i == length || !level.isEmptyBlock(pos.above())) { level.setBlock(pos, Blocks.TWISTING_VINES.defaultBlockState().setValue(GrowingPlantHeadBlock.AGE, Mth.nextInt(random, minAge, maxAge)), 2); break; } level.setBlock(pos, Blocks.TWISTING_VINES_PLANT.defaultBlockState(), 2); } pos.move(Direction.UP); } } private static boolean isInvalidPlacementLocation(LevelAccessor level, BlockPos pos) { if (!level.isEmptyBlock(pos)) { return true; } else { BlockState blockState = level.getBlockState(pos.below()); return !blockState.is(Blocks.NETHERRACK) && !blockState.is(Blocks.WARPED_NYLIUM) && !blockState.is(Blocks.WARPED_WART_BLOCK); } } }