188 lines
6.2 KiB
Java
188 lines
6.2 KiB
Java
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.Block;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.chunk.ChunkGenerator;
|
|
|
|
public class HugeFungusFeature extends Feature<HugeFungusConfiguration> {
|
|
private static final float HUGE_PROBABILITY = 0.06F;
|
|
|
|
public HugeFungusFeature(Codec<HugeFungusConfiguration> codec) {
|
|
super(codec);
|
|
}
|
|
|
|
@Override
|
|
public boolean place(FeaturePlaceContext<HugeFungusConfiguration> context) {
|
|
WorldGenLevel worldGenLevel = context.level();
|
|
BlockPos blockPos = context.origin();
|
|
RandomSource randomSource = context.random();
|
|
ChunkGenerator chunkGenerator = context.chunkGenerator();
|
|
HugeFungusConfiguration hugeFungusConfiguration = context.config();
|
|
Block block = hugeFungusConfiguration.validBaseState.getBlock();
|
|
BlockPos blockPos2 = null;
|
|
BlockState blockState = worldGenLevel.getBlockState(blockPos.below());
|
|
if (blockState.is(block)) {
|
|
blockPos2 = blockPos;
|
|
}
|
|
|
|
if (blockPos2 == null) {
|
|
return false;
|
|
} else {
|
|
int i = Mth.nextInt(randomSource, 4, 13);
|
|
if (randomSource.nextInt(12) == 0) {
|
|
i *= 2;
|
|
}
|
|
|
|
if (!hugeFungusConfiguration.planted) {
|
|
int j = chunkGenerator.getGenDepth();
|
|
if (blockPos2.getY() + i + 1 >= j) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
boolean bl = !hugeFungusConfiguration.planted && randomSource.nextFloat() < 0.06F;
|
|
worldGenLevel.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 260);
|
|
this.placeStem(worldGenLevel, randomSource, hugeFungusConfiguration, blockPos2, i, bl);
|
|
this.placeHat(worldGenLevel, randomSource, hugeFungusConfiguration, blockPos2, i, bl);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
private static boolean isReplaceable(WorldGenLevel level, BlockPos pos, HugeFungusConfiguration config, boolean checkConfig) {
|
|
if (level.isStateAtPosition(pos, BlockBehaviour.BlockStateBase::canBeReplaced)) {
|
|
return true;
|
|
} else {
|
|
return checkConfig ? config.replaceableBlocks.test(level, pos) : false;
|
|
}
|
|
}
|
|
|
|
private void placeStem(WorldGenLevel level, RandomSource random, HugeFungusConfiguration config, BlockPos pos, int height, boolean huge) {
|
|
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
|
BlockState blockState = config.stemState;
|
|
int i = huge ? 1 : 0;
|
|
|
|
for (int j = -i; j <= i; j++) {
|
|
for (int k = -i; k <= i; k++) {
|
|
boolean bl = huge && Mth.abs(j) == i && Mth.abs(k) == i;
|
|
|
|
for (int l = 0; l < height; l++) {
|
|
mutableBlockPos.setWithOffset(pos, j, l, k);
|
|
if (isReplaceable(level, mutableBlockPos, config, true)) {
|
|
if (config.planted) {
|
|
if (!level.getBlockState(mutableBlockPos.below()).isAir()) {
|
|
level.destroyBlock(mutableBlockPos, true);
|
|
}
|
|
|
|
level.setBlock(mutableBlockPos, blockState, 3);
|
|
} else if (bl) {
|
|
if (random.nextFloat() < 0.1F) {
|
|
this.setBlock(level, mutableBlockPos, blockState);
|
|
}
|
|
} else {
|
|
this.setBlock(level, mutableBlockPos, blockState);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void placeHat(WorldGenLevel level, RandomSource random, HugeFungusConfiguration config, BlockPos pos, int height, boolean huge) {
|
|
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
|
boolean bl = config.hatState.is(Blocks.NETHER_WART_BLOCK);
|
|
int i = Math.min(random.nextInt(1 + height / 3) + 5, height);
|
|
int j = height - i;
|
|
|
|
for (int k = j; k <= height; k++) {
|
|
int l = k < height - random.nextInt(3) ? 2 : 1;
|
|
if (i > 8 && k < j + 4) {
|
|
l = 3;
|
|
}
|
|
|
|
if (huge) {
|
|
l++;
|
|
}
|
|
|
|
for (int m = -l; m <= l; m++) {
|
|
for (int n = -l; n <= l; n++) {
|
|
boolean bl2 = m == -l || m == l;
|
|
boolean bl3 = n == -l || n == l;
|
|
boolean bl4 = !bl2 && !bl3 && k != height;
|
|
boolean bl5 = bl2 && bl3;
|
|
boolean bl6 = k < j + 3;
|
|
mutableBlockPos.setWithOffset(pos, m, k, n);
|
|
if (isReplaceable(level, mutableBlockPos, config, false)) {
|
|
if (config.planted && !level.getBlockState(mutableBlockPos.below()).isAir()) {
|
|
level.destroyBlock(mutableBlockPos, true);
|
|
}
|
|
|
|
if (bl6) {
|
|
if (!bl4) {
|
|
this.placeHatDropBlock(level, random, mutableBlockPos, config.hatState, bl);
|
|
}
|
|
} else if (bl4) {
|
|
this.placeHatBlock(level, random, config, mutableBlockPos, 0.1F, 0.2F, bl ? 0.1F : 0.0F);
|
|
} else if (bl5) {
|
|
this.placeHatBlock(level, random, config, mutableBlockPos, 0.01F, 0.7F, bl ? 0.083F : 0.0F);
|
|
} else {
|
|
this.placeHatBlock(level, random, config, mutableBlockPos, 5.0E-4F, 0.98F, bl ? 0.07F : 0.0F);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void placeHatBlock(
|
|
LevelAccessor level,
|
|
RandomSource random,
|
|
HugeFungusConfiguration config,
|
|
BlockPos.MutableBlockPos pos,
|
|
float decorationChance,
|
|
float hatChance,
|
|
float weepingVineChance
|
|
) {
|
|
if (random.nextFloat() < decorationChance) {
|
|
this.setBlock(level, pos, config.decorState);
|
|
} else if (random.nextFloat() < hatChance) {
|
|
this.setBlock(level, pos, config.hatState);
|
|
if (random.nextFloat() < weepingVineChance) {
|
|
tryPlaceWeepingVines(pos, level, random);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void placeHatDropBlock(LevelAccessor level, RandomSource random, BlockPos pos, BlockState state, boolean weepingVines) {
|
|
if (level.getBlockState(pos.below()).is(state.getBlock())) {
|
|
this.setBlock(level, pos, state);
|
|
} else if (random.nextFloat() < 0.15) {
|
|
this.setBlock(level, pos, state);
|
|
if (weepingVines && random.nextInt(11) == 0) {
|
|
tryPlaceWeepingVines(pos, level, random);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void tryPlaceWeepingVines(BlockPos pos, LevelAccessor level, RandomSource random) {
|
|
BlockPos.MutableBlockPos mutableBlockPos = pos.mutable().move(Direction.DOWN);
|
|
if (level.isEmptyBlock(mutableBlockPos)) {
|
|
int i = Mth.nextInt(random, 1, 5);
|
|
if (random.nextInt(7) == 0) {
|
|
i *= 2;
|
|
}
|
|
|
|
int j = 23;
|
|
int k = 25;
|
|
WeepingVinesFeature.placeWeepingVinesColumn(level, random, mutableBlockPos, i, 23, 25);
|
|
}
|
|
}
|
|
}
|