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))); return modifier(new IsBasin(BlockPredicate.anyOf(predicates)));
} }
public BCLFeatureBuilder inOpenBasinOf(BlockPredicate... predicates) {
return modifier(IsBasin.openTop(BlockPredicate.anyOf(predicates)));
}
public BCLFeatureBuilder is(BlockPredicate... predicates) { public BCLFeatureBuilder is(BlockPredicate... predicates) {
return modifier(new Is(BlockPredicate.anyOf(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.util.valueproviders.UniformInt;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.WorldGenLevel; 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.block.state.BlockState;
import net.minecraft.world.level.levelgen.GenerationStep; import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate; 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 com.mojang.serialization.Codec;
import org.betterx.bclib.api.features.config.ScatterFeatureConfig; import org.betterx.bclib.api.features.config.ScatterFeatureConfig;
import org.betterx.bclib.api.tag.CommonBlockTags;
import org.betterx.bclib.util.BlocksHelper; import org.betterx.bclib.util.BlocksHelper;
import java.util.ArrayList; import java.util.ArrayList;
@ -42,7 +42,7 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
if (cfg.floorChance > 0) set.add(PlacementUtils.inlinePlaced(inlineFeature, if (cfg.floorChance > 0) set.add(PlacementUtils.inlinePlaced(inlineFeature,
cfg, cfg,
EnvironmentScanPlacement.scanningFor(Direction.DOWN, EnvironmentScanPlacement.scanningFor(Direction.DOWN,
BlockPredicate.solid(), BlockPredicate.matchesTag(CommonBlockTags.TERRAIN),
BlockPredicate.ONLY_IN_AIR_PREDICATE, BlockPredicate.ONLY_IN_AIR_PREDICATE,
12), 12),
RandomOffsetPlacement.vertical(ConstantInt.of(1)))); RandomOffsetPlacement.vertical(ConstantInt.of(1))));
@ -51,7 +51,7 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
set.add(PlacementUtils.inlinePlaced(inlineFeature, set.add(PlacementUtils.inlinePlaced(inlineFeature,
cfg, cfg,
EnvironmentScanPlacement.scanningFor(Direction.UP, EnvironmentScanPlacement.scanningFor(Direction.UP,
BlockPredicate.solid(), BlockPredicate.matchesTag(CommonBlockTags.TERRAIN),
BlockPredicate.ONLY_IN_AIR_PREDICATE, BlockPredicate.ONLY_IN_AIR_PREDICATE,
12), 12),
RandomOffsetPlacement.vertical(ConstantInt.of(-1)))); RandomOffsetPlacement.vertical(ConstantInt.of(-1))));
@ -112,7 +112,7 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
for (int i = 0; i < tryCount; i++) { for (int i = 0; i < tryCount; i++) {
int x = origin.getX() + (int) (random.nextGaussian() * config.maxSpread); int x = origin.getX() + (int) (random.nextGaussian() * config.maxSpread);
int z = origin.getZ() + (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)) { if (BlocksHelper.findSurroundingSurface(level, POS, surfaceDirection, 4, config::isValidBase)) {
int myHeight; int myHeight;
@ -121,12 +121,12 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
POS, POS,
direction, direction,
config.maxHeight, config.maxHeight,
state -> state.getMaterial().isReplaceable()); BlocksHelper::isFree
);
} else { } else {
myHeight = centerHeight; myHeight = centerHeight;
} }
POS.move(direction, 1);
int dx = x - POS.getX(); int dx = x - POS.getX();
int dz = z - POS.getZ(); int dz = z - POS.getZ();
float sizeFactor = (1 - (float) (Math.sqrt(dx * dx + dz * dz) / distNormalizer)); 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.minHeight + sizeFactor * (myHeight - config.minHeight)
), config.maxHeight); ), 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, buildPillarWithBase(level,
POS, POS,
POS.relative(direction.getOpposite()), POS.relative(direction.getOpposite()),
@ -155,7 +159,7 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
int height, int height,
ScatterFeatureConfig config, ScatterFeatureConfig config,
RandomSource random) { 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); createPatchOfBaseBlocks(level, random, basePos, config);
buildPillar(level, origin, direction, height, config, random); buildPillar(level, origin, direction, height, config, random);
} }
@ -170,6 +174,10 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
final BlockPos.MutableBlockPos POS = origin.mutable(); final BlockPos.MutableBlockPos POS = origin.mutable();
buildBaseToTipColumn(height, (blockState) -> { 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); BlocksHelper.setWithoutUpdate(level, POS, blockState);
POS.move(direction); POS.move(direction);
}, config, random); }, config, random);
@ -181,16 +189,6 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
RandomSource random) { RandomSource random) {
for (int size = 0; size < totalHeight; size++) { for (int size = 0; size < totalHeight; size++) {
consumer.accept(config.createBlock(size, totalHeight - 1, random)); 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.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.Optional;
public class IsBasin extends PlacementFilter { public class IsBasin extends PlacementFilter {
public static final Codec<IsBasin> CODEC = RecordCodecBuilder.create((instance) -> instance public static final Codec<IsBasin> CODEC = RecordCodecBuilder.create((instance) -> instance
.group( .group(
BlockPredicate.CODEC BlockPredicate.CODEC
.fieldOf("predicate") .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)); .apply(instance, IsBasin::new));
private final BlockPredicate predicate; private final BlockPredicate predicate;
private final Optional<BlockPredicate> topPredicate;
public IsBasin(BlockPredicate predicate) { public IsBasin(BlockPredicate predicate) {
this(predicate, Optional.empty());
}
public IsBasin(BlockPredicate predicate, Optional<BlockPredicate> topPredicate) {
this.predicate = predicate; this.predicate = predicate;
this.topPredicate = topPredicate;
} }
public static IsBasin simple(BlockPredicate predicate) { public static IsBasin simple(BlockPredicate predicate) {
return new IsBasin(predicate); return new IsBasin(predicate);
} }
public static IsBasin openTop(BlockPredicate predicate) {
return new IsBasin(predicate, Optional.of(BlockPredicate.ONLY_IN_AIR_PREDICATE));
}
@Override @Override
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) { protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
WorldGenLevel level = ctx.getLevel(); WorldGenLevel level = ctx.getLevel();
if (topPredicate.isPresent() && !topPredicate.get().test(level, pos.above())) return false;
return predicate.test(level, pos.below()) return predicate.test(level, pos.below())
&& predicate.test(level, pos.west()) && predicate.test(level, pos.west())
&& predicate.test(level, pos.east()) && predicate.test(level, pos.east())

View file

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

View file

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