Added Warp Cap Feature

This commit is contained in:
Frank 2022-06-03 11:31:56 +02:00
parent 3a61c4cb86
commit f82d8b6178
4 changed files with 82 additions and 42 deletions

View file

@ -275,6 +275,10 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
return modifier(new FindSolidInDirection(dir, distance)); return modifier(new FindSolidInDirection(dir, distance));
} }
public BCLFeatureBuilder findSolidSurface(List<Direction> dir, int distance) {
return modifier(new FindSolidInDirection(dir, distance));
}
public BCLFeatureBuilder heightmap() { public BCLFeatureBuilder heightmap() {
return modifier(PlacementUtils.HEIGHTMAP); return modifier(PlacementUtils.HEIGHTMAP);
} }

View file

@ -41,21 +41,21 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
Feature<T> inlineFeature) { Feature<T> inlineFeature) {
List<Holder<PlacedFeature>> set = new ArrayList<>(2); List<Holder<PlacedFeature>> set = new ArrayList<>(2);
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.solid(),
BlockPredicate.ONLY_IN_AIR_PREDICATE, BlockPredicate.ONLY_IN_AIR_PREDICATE,
12), 12),
RandomOffsetPlacement.vertical(ConstantInt.of(1)))); RandomOffsetPlacement.vertical(ConstantInt.of(1))));
if (cfg.floorChance < 1) { if (cfg.floorChance < 1) {
set.add(PlacementUtils.inlinePlaced(inlineFeature, set.add(PlacementUtils.inlinePlaced(inlineFeature,
cfg, cfg,
EnvironmentScanPlacement.scanningFor(Direction.UP, EnvironmentScanPlacement.scanningFor(Direction.UP,
BlockPredicate.solid(), BlockPredicate.solid(),
BlockPredicate.ONLY_IN_AIR_PREDICATE, BlockPredicate.ONLY_IN_AIR_PREDICATE,
12), 12),
RandomOffsetPlacement.vertical(ConstantInt.of(-1)))); RandomOffsetPlacement.vertical(ConstantInt.of(-1))));
} }
SimpleRandomFeatureConfiguration configuration = new SimpleRandomFeatureConfiguration(HolderSet.direct(set)); SimpleRandomFeatureConfiguration configuration = new SimpleRandomFeatureConfiguration(HolderSet.direct(set));
@ -87,7 +87,8 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
if (direction.isEmpty()) { if (direction.isEmpty()) {
return false; 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); int i = (int) (random.nextFloat() * (1 + config.maxHeight - config.minHeight) + config.minHeight);
growCenterPillar(level, origin, basePos, direction.get(), i, config, random); growCenterPillar(level, origin, basePos, direction.get(), i, config, random);
@ -105,10 +106,8 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
if (config.isValidBase(level.getBlockState(basePos))) { if (config.isValidBase(level.getBlockState(basePos))) {
final Direction surfaceDirection = direction.getOpposite(); final Direction surfaceDirection = direction.getOpposite();
BlockPos.MutableBlockPos POS = new BlockPos.MutableBlockPos(); BlockPos.MutableBlockPos POS = new BlockPos.MutableBlockPos();
basePos = basePos.relative(direction, 1);
buildPillarWithBase(level, origin, basePos, direction, centerHeight, config, random); buildPillarWithBase(level, origin, basePos, direction, centerHeight, config, random);
final double distNormalizer = (config.maxSpread * Math.sqrt(2)); final double distNormalizer = (config.maxSpread * Math.sqrt(2));
final int tryCount = config.spreadCount.sample(random); final int tryCount = config.spreadCount.sample(random);
for (int i = 0; i < tryCount; i++) { for (int i = 0; i < tryCount; i++) {
@ -120,10 +119,10 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
int myHeight; int myHeight;
if (config.growWhileFree) { if (config.growWhileFree) {
myHeight = BlocksHelper.blockCount(level, myHeight = BlocksHelper.blockCount(level,
POS, POS,
direction, direction,
config.maxHeight, config.maxHeight,
state -> state.getMaterial().isReplaceable()); state -> state.getMaterial().isReplaceable());
} else { } else {
myHeight = centerHeight; myHeight = centerHeight;
} }
@ -136,15 +135,15 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
myHeight = (int) Math.min(Math.max( myHeight = (int) Math.min(Math.max(
config.minHeight, config.minHeight,
config.minHeight + sizeFactor * (myHeight - config.minHeight) config.minHeight + sizeFactor * (myHeight - config.minHeight)
), config.maxHeight); ), config.maxHeight);
buildPillarWithBase(level, buildPillarWithBase(level,
POS, POS,
POS.relative(direction.getOpposite()), POS.relative(direction.getOpposite()),
direction, direction,
myHeight, myHeight,
config, config,
random); random);
} }
} }
} }

View file

@ -2,6 +2,7 @@ package org.betterx.bclib.api.features.placement;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.placement.PlacementContext; import net.minecraft.world.level.levelgen.placement.PlacementContext;
import net.minecraft.world.level.levelgen.placement.PlacementModifier; 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.api.tag.CommonBlockTags;
import org.betterx.bclib.util.BlocksHelper; import org.betterx.bclib.util.BlocksHelper;
import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
public class FindSolidInDirection extends PlacementModifier { public class FindSolidInDirection extends PlacementModifier {
public static final Codec<FindSolidInDirection> 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 DOWN = new FindSolidInDirection(Direction.DOWN, 6);
protected static final FindSolidInDirection UP = new FindSolidInDirection(Direction.UP, 6); protected static final FindSolidInDirection UP = new FindSolidInDirection(Direction.UP, 6);
public static final Codec<FindSolidInDirection> CODEC = RecordCodecBuilder.create((instance) -> instance private final List<Direction> direction;
.group( private final int maxSearchDistance;
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));
public FindSolidInDirection(Direction direction, int maxSearchDistance) { public FindSolidInDirection(Direction direction, int maxSearchDistance) {
this(List.of(direction), maxSearchDistance);
}
public FindSolidInDirection(List<Direction> direction, int maxSearchDistance) {
this.direction = direction; this.direction = direction;
this.maxSearchDistance = maxSearchDistance; this.maxSearchDistance = maxSearchDistance;
} }
@ -48,25 +59,26 @@ public class FindSolidInDirection extends PlacementModifier {
return new FindSolidInDirection(Direction.UP, dist); 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 @Override
public Stream<BlockPos> getPositions(PlacementContext placementContext, public Stream<BlockPos> getPositions(PlacementContext placementContext,
RandomSource randomSource, RandomSource randomSource,
BlockPos blockPos) { BlockPos blockPos) {
BlockPos.MutableBlockPos POS = blockPos.mutable(); BlockPos.MutableBlockPos POS = blockPos.mutable();
if (BlocksHelper.findSurroundingSurface(placementContext.getLevel(), Direction d = randomDirection(randomSource);
POS, if (BlocksHelper.findOnSurroundingSurface(placementContext.getLevel(),
direction, POS,
maxSearchDistance, d,
state -> state.is(CommonBlockTags.TERRAIN)) maxSearchDistance,
) return Stream.of(POS); state -> state.is(CommonBlockTags.TERRAIN)))
return Stream.of(POS);
return Stream.of(); return Stream.of();
} }
private final Direction direction;
private final int maxSearchDistance;
@Override @Override
public PlacementModifierType<?> type() { public PlacementModifierType<?> type() {
return PlacementModifiers.SOLID_IN_DIR; return PlacementModifiers.SOLID_IN_DIR;

View file

@ -229,6 +229,31 @@ public class BlocksHelper {
return false; return false;
} }
public static boolean findOnSurroundingSurface(LevelAccessor level,
MutableBlockPos startPos,
Direction dir,
int length,
Predicate<BlockState> 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, public static boolean findSurroundingSurface(LevelAccessor level,
MutableBlockPos startPos, MutableBlockPos startPos,
Direction dir, Direction dir,