Fixed ScatterFeature

This commit is contained in:
Frank 2022-06-03 16:40:17 +02:00
parent 51bd560fa0
commit 0149b17a1a
6 changed files with 170 additions and 146 deletions

View file

@ -260,6 +260,10 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
return modifier(new IsBasin(BlockPredicate.anyOf(predicates)));
}
public BCLFeatureBuilder inOpenBasinOf(BlockPredicate... predicates) {
return modifier(IsBasin.openTop(BlockPredicate.anyOf(predicates)));
}
public BCLFeatureBuilder is(BlockPredicate... predicates) {
return modifier(new Is(BlockPredicate.anyOf(predicates)));
}

View file

@ -12,7 +12,6 @@ import net.minecraft.util.valueproviders.ConstantInt;
import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.level.LevelAccessor;
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.GenerationStep;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
@ -23,6 +22,7 @@ import net.minecraft.world.level.levelgen.placement.*;
import com.mojang.serialization.Codec;
import org.betterx.bclib.api.features.config.ScatterFeatureConfig;
import org.betterx.bclib.api.tag.CommonBlockTags;
import org.betterx.bclib.util.BlocksHelper;
import java.util.ArrayList;
@ -42,7 +42,7 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
if (cfg.floorChance > 0) set.add(PlacementUtils.inlinePlaced(inlineFeature,
cfg,
EnvironmentScanPlacement.scanningFor(Direction.DOWN,
BlockPredicate.solid(),
BlockPredicate.matchesTag(CommonBlockTags.TERRAIN),
BlockPredicate.ONLY_IN_AIR_PREDICATE,
12),
RandomOffsetPlacement.vertical(ConstantInt.of(1))));
@ -51,7 +51,7 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
set.add(PlacementUtils.inlinePlaced(inlineFeature,
cfg,
EnvironmentScanPlacement.scanningFor(Direction.UP,
BlockPredicate.solid(),
BlockPredicate.matchesTag(CommonBlockTags.TERRAIN),
BlockPredicate.ONLY_IN_AIR_PREDICATE,
12),
RandomOffsetPlacement.vertical(ConstantInt.of(-1))));
@ -112,7 +112,7 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
for (int i = 0; i < tryCount; i++) {
int x = origin.getX() + (int) (random.nextGaussian() * config.maxSpread);
int z = origin.getZ() + (int) (random.nextGaussian() * config.maxSpread);
POS.set(x, origin.getY(), z);
POS.set(x, basePos.getY(), z);
if (BlocksHelper.findSurroundingSurface(level, POS, surfaceDirection, 4, config::isValidBase)) {
int myHeight;
@ -121,12 +121,12 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
POS,
direction,
config.maxHeight,
state -> state.getMaterial().isReplaceable());
BlocksHelper::isFree
);
} else {
myHeight = centerHeight;
}
POS.move(direction, 1);
int dx = x - POS.getX();
int dz = z - POS.getZ();
float sizeFactor = (1 - (float) (Math.sqrt(dx * dx + dz * dz) / distNormalizer));
@ -136,6 +136,10 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
config.minHeight + sizeFactor * (myHeight - config.minHeight)
), config.maxHeight);
BlockState baseState = level.getBlockState(POS.relative(direction.getOpposite()));
if (!config.isValidBase(baseState)) {
System.out.println("Starting from " + baseState + " at " + POS.relative(direction.getOpposite()));
}
buildPillarWithBase(level,
POS,
POS.relative(direction.getOpposite()),
@ -155,7 +159,7 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
int height,
ScatterFeatureConfig config,
RandomSource random) {
if (BlocksHelper.isFreeSpace(level, origin, direction, height, (state) -> state.is(Blocks.AIR))) {
if (BlocksHelper.isFreeSpace(level, origin, direction, height, BlocksHelper::isFree)) {
createPatchOfBaseBlocks(level, random, basePos, config);
buildPillar(level, origin, direction, height, config, random);
}
@ -170,6 +174,10 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
final BlockPos.MutableBlockPos POS = origin.mutable();
buildBaseToTipColumn(height, (blockState) -> {
BlockState previous = level.getBlockState(POS);
if (!BlocksHelper.isFree(previous)) {
System.out.println("Replaced " + previous + " with " + blockState + " at " + POS);
}
BlocksHelper.setWithoutUpdate(level, POS, blockState);
POS.move(direction);
}, config, random);
@ -181,16 +189,6 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
RandomSource random) {
for (int size = 0; size < totalHeight; size++) {
consumer.accept(config.createBlock(size, totalHeight - 1, random));
// Block s = config.createBlock(size, totalHeight - 1, random).getBlock();
// if (size == 0) s = Blocks.YELLOW_CONCRETE;
// else if (size == 1) s = Blocks.LIME_CONCRETE;
// else if (size == 2) s = Blocks.CYAN_CONCRETE;
// else if (size == 3) s = Blocks.LIGHT_BLUE_CONCRETE;
// else if (size == 4) s = Blocks.BLUE_CONCRETE;
// else if (size == 5) s = Blocks.PURPLE_CONCRETE;
// else if (size == 6) s = Blocks.MAGENTA_CONCRETE;
// else s = Blocks.GRAY_CONCRETE;
// consumer.accept(s.defaultBlockState());
}
}

View file

@ -11,29 +11,46 @@ import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.Optional;
public class IsBasin extends PlacementFilter {
public static final Codec<IsBasin> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
BlockPredicate.CODEC
.fieldOf("predicate")
.forGetter(cfg -> cfg.predicate)
.forGetter(cfg -> cfg.predicate),
BlockPredicate.CODEC
.optionalFieldOf("top_predicate")
.orElse(Optional.empty())
.forGetter(cfg -> cfg.topPredicate)
)
.apply(instance, IsBasin::new));
private final BlockPredicate predicate;
private final Optional<BlockPredicate> topPredicate;
public IsBasin(BlockPredicate predicate) {
this(predicate, Optional.empty());
}
public IsBasin(BlockPredicate predicate, Optional<BlockPredicate> topPredicate) {
this.predicate = predicate;
this.topPredicate = topPredicate;
}
public static IsBasin simple(BlockPredicate predicate) {
return new IsBasin(predicate);
}
public static IsBasin openTop(BlockPredicate predicate) {
return new IsBasin(predicate, Optional.of(BlockPredicate.ONLY_IN_AIR_PREDICATE));
}
@Override
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
WorldGenLevel level = ctx.getLevel();
if (topPredicate.isPresent() && !topPredicate.get().test(level, pos.above())) return false;
return predicate.test(level, pos.below())
&& predicate.test(level, pos.west())
&& predicate.test(level, pos.east())

View file

@ -53,7 +53,7 @@ public class MinEmptyFilter extends PlacementFilter {
pos.relative(direction),
direction,
distance - 1,
state -> state.getMaterial().isReplaceable()
BlocksHelper::isFree
);
}

View file

@ -251,21 +251,28 @@ public class BlocksHelper {
Direction dir,
int length,
Predicate<BlockState> surface) {
BlockState beforeState = null;
BlockState nowState;
for (int len = 0; len < length; len++) {
if (surface.test(level.getBlockState(startPos))) {
nowState = level.getBlockState(startPos);
if (surface.test(nowState)) {
if (len == 0) { //we started inside of the surface
beforeState = nowState;
for (int lenUp = 0; lenUp < length; lenUp++) {
startPos.move(dir, -1);
if (BlocksHelper.isFree(level.getBlockState(startPos))) {
startPos.move(dir, 1);
return true;
nowState = level.getBlockState(startPos);
if (BlocksHelper.isFree(nowState)) {
return surface.test(beforeState);
}
beforeState = nowState;
}
return false;
} else {
startPos.move(dir, -1);
return BlocksHelper.isFree(beforeState);
}
return true;
}
beforeState = nowState;
startPos.move(dir, 1);
}
return false;
@ -279,11 +286,10 @@ public class BlocksHelper {
Predicate<BlockState> freeSurface) {
MutableBlockPos POS = startPos.mutable();
for (int len = 0; len < length; len++) {
POS.move(dir, 1);
if (!freeSurface.test(level.getBlockState(POS))) {
return false;
}
POS.move(dir, 1);
}
return true;
}
@ -294,12 +300,11 @@ public class BlocksHelper {
int length,
Predicate<BlockState> freeSurface) {
MutableBlockPos POS = startPos.mutable();
for (int len = 1; len < length; len++) {
POS.move(dir, 1);
for (int len = 0; len < length; len++) {
if (!freeSurface.test(level.getBlockState(POS))) {
return len - 1;
return len;
}
POS.move(dir, 1);
}
return length;
}