From f007bcfa3197900e2d7c5e7d13b140e6829dc9df Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 25 Jun 2022 11:49:49 +0200 Subject: [PATCH] New Configurations for PillarFeature --- .../features/config/PillarFeatureConfig.java | 44 ++++++++++++++-- .../features/features/PillarFeature.java | 21 ++++++-- .../levelgen/features/BCLFeatureBuilder.java | 52 ++++++++++++++++--- 3 files changed, 101 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PillarFeatureConfig.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PillarFeatureConfig.java index 9c17485e..271f9c59 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PillarFeatureConfig.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PillarFeatureConfig.java @@ -9,6 +9,7 @@ import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.util.StringRepresentable; import net.minecraft.util.valueproviders.IntProvider; +import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; @@ -20,6 +21,20 @@ public class PillarFeatureConfig implements FeatureConfiguration { BlockState apply(int height, int maxHeight, BlockState inputState, BlockPos pos, RandomSource rnd); } + @FunctionalInterface + public interface PlacePredicate { + PlacePredicate ALLWAYS = (min, max, start, above, level, allow, rnd) -> true; + boolean at( + int minHeight, + int maxHeight, + BlockPos startPos, + BlockPos abovePos, + WorldGenLevel level, + BlockPredicate allowedPlacement, + RandomSource rnd + ); + } + public enum KnownTransformers implements StringRepresentable { SIZE_DECREASE( "size_decrease", @@ -35,6 +50,17 @@ public class PillarFeatureConfig implements FeatureConfiguration { "bottom_grow", (height, maxHeight, state, pos, rnd) -> state .setValue(BlockProperties.BOTTOM, height == maxHeight) + ), + TRIPLE_SHAPE_FILL( + "triple_shape_fill", + (height, maxHeight, state, pos, rnd) -> { + if (height == 0) + return state.setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.BOTTOM); + if (height == maxHeight) + return state.setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.TOP); + return state.setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.MIDDLE); + }, + (minHeight, maxHeight, startPos, abovePos, level, allow, rnd) -> !allow.test(level, abovePos) ); @@ -44,10 +70,16 @@ public class PillarFeatureConfig implements FeatureConfiguration { public final String name; public final StateTransform stateTransform; + public final PlacePredicate canPlace; KnownTransformers(String name, StateTransform stateTransform) { + this(name, stateTransform, PlacePredicate.ALLWAYS); + } + + KnownTransformers(String name, StateTransform stateTransform, PlacePredicate canPlace) { this.name = name; this.stateTransform = stateTransform; + this.canPlace = canPlace; } @Override @@ -63,7 +95,8 @@ public class PillarFeatureConfig implements FeatureConfiguration { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance .group( - IntProvider.CODEC.fieldOf("height").forGetter(o -> o.height), + IntProvider.CODEC.fieldOf("min_height").forGetter(o -> o.minHeight), + IntProvider.CODEC.fieldOf("max_height").forGetter(o -> o.maxHeight), Direction.CODEC.fieldOf("direction").orElse(Direction.UP).forGetter(o -> o.direction), BlockPredicate.CODEC.fieldOf("allowed_placement").forGetter(o -> o.allowedPlacement), BlockStateProvider.CODEC.fieldOf("state").forGetter(o -> o.stateProvider), @@ -71,7 +104,8 @@ public class PillarFeatureConfig implements FeatureConfiguration { ) .apply(instance, PillarFeatureConfig::new)); - public final IntProvider height; + public final IntProvider maxHeight; + public final IntProvider minHeight; public final BlockStateProvider stateProvider; public final KnownTransformers transformer; @@ -80,13 +114,15 @@ public class PillarFeatureConfig implements FeatureConfiguration { public PillarFeatureConfig( - IntProvider height, + IntProvider minHeight, + IntProvider maxHeight, Direction direction, BlockPredicate allowedPlacement, BlockStateProvider stateProvider, KnownTransformers transformer ) { - this.height = height; + this.minHeight = minHeight; + this.maxHeight = maxHeight; this.stateProvider = stateProvider; this.transformer = transformer; this.direction = direction; diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/PillarFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/PillarFeature.java index bf01214c..8c318022 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/PillarFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/PillarFeature.java @@ -22,22 +22,33 @@ public class PillarFeature extends Feature { final WorldGenLevel level = featurePlaceContext.level(); final PillarFeatureConfig config = featurePlaceContext.config(); final RandomSource rnd = featurePlaceContext.random(); - int maxHeight = config.height.sample(rnd); - + int maxHeight = config.maxHeight.sample(rnd); + int minHeight = config.minHeight.sample(rnd); BlockPos.MutableBlockPos posnow = featurePlaceContext.origin().mutable(); for (height = 0; height < maxHeight; ++height) { if (!config.allowedPlacement.test(level, posnow)) { - maxHeight = height - 1; + maxHeight = height; break; } posnow.move(config.direction); } - if (maxHeight < 0) return false; + if (maxHeight < minHeight) return false; + if (!config.transformer.canPlace.at( + minHeight, + maxHeight, + featurePlaceContext.origin(), + posnow, + level, + config.allowedPlacement, + rnd + )) { + return false; + } posnow = featurePlaceContext.origin().mutable(); for (height = 0; height < maxHeight; ++height) { - BlockState state = config.transform(height, maxHeight, posnow, rnd); + BlockState state = config.transform(height, maxHeight - 1, posnow, rnd); BlocksHelper.setWithoutUpdate(level, posnow, state); posnow.move(config.direction); } diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java index ccead0b2..2372cfc7 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java @@ -272,7 +272,8 @@ public abstract class BCLFeatureBuilder, FC extends Featur } public static class AsPillar extends BCLFeatureBuilder { - private IntProvider height; + private IntProvider maxHeight; + private IntProvider minHeight; private BlockStateProvider stateProvider; private final PillarFeatureConfig.KnownTransformers transformer; @@ -311,13 +312,23 @@ public abstract class BCLFeatureBuilder, FC extends Featur return this; } - public AsPillar height(int v) { - this.height = ConstantInt.of(v); + public AsPillar maxHeight(int v) { + this.maxHeight = ConstantInt.of(v); return this; } - public AsPillar height(IntProvider v) { - this.height = v; + public AsPillar maxHeight(IntProvider v) { + this.maxHeight = v; + return this; + } + + public AsPillar minHeight(int v) { + this.minHeight = ConstantInt.of(v); + return this; + } + + public AsPillar minHeight(IntProvider v) { + this.minHeight = v; return this; } @@ -327,10 +338,18 @@ public abstract class BCLFeatureBuilder, FC extends Featur if (stateProvider == null) { throw new IllegalStateException("A Pillar Features need a stateProvider"); } - if (height == null) { + if (maxHeight == null) { throw new IllegalStateException("A Pillar Features need a height"); } - return new PillarFeatureConfig(height, direction, allowedPlacement, stateProvider, transformer); + if (minHeight == null) minHeight = ConstantInt.of(0); + return new PillarFeatureConfig( + minHeight, + maxHeight, + direction, + allowedPlacement, + stateProvider, + transformer + ); } } @@ -379,6 +398,25 @@ public abstract class BCLFeatureBuilder, FC extends Featur return add(ConstantInt.of(height), state); } + protected static SimpleWeightedRandomList buildWeightedList(BlockState state) { + return SimpleWeightedRandomList + .builder() + .add(state, 1) + .build(); + } + + @SafeVarargs + public final AsBlockColumn addRandom(int height, BlockState... states) { + return this.addRandom(ConstantInt.of(height), states); + } + + @SafeVarargs + public final AsBlockColumn addRandom(IntProvider height, BlockState... states) { + var builder = SimpleWeightedRandomList.builder(); + for (BlockState state : states) builder.add(state, 1); + return add(height, new WeightedStateProvider(builder.build())); + } + public AsBlockColumn add(IntProvider height, Block block) { return add(height, BlockStateProvider.simple(block)); }