diff --git a/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java b/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java index 2d276dbd..618457cf 100644 --- a/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java +++ b/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java @@ -275,6 +275,10 @@ public class BCLFeatureBuilder dir, int distance) { + return modifier(new FindSolidInDirection(dir, distance)); + } + public BCLFeatureBuilder heightmap() { return modifier(PlacementUtils.HEIGHTMAP); } diff --git a/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java b/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java index 02dc813a..b681ea23 100644 --- a/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java +++ b/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java @@ -41,21 +41,21 @@ public class ScatterFeature Feature inlineFeature) { List> set = new ArrayList<>(2); if (cfg.floorChance > 0) set.add(PlacementUtils.inlinePlaced(inlineFeature, - cfg, - EnvironmentScanPlacement.scanningFor(Direction.DOWN, - BlockPredicate.solid(), - BlockPredicate.ONLY_IN_AIR_PREDICATE, - 12), - RandomOffsetPlacement.vertical(ConstantInt.of(1)))); + cfg, + EnvironmentScanPlacement.scanningFor(Direction.DOWN, + BlockPredicate.solid(), + BlockPredicate.ONLY_IN_AIR_PREDICATE, + 12), + RandomOffsetPlacement.vertical(ConstantInt.of(1)))); if (cfg.floorChance < 1) { set.add(PlacementUtils.inlinePlaced(inlineFeature, - cfg, - EnvironmentScanPlacement.scanningFor(Direction.UP, - BlockPredicate.solid(), - BlockPredicate.ONLY_IN_AIR_PREDICATE, - 12), - RandomOffsetPlacement.vertical(ConstantInt.of(-1)))); + cfg, + EnvironmentScanPlacement.scanningFor(Direction.UP, + BlockPredicate.solid(), + BlockPredicate.ONLY_IN_AIR_PREDICATE, + 12), + RandomOffsetPlacement.vertical(ConstantInt.of(-1)))); } SimpleRandomFeatureConfiguration configuration = new SimpleRandomFeatureConfiguration(HolderSet.direct(set)); @@ -87,7 +87,8 @@ public class ScatterFeature if (direction.isEmpty()) { return false; } - BlockPos basePos = origin.relative(direction.get().getOpposite()); + BlockPos basePos = origin.relative(direction.get(), -1); + int i = (int) (random.nextFloat() * (1 + config.maxHeight - config.minHeight) + config.minHeight); growCenterPillar(level, origin, basePos, direction.get(), i, config, random); @@ -105,10 +106,8 @@ public class ScatterFeature if (config.isValidBase(level.getBlockState(basePos))) { final Direction surfaceDirection = direction.getOpposite(); BlockPos.MutableBlockPos POS = new BlockPos.MutableBlockPos(); - basePos = basePos.relative(direction, 1); buildPillarWithBase(level, origin, basePos, direction, centerHeight, config, random); - - + final double distNormalizer = (config.maxSpread * Math.sqrt(2)); final int tryCount = config.spreadCount.sample(random); for (int i = 0; i < tryCount; i++) { @@ -120,10 +119,10 @@ public class ScatterFeature int myHeight; if (config.growWhileFree) { myHeight = BlocksHelper.blockCount(level, - POS, - direction, - config.maxHeight, - state -> state.getMaterial().isReplaceable()); + POS, + direction, + config.maxHeight, + state -> state.getMaterial().isReplaceable()); } else { myHeight = centerHeight; } @@ -136,15 +135,15 @@ public class ScatterFeature myHeight = (int) Math.min(Math.max( config.minHeight, config.minHeight + sizeFactor * (myHeight - config.minHeight) - ), config.maxHeight); + ), config.maxHeight); buildPillarWithBase(level, - POS, - POS.relative(direction.getOpposite()), - direction, - myHeight, - config, - random); + POS, + POS.relative(direction.getOpposite()), + direction, + myHeight, + config, + random); } } } diff --git a/src/main/java/org/betterx/bclib/api/features/placement/FindSolidInDirection.java b/src/main/java/org/betterx/bclib/api/features/placement/FindSolidInDirection.java index f634886d..d73ebb96 100644 --- a/src/main/java/org/betterx/bclib/api/features/placement/FindSolidInDirection.java +++ b/src/main/java/org/betterx/bclib/api/features/placement/FindSolidInDirection.java @@ -2,6 +2,7 @@ package org.betterx.bclib.api.features.placement; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.util.ExtraCodecs; import net.minecraft.util.RandomSource; import net.minecraft.world.level.levelgen.placement.PlacementContext; import net.minecraft.world.level.levelgen.placement.PlacementModifier; @@ -12,20 +13,30 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import org.betterx.bclib.api.tag.CommonBlockTags; import org.betterx.bclib.util.BlocksHelper; +import java.util.List; import java.util.stream.Stream; public class FindSolidInDirection extends PlacementModifier { + public static final Codec CODEC = RecordCodecBuilder + .create((instance) -> instance.group( + ExtraCodecs.nonEmptyList(Direction.CODEC.listOf()) + .fieldOf("dir") + .orElse(List.of(Direction.DOWN)) + .forGetter(a -> a.direction), + Codec.intRange(1, 32).fieldOf("dist").orElse(12).forGetter((p) -> p.maxSearchDistance)) + .apply(instance, + FindSolidInDirection::new)); protected static final FindSolidInDirection DOWN = new FindSolidInDirection(Direction.DOWN, 6); protected static final FindSolidInDirection UP = new FindSolidInDirection(Direction.UP, 6); - public static final Codec CODEC = RecordCodecBuilder.create((instance) -> instance - .group( - Direction.CODEC.fieldOf("dir").orElse(Direction.DOWN).forGetter((p) -> p.direction), - Codec.intRange(1, 32).fieldOf("dist").orElse(12).forGetter((p) -> p.maxSearchDistance) - ) - .apply(instance, FindSolidInDirection::new)); + private final List direction; + private final int maxSearchDistance; public FindSolidInDirection(Direction direction, int maxSearchDistance) { + this(List.of(direction), maxSearchDistance); + } + + public FindSolidInDirection(List direction, int maxSearchDistance) { this.direction = direction; this.maxSearchDistance = maxSearchDistance; } @@ -48,25 +59,26 @@ public class FindSolidInDirection extends PlacementModifier { return new FindSolidInDirection(Direction.UP, dist); } + public Direction randomDirection(RandomSource random) { + return direction.get(Math.max(0, Math.min(direction.size(), random.nextInt(direction.size())))); + } @Override public Stream getPositions(PlacementContext placementContext, RandomSource randomSource, BlockPos blockPos) { BlockPos.MutableBlockPos POS = blockPos.mutable(); - if (BlocksHelper.findSurroundingSurface(placementContext.getLevel(), - POS, - direction, - maxSearchDistance, - state -> state.is(CommonBlockTags.TERRAIN)) - ) return Stream.of(POS); + Direction d = randomDirection(randomSource); + if (BlocksHelper.findOnSurroundingSurface(placementContext.getLevel(), + POS, + d, + maxSearchDistance, + state -> state.is(CommonBlockTags.TERRAIN))) + return Stream.of(POS); return Stream.of(); } - private final Direction direction; - private final int maxSearchDistance; - @Override public PlacementModifierType type() { return PlacementModifiers.SOLID_IN_DIR; diff --git a/src/main/java/org/betterx/bclib/util/BlocksHelper.java b/src/main/java/org/betterx/bclib/util/BlocksHelper.java index e0ee04cc..ec94ba34 100644 --- a/src/main/java/org/betterx/bclib/util/BlocksHelper.java +++ b/src/main/java/org/betterx/bclib/util/BlocksHelper.java @@ -229,6 +229,31 @@ public class BlocksHelper { return false; } + public static boolean findOnSurroundingSurface(LevelAccessor level, + MutableBlockPos startPos, + Direction dir, + int length, + Predicate surface) { + for (int len = 0; len < length; len++) { + if (surface.test(level.getBlockState(startPos))) { + if (len == 0) { //we started inside of the surface + for (int lenUp = 0; lenUp < length; lenUp++) { + startPos.move(dir, -1); + if (!surface.test(level.getBlockState(startPos))) { + return true; + } + } + return false; + } + startPos.move(dir, -1); + return true; + } + + startPos.move(dir, 1); + } + return false; + } + public static boolean findSurroundingSurface(LevelAccessor level, MutableBlockPos startPos, Direction dir,