219 lines
11 KiB
Java
219 lines
11 KiB
Java
package net.minecraft.world.level.levelgen.feature;
|
|
|
|
import net.minecraft.world.level.block.state.AbstractStateHolder;
|
|
import net.minecraft.world.level.levelgen.feature.treedecorators.TreeDecorator;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
|
import java.util.Iterator;
|
|
import net.minecraft.world.level.block.state.properties.Property;
|
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.world.phys.shapes.BitSetDiscreteVoxelShape;
|
|
import net.minecraft.world.phys.shapes.DiscreteVoxelShape;
|
|
import java.util.List;
|
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
|
import java.util.Comparator;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Sets;
|
|
import net.minecraft.world.level.levelgen.ChunkGeneratorSettings;
|
|
import net.minecraft.world.level.chunk.ChunkGenerator;
|
|
import net.minecraft.world.level.LevelAccessor;
|
|
import net.minecraft.core.Vec3i;
|
|
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
|
import java.util.Set;
|
|
import java.util.Random;
|
|
import net.minecraft.world.level.LevelWriter;
|
|
import net.minecraft.world.level.LevelSimulatedRW;
|
|
import net.minecraft.world.level.material.Material;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.tags.BlockTags;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.world.level.LevelSimulatedReader;
|
|
import com.mojang.datafixers.Dynamic;
|
|
import java.util.function.Function;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration;
|
|
|
|
public abstract class AbstractTreeFeature<T extends TreeConfiguration> extends Feature<T> {
|
|
public AbstractTreeFeature(final Function<Dynamic<?>, ? extends T> function) {
|
|
super(function);
|
|
}
|
|
|
|
protected static boolean isFree(final LevelSimulatedReader bjz, final BlockPos fk) {
|
|
final Block bpe2;
|
|
return bjz.isStateAtPosition(fk, byg -> {
|
|
bpe2 = byg.getBlock();
|
|
return byg.isAir() || byg.is(BlockTags.LEAVES) || Feature.isDirt(bpe2) || bpe2.is(BlockTags.LOGS) || bpe2.is(BlockTags.SAPLINGS) || bpe2 == Blocks.VINE;
|
|
});
|
|
}
|
|
|
|
public static boolean isAir(final LevelSimulatedReader bjz, final BlockPos fk) {
|
|
return bjz.isStateAtPosition(fk, BlockState::isAir);
|
|
}
|
|
|
|
protected static boolean isDirt(final LevelSimulatedReader bjz, final BlockPos fk) {
|
|
final Block bpe2;
|
|
return bjz.isStateAtPosition(fk, byg -> {
|
|
bpe2 = byg.getBlock();
|
|
return Feature.isDirt(bpe2) && bpe2 != Blocks.GRASS_BLOCK && bpe2 != Blocks.MYCELIUM;
|
|
});
|
|
}
|
|
|
|
protected static boolean isVine(final LevelSimulatedReader bjz, final BlockPos fk) {
|
|
return bjz.isStateAtPosition(fk, byg -> byg.getBlock() == Blocks.VINE);
|
|
}
|
|
|
|
public static boolean isBlockWater(final LevelSimulatedReader bjz, final BlockPos fk) {
|
|
return bjz.isStateAtPosition(fk, byg -> byg.getBlock() == Blocks.WATER);
|
|
}
|
|
|
|
public static boolean isAirOrLeaves(final LevelSimulatedReader bjz, final BlockPos fk) {
|
|
return bjz.isStateAtPosition(fk, byg -> byg.isAir() || byg.is(BlockTags.LEAVES));
|
|
}
|
|
|
|
public static boolean isGrassOrDirt(final LevelSimulatedReader bjz, final BlockPos fk) {
|
|
return bjz.isStateAtPosition(fk, byg -> Feature.isDirt(byg.getBlock()));
|
|
}
|
|
|
|
protected static boolean isGrassOrDirtOrFarmland(final LevelSimulatedReader bjz, final BlockPos fk) {
|
|
final Block bpe2;
|
|
return bjz.isStateAtPosition(fk, byg -> {
|
|
bpe2 = byg.getBlock();
|
|
return Feature.isDirt(bpe2) || bpe2 == Blocks.FARMLAND;
|
|
});
|
|
}
|
|
|
|
public static boolean isReplaceablePlant(final LevelSimulatedReader bjz, final BlockPos fk) {
|
|
final Material cok2;
|
|
return bjz.isStateAtPosition(fk, byg -> {
|
|
cok2 = byg.getMaterial();
|
|
return cok2 == Material.REPLACEABLE_PLANT;
|
|
});
|
|
}
|
|
|
|
protected void setDirtAt(final LevelSimulatedRW bjy, final BlockPos fk) {
|
|
if (!isDirt(bjy, fk)) {
|
|
this.setBlock(bjy, fk, Blocks.DIRT.defaultBlockState());
|
|
}
|
|
}
|
|
|
|
protected boolean placeLog(final LevelSimulatedRW bjy, final Random random, final BlockPos fk, final Set<BlockPos> set, final BoundingBox cky, final TreeConfiguration chi) {
|
|
if (isAirOrLeaves(bjy, fk) || isReplaceablePlant(bjy, fk) || isBlockWater(bjy, fk)) {
|
|
this.setBlock(bjy, fk, chi.trunkProvider.getState(random, fk), cky);
|
|
set.add(fk.immutable());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected boolean placeLeaf(final LevelSimulatedRW bjy, final Random random, final BlockPos fk, final Set<BlockPos> set, final BoundingBox cky, final TreeConfiguration chi) {
|
|
if (isAirOrLeaves(bjy, fk) || isReplaceablePlant(bjy, fk) || isBlockWater(bjy, fk)) {
|
|
this.setBlock(bjy, fk, chi.leavesProvider.getState(random, fk), cky);
|
|
set.add(fk.immutable());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
protected void setBlock(final LevelWriter bkb, final BlockPos fk, final BlockState byg) {
|
|
this.setBlockKnownShape(bkb, fk, byg);
|
|
}
|
|
|
|
protected final void setBlock(final LevelWriter bkb, final BlockPos fk, final BlockState byg, final BoundingBox cky) {
|
|
this.setBlockKnownShape(bkb, fk, byg);
|
|
cky.expand(new BoundingBox(fk, fk));
|
|
}
|
|
|
|
private void setBlockKnownShape(final LevelWriter bkb, final BlockPos fk, final BlockState byg) {
|
|
bkb.setBlock(fk, byg, 19);
|
|
}
|
|
|
|
@Override
|
|
public final boolean place(final LevelAccessor bju, final ChunkGenerator<? extends ChunkGeneratorSettings> bzx, final Random random, final BlockPos fk, final T chi) {
|
|
final Set<BlockPos> set7 = Sets.newHashSet();
|
|
final Set<BlockPos> set8 = Sets.newHashSet();
|
|
final Set<BlockPos> set9 = Sets.newHashSet();
|
|
final BoundingBox cky10 = BoundingBox.getUnknownBox();
|
|
final boolean boolean11 = this.doPlace(bju, random, fk, set7, set8, cky10, chi);
|
|
if (cky10.x0 > cky10.x1 || !boolean11 || set7.isEmpty()) {
|
|
return false;
|
|
}
|
|
if (!chi.decorators.isEmpty()) {
|
|
final List<BlockPos> list12 = Lists.newArrayList(set7);
|
|
final List<BlockPos> list13 = Lists.newArrayList(set8);
|
|
list12.sort(Comparator.comparingInt(Vec3i::getY));
|
|
list13.sort(Comparator.comparingInt(Vec3i::getY));
|
|
chi.decorators.forEach(ciq -> ciq.place(bju, random, list12, list13, set9, cky10));
|
|
}
|
|
final DiscreteVoxelShape cvr12 = this.updateLeaves(bju, cky10, set7, set9);
|
|
StructureTemplate.updateShapeAtEdge(bju, 3, cvr12, cky10.x0, cky10.y0, cky10.z0);
|
|
return true;
|
|
}
|
|
|
|
private DiscreteVoxelShape updateLeaves(final LevelAccessor bju, final BoundingBox cky, final Set<BlockPos> set3, final Set<BlockPos> set4) {
|
|
final List<Set<BlockPos>> list6 = Lists.newArrayList();
|
|
final DiscreteVoxelShape cvr7 = new BitSetDiscreteVoxelShape(cky.getXSpan(), cky.getYSpan(), cky.getZSpan());
|
|
final int integer8 = 6;
|
|
for (int integer9 = 0; integer9 < 6; ++integer9) {
|
|
list6.add(Sets.newHashSet());
|
|
}
|
|
try (final BlockPos.PooledMutableBlockPos b9 = BlockPos.PooledMutableBlockPos.acquire()) {
|
|
for (final BlockPos fk12 : Lists.<BlockPos>newArrayList(set4)) {
|
|
if (cky.isInside(fk12)) {
|
|
cvr7.setFull(fk12.getX() - cky.x0, fk12.getY() - cky.y0, fk12.getZ() - cky.z0, true, true);
|
|
}
|
|
}
|
|
for (final BlockPos fk12 : Lists.<BlockPos>newArrayList(set3)) {
|
|
if (cky.isInside(fk12)) {
|
|
cvr7.setFull(fk12.getX() - cky.x0, fk12.getY() - cky.y0, fk12.getZ() - cky.z0, true, true);
|
|
}
|
|
for (final Direction fp16 : Direction.values()) {
|
|
b9.set((Vec3i)fk12).move(fp16);
|
|
if (!set3.contains(b9)) {
|
|
final BlockState byg17 = bju.getBlockState(b9);
|
|
if (byg17.<Comparable>hasProperty((Property<Comparable>)BlockStateProperties.DISTANCE)) {
|
|
list6.get(0).add(b9.immutable());
|
|
this.setBlockKnownShape(bju, b9, ((AbstractStateHolder<O, BlockState>)byg17).<Comparable, Integer>setValue((Property<Comparable>)BlockStateProperties.DISTANCE, 1));
|
|
if (cky.isInside(b9)) {
|
|
cvr7.setFull(b9.getX() - cky.x0, b9.getY() - cky.y0, b9.getZ() - cky.z0, true, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (int integer10 = 1; integer10 < 6; ++integer10) {
|
|
final Set<BlockPos> set5 = list6.get(integer10 - 1);
|
|
final Set<BlockPos> set6 = list6.get(integer10);
|
|
for (final BlockPos fk13 : set5) {
|
|
if (cky.isInside(fk13)) {
|
|
cvr7.setFull(fk13.getX() - cky.x0, fk13.getY() - cky.y0, fk13.getZ() - cky.z0, true, true);
|
|
}
|
|
for (final Direction fp17 : Direction.values()) {
|
|
b9.set((Vec3i)fk13).move(fp17);
|
|
if (!set5.contains(b9)) {
|
|
if (!set6.contains(b9)) {
|
|
final BlockState byg18 = bju.getBlockState(b9);
|
|
if (byg18.<Comparable>hasProperty((Property<Comparable>)BlockStateProperties.DISTANCE)) {
|
|
final int integer11 = byg18.<Integer>getValue((Property<Integer>)BlockStateProperties.DISTANCE);
|
|
if (integer11 > integer10 + 1) {
|
|
final BlockState byg19 = ((AbstractStateHolder<O, BlockState>)byg18).<Comparable, Integer>setValue((Property<Comparable>)BlockStateProperties.DISTANCE, integer10 + 1);
|
|
this.setBlockKnownShape(bju, b9, byg19);
|
|
if (cky.isInside(b9)) {
|
|
cvr7.setFull(b9.getX() - cky.x0, b9.getY() - cky.y0, b9.getZ() - cky.z0, true, true);
|
|
}
|
|
set6.add(b9.immutable());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return cvr7;
|
|
}
|
|
|
|
protected abstract boolean doPlace(final LevelSimulatedRW bjy, final Random random, final BlockPos fk, final Set<BlockPos> set4, final Set<BlockPos> set5, final BoundingBox cky, final T chi);
|
|
}
|