diff --git a/src/main/java/org/betterx/bclib/api/features/BCLFeature.java b/src/main/java/org/betterx/bclib/api/features/BCLFeature.java index f529b5c8..ff41bb66 100644 --- a/src/main/java/org/betterx/bclib/api/features/BCLFeature.java +++ b/src/main/java/org/betterx/bclib/api/features/BCLFeature.java @@ -15,7 +15,6 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraft.world.level.levelgen.placement.PlacementModifier; import org.betterx.bclib.BCLib; -import org.betterx.bclib.api.features.config.BlockPlaceFeatureConfig; import org.betterx.bclib.api.features.config.ScatterFeatureConfig; import java.util.Map.Entry; @@ -25,11 +24,7 @@ public class BCLFeature { public static final Feature SCATTER_ON_SOLID = register( BCLib.makeID("scatter_on_solid"), new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC) - ); - public static final Feature PLACE_BLOCK = register( - BCLib.makeID("place_block"), - new BlockPlaceFeature<>(BlockPlaceFeatureConfig.CODEC) - ); + ); private final Holder placedFeature; private final Decoration featureStep; private final Feature feature; @@ -67,12 +62,12 @@ public class BCLFeature { Holder> configuredFeature; if (!BuiltinRegistries.CONFIGURED_FEATURE.containsKey(id)) { configuredFeature = (Holder>) (Object) FeatureUtils.register(id.toString(), - feature, - configuration); + feature, + configuration); } else { configuredFeature = BuiltinRegistries.CONFIGURED_FEATURE .getHolder(ResourceKey.create(BuiltinRegistries.CONFIGURED_FEATURE.key(), - id)) + id)) .orElseThrow(); } @@ -80,7 +75,7 @@ public class BCLFeature { return PlacementUtils.register(id.toString(), configuredFeature, modifiers); } else { return BuiltinRegistries.PLACED_FEATURE.getHolder(ResourceKey.create(BuiltinRegistries.PLACED_FEATURE.key(), - id)).orElseThrow(); + id)).orElseThrow(); } } 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 618457cf..07efa707 100644 --- a/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java +++ b/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java @@ -189,10 +189,26 @@ public class BCLFeatureBuilder extends Feature { - public BlockPlaceFeature(Codec codec) { - super(codec); - } - - @Override - public boolean place(FeaturePlaceContext ctx) { - Optional state = ctx.config().getRandomBlock(ctx.random()); - if (state.isPresent()) - BlocksHelper.setWithoutUpdate(ctx.level(), ctx.origin(), state.get()); - return true; - } -} 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 b681ea23..507184b4 100644 --- a/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java +++ b/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java @@ -68,7 +68,7 @@ public class ScatterFeature .modifier(RandomOffsetPlacement.of( ClampedNormalInt.of(0.0f, 2.0f, -6, 6), ClampedNormalInt.of(0.0f, 0.6f, -2, 2))) - .modifier(BiomeFilter.biome()) + .onlyInBiome() .buildAndRegister(configuration); } @@ -107,7 +107,7 @@ public class ScatterFeature final Direction surfaceDirection = direction.getOpposite(); BlockPos.MutableBlockPos POS = new BlockPos.MutableBlockPos(); 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++) { diff --git a/src/main/java/org/betterx/bclib/api/features/config/BlockPlaceFeatureConfig.java b/src/main/java/org/betterx/bclib/api/features/config/BlockPlaceFeatureConfig.java deleted file mode 100644 index c37e5e51..00000000 --- a/src/main/java/org/betterx/bclib/api/features/config/BlockPlaceFeatureConfig.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.betterx.bclib.api.features.config; - -import net.minecraft.util.RandomSource; -import net.minecraft.util.random.SimpleWeightedRandomList; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; - -import java.util.List; -import java.util.Optional; - -public class BlockPlaceFeatureConfig implements FeatureConfiguration { - public static final Codec CODEC = SimpleWeightedRandomList - .wrappedCodec(BlockState.CODEC) - .comapFlatMap(BlockPlaceFeatureConfig::create, cfg -> cfg.weightedList) - .fieldOf("entries").codec(); - - private final SimpleWeightedRandomList weightedList; - - private static DataResult create(SimpleWeightedRandomList simpleWeightedRandomList) { - if (simpleWeightedRandomList.isEmpty()) { - return DataResult.error("BlockPlaceFeatureConfig with no states"); - } - return DataResult.success(new BlockPlaceFeatureConfig(simpleWeightedRandomList)); - } - - - private static SimpleWeightedRandomList convert(List states) { - var builder = SimpleWeightedRandomList.builder(); - for (BlockState s : states) builder.add(s, 1); - return builder.build(); - } - - public BlockPlaceFeatureConfig(Block block) { - this(block.defaultBlockState()); - } - - public BlockPlaceFeatureConfig(BlockState state) { - this(SimpleWeightedRandomList - .builder() - .add(state, 1) - .build()); - } - - public BlockPlaceFeatureConfig(List states) { - this(convert(states)); - } - - public BlockPlaceFeatureConfig(SimpleWeightedRandomList blocks) { - this.weightedList = blocks; - } - - public Optional getRandomBlock(RandomSource random) { - return this.weightedList.getRandomValue(random); - } -} diff --git a/src/main/java/org/betterx/bclib/api/features/config/ScatterFeatureConfig.java b/src/main/java/org/betterx/bclib/api/features/config/ScatterFeatureConfig.java index 9bd897a0..df83dfa9 100644 --- a/src/main/java/org/betterx/bclib/api/features/config/ScatterFeatureConfig.java +++ b/src/main/java/org/betterx/bclib/api/features/config/ScatterFeatureConfig.java @@ -17,7 +17,7 @@ import org.betterx.bclib.api.tag.CommonBlockTags; import java.util.Optional; public abstract class ScatterFeatureConfig implements FeatureConfiguration { - public interface Instancer extends Function15, Float, Float, Float, Float, Integer, Integer, Float, Float, Float, Boolean, IntProvider, T> { + public interface Instancer extends Function15, Optional, Optional, Float, Float, Float, Float, Integer, Integer, Float, Float, Float, Boolean, IntProvider, T> { } public final BlockState clusterBlock; @@ -39,8 +39,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { public final boolean growWhileFree; public ScatterFeatureConfig(BlockState clusterBlock, - BlockState tipBlock, - BlockState bottomBlock, + Optional tipBlock, + Optional bottomBlock, Optional baseState, float baseReplaceChance, float chanceOfDirectionalSpread, @@ -54,8 +54,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { boolean growWhileFree, IntProvider spreadCount) { this.clusterBlock = clusterBlock; - this.tipBlock = tipBlock == null ? clusterBlock : tipBlock; - this.bottomBlock = bottomBlock == null ? clusterBlock : bottomBlock; + this.tipBlock = tipBlock.orElse(clusterBlock); + this.bottomBlock = bottomBlock.orElse(clusterBlock); this.baseState = baseState; this.baseReplaceChance = baseReplaceChance; this.chanceOfDirectionalSpread = chanceOfDirectionalSpread; @@ -81,77 +81,81 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { public static Codec buildCodec(Instancer instancer) { return RecordCodecBuilder.create((instance) -> instance - .group(BlockState.CODEC - .fieldOf("cluster_block") - .forGetter((T cfg) -> cfg.clusterBlock), - BlockState.CODEC - .fieldOf("tip_block") - .orElse(null) - .forGetter((T cfg) -> cfg.tipBlock), - BlockState.CODEC - .fieldOf("bottom_block") - .orElse(null) - .forGetter((T cfg) -> cfg.bottomBlock), - BlockState.CODEC - .optionalFieldOf("base_state") - .forGetter((T cfg) -> cfg.baseState), - Codec - .floatRange(0.0F, 1.0F) - .fieldOf("baseReplaceChance") - .orElse(1.0F) - .forGetter((T cfg) -> cfg.baseReplaceChance), - Codec - .floatRange(0.0F, 1.0F) - .fieldOf("chance_of_directional_spread") - .orElse(0.7F) - .forGetter((T cfg) -> cfg.chanceOfDirectionalSpread), - Codec - .floatRange(0.0F, 1.0F) - .fieldOf("chance_of_spread_radius2") - .orElse(0.5F) - .forGetter((T cfg) -> cfg.chanceOfSpreadRadius2), - Codec - .floatRange(0.0F, 1.0F) - .fieldOf("chance_of_spread_radius3") - .orElse(0.5F) - .forGetter((T cfg) -> cfg.chanceOfSpreadRadius3), - Codec - .intRange(1, 20) - .fieldOf("min_height") - .orElse(2) - .forGetter((T cfg) -> cfg.minHeight), - Codec - .intRange(1, 20) - .fieldOf("max_height") - .orElse(7) - .forGetter((T cfg) -> cfg.maxHeight), - Codec - .floatRange(0, 10) - .fieldOf("max_spread") - .orElse(2f) - .forGetter((T cfg) -> cfg.maxSpread), - Codec - .floatRange(0, 1) - .fieldOf("size_variation") - .orElse(0.7f) - .forGetter((T cfg) -> cfg.sizeVariation), - Codec - .floatRange(0, 1) - .fieldOf("floor_chance") - .orElse(0.5f) - .forGetter((T cfg) -> cfg.floorChance), - Codec - .BOOL - .fieldOf("grow_while_empty") - .orElse(false) - .forGetter((T cfg) -> cfg.growWhileFree), - IntProvider.codec(0, 64) - .fieldOf("length") - .orElse(UniformInt.of(0, 3)) - .forGetter(cfg -> cfg.spreadCount) - ) - .apply(instance, instancer) - ); + .group(BlockState.CODEC + .fieldOf("cluster_block") + .forGetter((T cfg) -> cfg.clusterBlock), + BlockState.CODEC + .optionalFieldOf("tip_block") + .orElse(Optional.empty()) + .forGetter((T cfg) -> cfg.tipBlock == cfg.clusterBlock + ? Optional.empty() + : Optional.of(cfg.tipBlock)), + BlockState.CODEC + .optionalFieldOf("bottom_block") + .orElse(Optional.empty()) + .forGetter((T cfg) -> cfg.bottomBlock == cfg.clusterBlock + ? Optional.empty() + : Optional.of(cfg.bottomBlock)), + BlockState.CODEC + .optionalFieldOf("base_state") + .forGetter((T cfg) -> cfg.baseState), + Codec + .floatRange(0.0F, 1.0F) + .fieldOf("baseReplaceChance") + .orElse(1.0F) + .forGetter((T cfg) -> cfg.baseReplaceChance), + Codec + .floatRange(0.0F, 1.0F) + .fieldOf("chance_of_directional_spread") + .orElse(0.7F) + .forGetter((T cfg) -> cfg.chanceOfDirectionalSpread), + Codec + .floatRange(0.0F, 1.0F) + .fieldOf("chance_of_spread_radius2") + .orElse(0.5F) + .forGetter((T cfg) -> cfg.chanceOfSpreadRadius2), + Codec + .floatRange(0.0F, 1.0F) + .fieldOf("chance_of_spread_radius3") + .orElse(0.5F) + .forGetter((T cfg) -> cfg.chanceOfSpreadRadius3), + Codec + .intRange(1, 20) + .fieldOf("min_height") + .orElse(2) + .forGetter((T cfg) -> cfg.minHeight), + Codec + .intRange(1, 20) + .fieldOf("max_height") + .orElse(7) + .forGetter((T cfg) -> cfg.maxHeight), + Codec + .floatRange(0, 10) + .fieldOf("max_spread") + .orElse(2f) + .forGetter((T cfg) -> cfg.maxSpread), + Codec + .floatRange(0, 1) + .fieldOf("size_variation") + .orElse(0.7f) + .forGetter((T cfg) -> cfg.sizeVariation), + Codec + .floatRange(0, 1) + .fieldOf("floor_chance") + .orElse(0.5f) + .forGetter((T cfg) -> cfg.floorChance), + Codec + .BOOL + .fieldOf("grow_while_empty") + .orElse(false) + .forGetter((T cfg) -> cfg.growWhileFree), + IntProvider.codec(0, 64) + .fieldOf("length") + .orElse(UniformInt.of(0, 3)) + .forGetter(cfg -> cfg.spreadCount) + ) + .apply(instance, instancer) + ); } public static class Builder { @@ -240,10 +244,10 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { float chanceOfSpreadRadius2, float chanceOfSpreadRadius3) { return generateBaseBlock(baseState, - 1, - chanceOfDirectionalSpread, - chanceOfSpreadRadius2, - chanceOfSpreadRadius3); + 1, + chanceOfDirectionalSpread, + chanceOfSpreadRadius2, + chanceOfSpreadRadius3); } public Builder generateBaseBlock(BlockState baseState, @@ -291,8 +295,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { public T build() { return instancer.apply( this.clusterBlock, - this.tipBlock, - this.bottomBlock, + Optional.of(this.tipBlock), + Optional.of(this.bottomBlock), this.baseState, this.baseReplaceChance, this.chanceOfDirectionalSpread, @@ -305,7 +309,7 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { this.floorChance, this.growWhileFree, this.spreadCount - ); + ); } } @@ -313,8 +317,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { public static final Codec CODEC = buildCodec(OnSolid::new); public OnSolid(BlockState clusterBlock, - BlockState tipBlock, - BlockState bottomBlock, + Optional tipBlock, + Optional bottomBlock, Optional baseState, float baseReplaceChance, float chanceOfDirectionalSpread, @@ -328,20 +332,20 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { boolean growWhileFree, IntProvider spreadCount) { super(clusterBlock, - tipBlock, - bottomBlock, - baseState, - baseReplaceChance, - chanceOfDirectionalSpread, - chanceOfSpreadRadius2, - chanceOfSpreadRadius3, - minHeight, - maxHeight, - maxSpread, - sizeVariation, - floorChance, - growWhileFree, - spreadCount); + tipBlock, + bottomBlock, + baseState, + baseReplaceChance, + chanceOfDirectionalSpread, + chanceOfSpreadRadius2, + chanceOfSpreadRadius3, + minHeight, + maxHeight, + maxSpread, + sizeVariation, + floorChance, + growWhileFree, + spreadCount); } diff --git a/src/main/java/org/betterx/bclib/api/features/placement/IsEmptyAboveSampledFilter.java b/src/main/java/org/betterx/bclib/api/features/placement/IsEmptyAboveSampledFilter.java index c342ed19..46f5feb9 100644 --- a/src/main/java/org/betterx/bclib/api/features/placement/IsEmptyAboveSampledFilter.java +++ b/src/main/java/org/betterx/bclib/api/features/placement/IsEmptyAboveSampledFilter.java @@ -16,21 +16,42 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; public class IsEmptyAboveSampledFilter extends PlacementFilter { private static final IsEmptyAboveSampledFilter DEFAULT = new IsEmptyAboveSampledFilter(4, 2); private static final IsEmptyAboveSampledFilter DEFAULT1 = new IsEmptyAboveSampledFilter(1, 1); + private static final IsEmptyAboveSampledFilter DEFAULT2 = new IsEmptyAboveSampledFilter(1, 2); + + private static final IsEmptyAboveSampledFilter BELOW_DEFAULT = new IsEmptyAboveSampledFilter(-4, -2); + private static final IsEmptyAboveSampledFilter BELOW_DEFAULT1 = new IsEmptyAboveSampledFilter(-1, -1); + private static final IsEmptyAboveSampledFilter BELOW_DEFAULT2 = new IsEmptyAboveSampledFilter(-1, -2); public static final Codec CODEC = RecordCodecBuilder.create((instance) -> instance .group( - Codec.intRange(1, 32).fieldOf("d1").orElse(2).forGetter((p) -> p.distance1), - Codec.intRange(1, 32).fieldOf("d2").orElse(4).forGetter((p) -> p.distance1) - ) + Codec.intRange(-32, 32).fieldOf("d1").orElse(4).forGetter((p) -> p.distance1), + Codec.intRange(-32, 32).fieldOf("d2").orElse(2).forGetter((p) -> p.distance1) + ) .apply(instance, IsEmptyAboveSampledFilter::new)); public static PlacementFilter emptyAbove4() { return DEFAULT; } + public static PlacementFilter emptyAbove2() { + return DEFAULT2; + } + public static PlacementFilter emptyAbove() { return DEFAULT1; } + public static PlacementFilter emptyBelow4() { + return BELOW_DEFAULT; + } + + public static PlacementFilter emptyBelow2() { + return BELOW_DEFAULT2; + } + + public static PlacementFilter emptyBelow() { + return BELOW_DEFAULT1; + } + public IsEmptyAboveSampledFilter(int d1, int d2) { this.distance1 = d1; this.distance2 = d2;