158 lines
5.9 KiB
Java
158 lines
5.9 KiB
Java
|
package net.minecraft.world.level.levelgen.feature;
|
||
|
|
||
|
import com.google.common.collect.ImmutableList;
|
||
|
import com.mojang.serialization.Codec;
|
||
|
import javax.annotation.Nullable;
|
||
|
import net.minecraft.core.BlockPos;
|
||
|
import net.minecraft.core.Direction;
|
||
|
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.BlockState;
|
||
|
import net.minecraft.world.level.levelgen.feature.configurations.ColumnFeatureConfiguration;
|
||
|
|
||
|
public class BasaltColumnsFeature extends Feature<ColumnFeatureConfiguration> {
|
||
|
private static final ImmutableList<Block> CANNOT_PLACE_ON = ImmutableList.of(
|
||
|
Blocks.LAVA,
|
||
|
Blocks.BEDROCK,
|
||
|
Blocks.MAGMA_BLOCK,
|
||
|
Blocks.SOUL_SAND,
|
||
|
Blocks.NETHER_BRICKS,
|
||
|
Blocks.NETHER_BRICK_FENCE,
|
||
|
Blocks.NETHER_BRICK_STAIRS,
|
||
|
Blocks.NETHER_WART,
|
||
|
Blocks.CHEST,
|
||
|
Blocks.SPAWNER
|
||
|
);
|
||
|
private static final int CLUSTERED_REACH = 5;
|
||
|
private static final int CLUSTERED_SIZE = 50;
|
||
|
private static final int UNCLUSTERED_REACH = 8;
|
||
|
private static final int UNCLUSTERED_SIZE = 15;
|
||
|
|
||
|
public BasaltColumnsFeature(Codec<ColumnFeatureConfiguration> p_65153_) {
|
||
|
super(p_65153_);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean place(FeaturePlaceContext<ColumnFeatureConfiguration> p_159444_) {
|
||
|
int i = p_159444_.chunkGenerator().getSeaLevel();
|
||
|
BlockPos blockpos = p_159444_.origin();
|
||
|
WorldGenLevel worldgenlevel = p_159444_.level();
|
||
|
RandomSource randomsource = p_159444_.random();
|
||
|
ColumnFeatureConfiguration columnfeatureconfiguration = p_159444_.config();
|
||
|
if (!canPlaceAt(worldgenlevel, i, blockpos.mutable())) {
|
||
|
return false;
|
||
|
} else {
|
||
|
int j = columnfeatureconfiguration.height().sample(randomsource);
|
||
|
boolean flag = randomsource.nextFloat() < 0.9F;
|
||
|
int k = Math.min(j, flag ? 5 : 8);
|
||
|
int l = flag ? 50 : 15;
|
||
|
boolean flag1 = false;
|
||
|
|
||
|
for (BlockPos blockpos1 : BlockPos.randomBetweenClosed(
|
||
|
randomsource,
|
||
|
l,
|
||
|
blockpos.getX() - k,
|
||
|
blockpos.getY(),
|
||
|
blockpos.getZ() - k,
|
||
|
blockpos.getX() + k,
|
||
|
blockpos.getY(),
|
||
|
blockpos.getZ() + k
|
||
|
)) {
|
||
|
int i1 = j - blockpos1.distManhattan(blockpos);
|
||
|
if (i1 >= 0) {
|
||
|
flag1 |= this.placeColumn(worldgenlevel, i, blockpos1, i1, columnfeatureconfiguration.reach().sample(randomsource));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return flag1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private boolean placeColumn(LevelAccessor p_65168_, int p_65169_, BlockPos p_65170_, int p_65171_, int p_65172_) {
|
||
|
boolean flag = false;
|
||
|
|
||
|
for (BlockPos blockpos : BlockPos.betweenClosed(
|
||
|
p_65170_.getX() - p_65172_,
|
||
|
p_65170_.getY(),
|
||
|
p_65170_.getZ() - p_65172_,
|
||
|
p_65170_.getX() + p_65172_,
|
||
|
p_65170_.getY(),
|
||
|
p_65170_.getZ() + p_65172_
|
||
|
)) {
|
||
|
int i = blockpos.distManhattan(p_65170_);
|
||
|
BlockPos blockpos1 = isAirOrLavaOcean(p_65168_, p_65169_, blockpos)
|
||
|
? findSurface(p_65168_, p_65169_, blockpos.mutable(), i)
|
||
|
: findAir(p_65168_, blockpos.mutable(), i);
|
||
|
if (blockpos1 != null) {
|
||
|
int j = p_65171_ - i / 2;
|
||
|
|
||
|
for (BlockPos.MutableBlockPos blockpos$mutableblockpos = blockpos1.mutable(); j >= 0; j--) {
|
||
|
if (isAirOrLavaOcean(p_65168_, p_65169_, blockpos$mutableblockpos)) {
|
||
|
this.setBlock(p_65168_, blockpos$mutableblockpos, Blocks.BASALT.defaultBlockState());
|
||
|
blockpos$mutableblockpos.move(Direction.UP);
|
||
|
flag = true;
|
||
|
} else {
|
||
|
if (!p_65168_.getBlockState(blockpos$mutableblockpos).is(Blocks.BASALT)) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
blockpos$mutableblockpos.move(Direction.UP);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return flag;
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
private static BlockPos findSurface(LevelAccessor p_65159_, int p_65160_, BlockPos.MutableBlockPos p_65161_, int p_65162_) {
|
||
|
while (p_65161_.getY() > p_65159_.getMinY() + 1 && p_65162_ > 0) {
|
||
|
p_65162_--;
|
||
|
if (canPlaceAt(p_65159_, p_65160_, p_65161_)) {
|
||
|
return p_65161_;
|
||
|
}
|
||
|
|
||
|
p_65161_.move(Direction.DOWN);
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
private static boolean canPlaceAt(LevelAccessor p_65155_, int p_65156_, BlockPos.MutableBlockPos p_65157_) {
|
||
|
if (!isAirOrLavaOcean(p_65155_, p_65156_, p_65157_)) {
|
||
|
return false;
|
||
|
} else {
|
||
|
BlockState blockstate = p_65155_.getBlockState(p_65157_.move(Direction.DOWN));
|
||
|
p_65157_.move(Direction.UP);
|
||
|
return !blockstate.isAir() && !CANNOT_PLACE_ON.contains(blockstate.getBlock());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
private static BlockPos findAir(LevelAccessor p_65174_, BlockPos.MutableBlockPos p_65175_, int p_65176_) {
|
||
|
while (p_65175_.getY() <= p_65174_.getMaxY() && p_65176_ > 0) {
|
||
|
p_65176_--;
|
||
|
BlockState blockstate = p_65174_.getBlockState(p_65175_);
|
||
|
if (CANNOT_PLACE_ON.contains(blockstate.getBlock())) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
if (blockstate.isAir()) {
|
||
|
return p_65175_;
|
||
|
}
|
||
|
|
||
|
p_65175_.move(Direction.UP);
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
private static boolean isAirOrLavaOcean(LevelAccessor p_65164_, int p_65165_, BlockPos p_65166_) {
|
||
|
BlockState blockstate = p_65164_.getBlockState(p_65166_);
|
||
|
return blockstate.isAir() || blockstate.is(Blocks.LAVA) && p_65166_.getY() <= p_65165_;
|
||
|
}
|
||
|
}
|