minecraft-src/net/minecraft/world/level/levelgen/feature/LakeFeature.java
2025-07-04 02:00:41 +03:00

162 lines
5.7 KiB
Java

package net.minecraft.world.level.levelgen.feature;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.RandomSource;
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.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
@Deprecated
public class LakeFeature extends Feature<LakeFeature.Configuration> {
private static final BlockState AIR = Blocks.CAVE_AIR.defaultBlockState();
public LakeFeature(Codec<LakeFeature.Configuration> codec) {
super(codec);
}
@Override
public boolean place(FeaturePlaceContext<LakeFeature.Configuration> context) {
BlockPos blockPos = context.origin();
WorldGenLevel worldGenLevel = context.level();
RandomSource randomSource = context.random();
LakeFeature.Configuration configuration = context.config();
if (blockPos.getY() <= worldGenLevel.getMinY() + 4) {
return false;
} else {
blockPos = blockPos.below(4);
boolean[] bls = new boolean[2048];
int i = randomSource.nextInt(4) + 4;
for (int j = 0; j < i; j++) {
double d = randomSource.nextDouble() * 6.0 + 3.0;
double e = randomSource.nextDouble() * 4.0 + 2.0;
double f = randomSource.nextDouble() * 6.0 + 3.0;
double g = randomSource.nextDouble() * (16.0 - d - 2.0) + 1.0 + d / 2.0;
double h = randomSource.nextDouble() * (8.0 - e - 4.0) + 2.0 + e / 2.0;
double k = randomSource.nextDouble() * (16.0 - f - 2.0) + 1.0 + f / 2.0;
for (int l = 1; l < 15; l++) {
for (int m = 1; m < 15; m++) {
for (int n = 1; n < 7; n++) {
double o = (l - g) / (d / 2.0);
double p = (n - h) / (e / 2.0);
double q = (m - k) / (f / 2.0);
double r = o * o + p * p + q * q;
if (r < 1.0) {
bls[(l * 16 + m) * 8 + n] = true;
}
}
}
}
}
BlockState blockState = configuration.fluid().getState(randomSource, blockPos);
for (int s = 0; s < 16; s++) {
for (int t = 0; t < 16; t++) {
for (int u = 0; u < 8; u++) {
boolean bl = !bls[(s * 16 + t) * 8 + u]
&& (
s < 15 && bls[((s + 1) * 16 + t) * 8 + u]
|| s > 0 && bls[((s - 1) * 16 + t) * 8 + u]
|| t < 15 && bls[(s * 16 + t + 1) * 8 + u]
|| t > 0 && bls[(s * 16 + (t - 1)) * 8 + u]
|| u < 7 && bls[(s * 16 + t) * 8 + u + 1]
|| u > 0 && bls[(s * 16 + t) * 8 + (u - 1)]
);
if (bl) {
BlockState blockState2 = worldGenLevel.getBlockState(blockPos.offset(s, u, t));
if (u >= 4 && blockState2.liquid()) {
return false;
}
if (u < 4 && !blockState2.isSolid() && worldGenLevel.getBlockState(blockPos.offset(s, u, t)) != blockState) {
return false;
}
}
}
}
}
for (int s = 0; s < 16; s++) {
for (int t = 0; t < 16; t++) {
for (int ux = 0; ux < 8; ux++) {
if (bls[(s * 16 + t) * 8 + ux]) {
BlockPos blockPos2 = blockPos.offset(s, ux, t);
if (this.canReplaceBlock(worldGenLevel.getBlockState(blockPos2))) {
boolean bl2 = ux >= 4;
worldGenLevel.setBlock(blockPos2, bl2 ? AIR : blockState, 2);
if (bl2) {
worldGenLevel.scheduleTick(blockPos2, AIR.getBlock(), 0);
this.markAboveForPostProcessing(worldGenLevel, blockPos2);
}
}
}
}
}
}
BlockState blockState3 = configuration.barrier().getState(randomSource, blockPos);
if (!blockState3.isAir()) {
for (int t = 0; t < 16; t++) {
for (int uxx = 0; uxx < 16; uxx++) {
for (int v = 0; v < 8; v++) {
boolean bl2 = !bls[(t * 16 + uxx) * 8 + v]
&& (
t < 15 && bls[((t + 1) * 16 + uxx) * 8 + v]
|| t > 0 && bls[((t - 1) * 16 + uxx) * 8 + v]
|| uxx < 15 && bls[(t * 16 + uxx + 1) * 8 + v]
|| uxx > 0 && bls[(t * 16 + (uxx - 1)) * 8 + v]
|| v < 7 && bls[(t * 16 + uxx) * 8 + v + 1]
|| v > 0 && bls[(t * 16 + uxx) * 8 + (v - 1)]
);
if (bl2 && (v < 4 || randomSource.nextInt(2) != 0)) {
BlockState blockState4 = worldGenLevel.getBlockState(blockPos.offset(t, v, uxx));
if (blockState4.isSolid() && !blockState4.is(BlockTags.LAVA_POOL_STONE_CANNOT_REPLACE)) {
BlockPos blockPos3 = blockPos.offset(t, v, uxx);
worldGenLevel.setBlock(blockPos3, blockState3, 2);
this.markAboveForPostProcessing(worldGenLevel, blockPos3);
}
}
}
}
}
}
if (blockState.getFluidState().is(FluidTags.WATER)) {
for (int t = 0; t < 16; t++) {
for (int uxx = 0; uxx < 16; uxx++) {
int vx = 4;
BlockPos blockPos4 = blockPos.offset(t, 4, uxx);
if (worldGenLevel.getBiome(blockPos4).value().shouldFreeze(worldGenLevel, blockPos4, false)
&& this.canReplaceBlock(worldGenLevel.getBlockState(blockPos4))) {
worldGenLevel.setBlock(blockPos4, Blocks.ICE.defaultBlockState(), 2);
}
}
}
}
return true;
}
}
private boolean canReplaceBlock(BlockState state) {
return !state.is(BlockTags.FEATURES_CANNOT_REPLACE);
}
public record Configuration(BlockStateProvider fluid, BlockStateProvider barrier) implements FeatureConfiguration {
public static final Codec<LakeFeature.Configuration> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
BlockStateProvider.CODEC.fieldOf("fluid").forGetter(LakeFeature.Configuration::fluid),
BlockStateProvider.CODEC.fieldOf("barrier").forGetter(LakeFeature.Configuration::barrier)
)
.apply(instance, LakeFeature.Configuration::new)
);
}
}