200 lines
9.5 KiB
Java
200 lines
9.5 KiB
Java
package net.minecraft.world.level.levelgen.feature;
|
|
|
|
import com.mojang.serialization.Codec;
|
|
import java.util.Optional;
|
|
import java.util.OptionalInt;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.tags.BlockTags;
|
|
import net.minecraft.tags.FluidTags;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.util.valueproviders.ClampedNormalFloat;
|
|
import net.minecraft.world.level.LevelAccessor;
|
|
import net.minecraft.world.level.LevelReader;
|
|
import net.minecraft.world.level.WorldGenLevel;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.levelgen.Column;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.DripstoneClusterConfiguration;
|
|
|
|
public class DripstoneClusterFeature extends Feature<DripstoneClusterConfiguration> {
|
|
public DripstoneClusterFeature(Codec<DripstoneClusterConfiguration> p_159575_) {
|
|
super(p_159575_);
|
|
}
|
|
|
|
@Override
|
|
public boolean place(FeaturePlaceContext<DripstoneClusterConfiguration> p_159605_) {
|
|
WorldGenLevel worldgenlevel = p_159605_.level();
|
|
BlockPos blockpos = p_159605_.origin();
|
|
DripstoneClusterConfiguration dripstoneclusterconfiguration = p_159605_.config();
|
|
RandomSource randomsource = p_159605_.random();
|
|
if (!DripstoneUtils.isEmptyOrWater(worldgenlevel, blockpos)) {
|
|
return false;
|
|
} else {
|
|
int i = dripstoneclusterconfiguration.height.sample(randomsource);
|
|
float f = dripstoneclusterconfiguration.wetness.sample(randomsource);
|
|
float f1 = dripstoneclusterconfiguration.density.sample(randomsource);
|
|
int j = dripstoneclusterconfiguration.radius.sample(randomsource);
|
|
int k = dripstoneclusterconfiguration.radius.sample(randomsource);
|
|
|
|
for (int l = -j; l <= j; l++) {
|
|
for (int i1 = -k; i1 <= k; i1++) {
|
|
double d0 = this.getChanceOfStalagmiteOrStalactite(j, k, l, i1, dripstoneclusterconfiguration);
|
|
BlockPos blockpos1 = blockpos.offset(l, 0, i1);
|
|
this.placeColumn(worldgenlevel, randomsource, blockpos1, l, i1, f, d0, i, f1, dripstoneclusterconfiguration);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
private void placeColumn(
|
|
WorldGenLevel p_225016_,
|
|
RandomSource p_225017_,
|
|
BlockPos p_225018_,
|
|
int p_225019_,
|
|
int p_225020_,
|
|
float p_225021_,
|
|
double p_225022_,
|
|
int p_225023_,
|
|
float p_225024_,
|
|
DripstoneClusterConfiguration p_225025_
|
|
) {
|
|
Optional<Column> optional = Column.scan(p_225016_, p_225018_, p_225025_.floorToCeilingSearchRange, DripstoneUtils::isEmptyOrWater, DripstoneUtils::isNeitherEmptyNorWater);
|
|
if (!optional.isEmpty()) {
|
|
OptionalInt optionalint = optional.get().getCeiling();
|
|
OptionalInt optionalint1 = optional.get().getFloor();
|
|
if (!optionalint.isEmpty() || !optionalint1.isEmpty()) {
|
|
boolean flag = p_225017_.nextFloat() < p_225021_;
|
|
Column column;
|
|
if (flag && optionalint1.isPresent() && this.canPlacePool(p_225016_, p_225018_.atY(optionalint1.getAsInt()))) {
|
|
int i = optionalint1.getAsInt();
|
|
column = optional.get().withFloor(OptionalInt.of(i - 1));
|
|
p_225016_.setBlock(p_225018_.atY(i), Blocks.WATER.defaultBlockState(), 2);
|
|
} else {
|
|
column = optional.get();
|
|
}
|
|
|
|
OptionalInt optionalint2 = column.getFloor();
|
|
boolean flag1 = p_225017_.nextDouble() < p_225022_;
|
|
int j;
|
|
if (optionalint.isPresent() && flag1 && !this.isLava(p_225016_, p_225018_.atY(optionalint.getAsInt()))) {
|
|
int k = p_225025_.dripstoneBlockLayerThickness.sample(p_225017_);
|
|
this.replaceBlocksWithDripstoneBlocks(p_225016_, p_225018_.atY(optionalint.getAsInt()), k, Direction.UP);
|
|
int l;
|
|
if (optionalint2.isPresent()) {
|
|
l = Math.min(p_225023_, optionalint.getAsInt() - optionalint2.getAsInt());
|
|
} else {
|
|
l = p_225023_;
|
|
}
|
|
|
|
j = this.getDripstoneHeight(p_225017_, p_225019_, p_225020_, p_225024_, l, p_225025_);
|
|
} else {
|
|
j = 0;
|
|
}
|
|
|
|
boolean flag2 = p_225017_.nextDouble() < p_225022_;
|
|
int i3;
|
|
if (optionalint2.isPresent() && flag2 && !this.isLava(p_225016_, p_225018_.atY(optionalint2.getAsInt()))) {
|
|
int i1 = p_225025_.dripstoneBlockLayerThickness.sample(p_225017_);
|
|
this.replaceBlocksWithDripstoneBlocks(p_225016_, p_225018_.atY(optionalint2.getAsInt()), i1, Direction.DOWN);
|
|
if (optionalint.isPresent()) {
|
|
i3 = Math.max(0, j + Mth.randomBetweenInclusive(p_225017_, -p_225025_.maxStalagmiteStalactiteHeightDiff, p_225025_.maxStalagmiteStalactiteHeightDiff));
|
|
} else {
|
|
i3 = this.getDripstoneHeight(p_225017_, p_225019_, p_225020_, p_225024_, p_225023_, p_225025_);
|
|
}
|
|
} else {
|
|
i3 = 0;
|
|
}
|
|
|
|
int j1;
|
|
int j3;
|
|
if (optionalint.isPresent() && optionalint2.isPresent() && optionalint.getAsInt() - j <= optionalint2.getAsInt() + i3) {
|
|
int k1 = optionalint2.getAsInt();
|
|
int l1 = optionalint.getAsInt();
|
|
int i2 = Math.max(l1 - j, k1 + 1);
|
|
int j2 = Math.min(k1 + i3, l1 - 1);
|
|
int k2 = Mth.randomBetweenInclusive(p_225017_, i2, j2 + 1);
|
|
int l2 = k2 - 1;
|
|
j3 = l1 - k2;
|
|
j1 = l2 - k1;
|
|
} else {
|
|
j3 = j;
|
|
j1 = i3;
|
|
}
|
|
|
|
boolean flag3 = p_225017_.nextBoolean() && j3 > 0 && j1 > 0 && column.getHeight().isPresent() && j3 + j1 == column.getHeight().getAsInt();
|
|
if (optionalint.isPresent()) {
|
|
DripstoneUtils.growPointedDripstone(p_225016_, p_225018_.atY(optionalint.getAsInt() - 1), Direction.DOWN, j3, flag3);
|
|
}
|
|
|
|
if (optionalint2.isPresent()) {
|
|
DripstoneUtils.growPointedDripstone(p_225016_, p_225018_.atY(optionalint2.getAsInt() + 1), Direction.UP, j1, flag3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean isLava(LevelReader p_159586_, BlockPos p_159587_) {
|
|
return p_159586_.getBlockState(p_159587_).is(Blocks.LAVA);
|
|
}
|
|
|
|
private int getDripstoneHeight(RandomSource p_225009_, int p_225010_, int p_225011_, float p_225012_, int p_225013_, DripstoneClusterConfiguration p_225014_) {
|
|
if (p_225009_.nextFloat() > p_225012_) {
|
|
return 0;
|
|
} else {
|
|
int i = Math.abs(p_225010_) + Math.abs(p_225011_);
|
|
float f = (float)Mth.clampedMap(i, 0.0, p_225014_.maxDistanceFromCenterAffectingHeightBias, p_225013_ / 2.0, 0.0);
|
|
return (int)randomBetweenBiased(p_225009_, 0.0F, p_225013_, f, p_225014_.heightDeviation);
|
|
}
|
|
}
|
|
|
|
private boolean canPlacePool(WorldGenLevel p_159620_, BlockPos p_159621_) {
|
|
BlockState blockstate = p_159620_.getBlockState(p_159621_);
|
|
if (!blockstate.is(Blocks.WATER) && !blockstate.is(Blocks.DRIPSTONE_BLOCK) && !blockstate.is(Blocks.POINTED_DRIPSTONE)) {
|
|
if (p_159620_.getBlockState(p_159621_.above()).getFluidState().is(FluidTags.WATER)) {
|
|
return false;
|
|
} else {
|
|
for (Direction direction : Direction.Plane.HORIZONTAL) {
|
|
if (!this.canBeAdjacentToWater(p_159620_, p_159621_.relative(direction))) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return this.canBeAdjacentToWater(p_159620_, p_159621_.below());
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private boolean canBeAdjacentToWater(LevelAccessor p_159583_, BlockPos p_159584_) {
|
|
BlockState blockstate = p_159583_.getBlockState(p_159584_);
|
|
return blockstate.is(BlockTags.BASE_STONE_OVERWORLD) || blockstate.getFluidState().is(FluidTags.WATER);
|
|
}
|
|
|
|
private void replaceBlocksWithDripstoneBlocks(WorldGenLevel p_159589_, BlockPos p_159590_, int p_159591_, Direction p_159592_) {
|
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = p_159590_.mutable();
|
|
|
|
for (int i = 0; i < p_159591_; i++) {
|
|
if (!DripstoneUtils.placeDripstoneBlockIfPossible(p_159589_, blockpos$mutableblockpos)) {
|
|
return;
|
|
}
|
|
|
|
blockpos$mutableblockpos.move(p_159592_);
|
|
}
|
|
}
|
|
|
|
private double getChanceOfStalagmiteOrStalactite(int p_159577_, int p_159578_, int p_159579_, int p_159580_, DripstoneClusterConfiguration p_159581_) {
|
|
int i = p_159577_ - Math.abs(p_159579_);
|
|
int j = p_159578_ - Math.abs(p_159580_);
|
|
int k = Math.min(i, j);
|
|
return Mth.clampedMap(k, 0.0F, p_159581_.maxDistanceFromEdgeAffectingChanceOfDripstoneColumn, p_159581_.chanceOfDripstoneColumnAtMaxDistanceFromCenter, 1.0F);
|
|
}
|
|
|
|
private static float randomBetweenBiased(RandomSource p_225003_, float p_225004_, float p_225005_, float p_225006_, float p_225007_) {
|
|
return ClampedNormalFloat.sample(p_225003_, p_225006_, p_225007_, p_225004_, p_225005_);
|
|
}
|
|
} |