Code/net/minecraft/world/level/levelgen/feature/GeodeFeature.java

169 lines
8.4 KiB
Java

package net.minecraft.world.level.levelgen.feature;
import com.google.common.collect.Lists;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import java.util.List;
import java.util.function.Predicate;
import net.minecraft.Util;
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.WorldGenLevel;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.BuddingAmethystBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.levelgen.GeodeBlockSettings;
import net.minecraft.world.level.levelgen.GeodeCrackSettings;
import net.minecraft.world.level.levelgen.GeodeLayerSettings;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.feature.configurations.GeodeConfiguration;
import net.minecraft.world.level.levelgen.synth.NormalNoise;
import net.minecraft.world.level.material.FluidState;
public class GeodeFeature extends Feature<GeodeConfiguration> {
private static final Direction[] DIRECTIONS = Direction.values();
public GeodeFeature(Codec<GeodeConfiguration> p_159834_) {
super(p_159834_);
}
@Override
public boolean place(FeaturePlaceContext<GeodeConfiguration> p_159836_) {
GeodeConfiguration geodeconfiguration = p_159836_.config();
RandomSource randomsource = p_159836_.random();
BlockPos blockpos = p_159836_.origin();
WorldGenLevel worldgenlevel = p_159836_.level();
int i = geodeconfiguration.minGenOffset;
int j = geodeconfiguration.maxGenOffset;
List<Pair<BlockPos, Integer>> list = Lists.newLinkedList();
int k = geodeconfiguration.distributionPoints.sample(randomsource);
WorldgenRandom worldgenrandom = new WorldgenRandom(new LegacyRandomSource(worldgenlevel.getSeed()));
NormalNoise normalnoise = NormalNoise.create(worldgenrandom, -4, 1.0);
List<BlockPos> list1 = Lists.newLinkedList();
double d0 = (double)k / geodeconfiguration.outerWallDistance.getMaxValue();
GeodeLayerSettings geodelayersettings = geodeconfiguration.geodeLayerSettings;
GeodeBlockSettings geodeblocksettings = geodeconfiguration.geodeBlockSettings;
GeodeCrackSettings geodecracksettings = geodeconfiguration.geodeCrackSettings;
double d1 = 1.0 / Math.sqrt(geodelayersettings.filling);
double d2 = 1.0 / Math.sqrt(geodelayersettings.innerLayer + d0);
double d3 = 1.0 / Math.sqrt(geodelayersettings.middleLayer + d0);
double d4 = 1.0 / Math.sqrt(geodelayersettings.outerLayer + d0);
double d5 = 1.0 / Math.sqrt(geodecracksettings.baseCrackSize + randomsource.nextDouble() / 2.0 + (k > 3 ? d0 : 0.0));
boolean flag = randomsource.nextFloat() < geodecracksettings.generateCrackChance;
int l = 0;
for (int i1 = 0; i1 < k; i1++) {
int j1 = geodeconfiguration.outerWallDistance.sample(randomsource);
int k1 = geodeconfiguration.outerWallDistance.sample(randomsource);
int l1 = geodeconfiguration.outerWallDistance.sample(randomsource);
BlockPos blockpos1 = blockpos.offset(j1, k1, l1);
BlockState blockstate = worldgenlevel.getBlockState(blockpos1);
if (blockstate.isAir() || blockstate.is(geodeblocksettings.invalidBlocks)) {
if (++l > geodeconfiguration.invalidBlocksThreshold) {
return false;
}
}
list.add(Pair.of(blockpos1, geodeconfiguration.pointOffset.sample(randomsource)));
}
if (flag) {
int i2 = randomsource.nextInt(4);
int j2 = k * 2 + 1;
if (i2 == 0) {
list1.add(blockpos.offset(j2, 7, 0));
list1.add(blockpos.offset(j2, 5, 0));
list1.add(blockpos.offset(j2, 1, 0));
} else if (i2 == 1) {
list1.add(blockpos.offset(0, 7, j2));
list1.add(blockpos.offset(0, 5, j2));
list1.add(blockpos.offset(0, 1, j2));
} else if (i2 == 2) {
list1.add(blockpos.offset(j2, 7, j2));
list1.add(blockpos.offset(j2, 5, j2));
list1.add(blockpos.offset(j2, 1, j2));
} else {
list1.add(blockpos.offset(0, 7, 0));
list1.add(blockpos.offset(0, 5, 0));
list1.add(blockpos.offset(0, 1, 0));
}
}
List<BlockPos> list2 = Lists.newArrayList();
Predicate<BlockState> predicate = isReplaceable(geodeconfiguration.geodeBlockSettings.cannotReplace);
for (BlockPos blockpos3 : BlockPos.betweenClosed(blockpos.offset(i, i, i), blockpos.offset(j, j, j))) {
double d8 = normalnoise.getValue(blockpos3.getX(), blockpos3.getY(), blockpos3.getZ()) * geodeconfiguration.noiseMultiplier;
double d6 = 0.0;
double d7 = 0.0;
for (Pair<BlockPos, Integer> pair : list) {
d6 += Mth.invSqrt(blockpos3.distSqr(pair.getFirst()) + pair.getSecond().intValue()) + d8;
}
for (BlockPos blockpos6 : list1) {
d7 += Mth.invSqrt(blockpos3.distSqr(blockpos6) + geodecracksettings.crackPointOffset) + d8;
}
if (!(d6 < d4)) {
if (flag && d7 >= d5 && d6 < d1) {
this.safeSetBlock(worldgenlevel, blockpos3, Blocks.AIR.defaultBlockState(), predicate);
for (Direction direction1 : DIRECTIONS) {
BlockPos blockpos2 = blockpos3.relative(direction1);
FluidState fluidstate = worldgenlevel.getFluidState(blockpos2);
if (!fluidstate.isEmpty()) {
worldgenlevel.scheduleTick(blockpos2, fluidstate.getType(), 0);
}
}
} else if (d6 >= d1) {
this.safeSetBlock(worldgenlevel, blockpos3, geodeblocksettings.fillingProvider.getState(randomsource, blockpos3), predicate);
} else if (d6 >= d2) {
boolean flag1 = randomsource.nextFloat() < geodeconfiguration.useAlternateLayer0Chance;
if (flag1) {
this.safeSetBlock(worldgenlevel, blockpos3, geodeblocksettings.alternateInnerLayerProvider.getState(randomsource, blockpos3), predicate);
} else {
this.safeSetBlock(worldgenlevel, blockpos3, geodeblocksettings.innerLayerProvider.getState(randomsource, blockpos3), predicate);
}
if ((!geodeconfiguration.placementsRequireLayer0Alternate || flag1) && randomsource.nextFloat() < geodeconfiguration.usePotentialPlacementsChance) {
list2.add(blockpos3.immutable());
}
} else if (d6 >= d3) {
this.safeSetBlock(worldgenlevel, blockpos3, geodeblocksettings.middleLayerProvider.getState(randomsource, blockpos3), predicate);
} else if (d6 >= d4) {
this.safeSetBlock(worldgenlevel, blockpos3, geodeblocksettings.outerLayerProvider.getState(randomsource, blockpos3), predicate);
}
}
}
List<BlockState> list3 = geodeblocksettings.innerPlacements;
for (BlockPos blockpos4 : list2) {
BlockState blockstate1 = Util.getRandom(list3, randomsource);
for (Direction direction : DIRECTIONS) {
if (blockstate1.hasProperty(BlockStateProperties.FACING)) {
blockstate1 = blockstate1.setValue(BlockStateProperties.FACING, direction);
}
BlockPos blockpos5 = blockpos4.relative(direction);
BlockState blockstate2 = worldgenlevel.getBlockState(blockpos5);
if (blockstate1.hasProperty(BlockStateProperties.WATERLOGGED)) {
blockstate1 = blockstate1.setValue(BlockStateProperties.WATERLOGGED, blockstate2.getFluidState().isSource());
}
if (BuddingAmethystBlock.canClusterGrowAtState(blockstate2)) {
this.safeSetBlock(worldgenlevel, blockpos5, blockstate1, predicate);
break;
}
}
}
return true;
}
}