Enhanced new Feature Builders.
This commit is contained in:
parent
c4875b992a
commit
a1d6de908c
17 changed files with 880 additions and 133 deletions
|
@ -147,7 +147,8 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
|
|||
|
||||
|
||||
private static boolean isValidNetherBiome(Holder<Biome> biome, ResourceLocation location) {
|
||||
return biome.unwrapKey().get().location().toString().equals("betternether:bone_reef");
|
||||
return biome.unwrapKey().get().location().toString().contains("bone_reef");
|
||||
|
||||
// return NetherBiomes.canGenerateInNether(biome.unwrapKey().get()) ||
|
||||
// biome.is(BiomeTags.IS_NETHER) ||
|
||||
// BiomeAPI.wasRegisteredAsNetherBiome(location);
|
||||
|
|
|
@ -636,6 +636,19 @@ public class BiomeAPI {
|
|||
addBiomeFeature(biome, feature.getDecoration(), feature.getPlacedFeature());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new features to existing biome.
|
||||
*
|
||||
* @param biome {@link Biome} to add features in.
|
||||
* @param feature {@link ConfiguredFeature} to add.
|
||||
*/
|
||||
public static void addBiomeFeature(
|
||||
Holder<Biome> biome,
|
||||
org.betterx.bclib.api.v3.levelgen.features.BCLFeature feature
|
||||
) {
|
||||
addBiomeFeature(biome, feature.getDecoration(), feature.getPlacedFeature());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new features to existing biome.
|
||||
*
|
||||
|
|
|
@ -73,6 +73,11 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
|
|||
BCLib.makeID("condition"),
|
||||
new ConditionFeature()
|
||||
);
|
||||
|
||||
public static final Feature<PillarFeatureConfig> PILLAR = register(
|
||||
BCLib.makeID("pillar"),
|
||||
new PillarFeature()
|
||||
);
|
||||
private final Holder<PlacedFeature> placedFeature;
|
||||
private final Decoration featureStep;
|
||||
private final F feature;
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.features.config;
|
||||
|
||||
import org.betterx.bclib.blocks.BCLBlockProperties;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
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.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
||||
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
|
||||
public class PillarFeatureConfig implements FeatureConfiguration {
|
||||
@FunctionalInterface
|
||||
public interface StateTransform {
|
||||
int apply(int height, int maxHeight, BlockState inputState, BlockPos pos, RandomSource rnd);
|
||||
}
|
||||
|
||||
public enum KnownTransformers implements StringRepresentable {
|
||||
SIZE_DECREASE(
|
||||
"size_decrease",
|
||||
BCLBlockProperties.SIZE,
|
||||
(height, maxHeight, state, pos, rnd) -> Math.max(0, Math.min(7, maxHeight - height))
|
||||
),
|
||||
SIZE_INCREASE(
|
||||
"size_increase",
|
||||
BCLBlockProperties.SIZE,
|
||||
(height, maxHeight, state, pos, rnd) -> Math.max(0, Math.min(7, height))
|
||||
);
|
||||
|
||||
|
||||
public static final StringRepresentable.EnumCodec<KnownTransformers> CODEC = StringRepresentable
|
||||
.fromEnum(KnownTransformers::values);
|
||||
|
||||
|
||||
public final String name;
|
||||
public final IntegerProperty property;
|
||||
public final StateTransform transform;
|
||||
|
||||
KnownTransformers(String name, IntegerProperty property, StateTransform transform) {
|
||||
this.name = name;
|
||||
this.property = property;
|
||||
this.transform = transform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSerializedName() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
public static final Codec<PillarFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
IntProvider.CODEC.fieldOf("height").forGetter(o -> o.height),
|
||||
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),
|
||||
KnownTransformers.CODEC.fieldOf("transform").forGetter(o -> o.transformer)
|
||||
)
|
||||
.apply(instance, PillarFeatureConfig::new));
|
||||
|
||||
public final IntProvider height;
|
||||
public final BlockStateProvider stateProvider;
|
||||
|
||||
public final KnownTransformers transformer;
|
||||
public final Direction direction;
|
||||
public final BlockPredicate allowedPlacement;
|
||||
|
||||
|
||||
public PillarFeatureConfig(
|
||||
IntProvider height,
|
||||
Direction direction,
|
||||
BlockPredicate allowedPlacement,
|
||||
BlockStateProvider stateProvider,
|
||||
KnownTransformers transformer
|
||||
) {
|
||||
this.height = height;
|
||||
this.stateProvider = stateProvider;
|
||||
this.transformer = transformer;
|
||||
this.direction = direction;
|
||||
this.allowedPlacement = allowedPlacement;
|
||||
}
|
||||
|
||||
public BlockState transform(int currentHeight, int maxHeight, BlockPos pos, RandomSource rnd) {
|
||||
BlockState state = stateProvider.getState(rnd, pos);
|
||||
return state.setValue(
|
||||
transformer.property,
|
||||
transformer.transform.apply(currentHeight, maxHeight, state, pos, rnd)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.features.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.PillarFeatureConfig;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
|
||||
public class PillarFeature extends Feature<PillarFeatureConfig> {
|
||||
public PillarFeature() {
|
||||
super(PillarFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<PillarFeatureConfig> featurePlaceContext) {
|
||||
int height;
|
||||
final WorldGenLevel level = featurePlaceContext.level();
|
||||
final PillarFeatureConfig config = featurePlaceContext.config();
|
||||
final RandomSource rnd = featurePlaceContext.random();
|
||||
int maxHeight = config.height.sample(rnd);
|
||||
|
||||
BlockPos.MutableBlockPos posnow = featurePlaceContext.origin().mutable();
|
||||
|
||||
for (height = 0; height < maxHeight; ++height) {
|
||||
if (!config.allowedPlacement.test(level, posnow)) {
|
||||
maxHeight = height - 1;
|
||||
break;
|
||||
}
|
||||
posnow.move(config.direction);
|
||||
}
|
||||
if (maxHeight < 0) return false;
|
||||
|
||||
posnow = featurePlaceContext.origin().mutable();
|
||||
for (height = 0; height < maxHeight; ++height) {
|
||||
BlockState state = config.transform(height, maxHeight, posnow, rnd);
|
||||
BlocksHelper.setWithoutUpdate(level, posnow, state);
|
||||
posnow.move(config.direction);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
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;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ForAll extends PlacementModifier {
|
||||
public static final Codec<ForAll> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
ExtraCodecs.nonEmptyList(PlacementModifier.CODEC.listOf())
|
||||
.fieldOf("modifiers")
|
||||
.forGetter(a -> a.modifiers)
|
||||
)
|
||||
.apply(instance, ForAll::new));
|
||||
|
||||
private final List<PlacementModifier> modifiers;
|
||||
|
||||
public ForAll(List<PlacementModifier> modifiers) {
|
||||
this.modifiers = modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<BlockPos> getPositions(
|
||||
PlacementContext placementContext,
|
||||
RandomSource randomSource,
|
||||
BlockPos blockPos
|
||||
) {
|
||||
Stream.Builder<BlockPos> stream = Stream.builder();
|
||||
for (PlacementModifier p : modifiers) {
|
||||
p.getPositions(placementContext, randomSource, blockPos).forEach(pp -> stream.add(pp));
|
||||
}
|
||||
return stream.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementModifierType<?> type() {
|
||||
return PlacementModifiers.FOR_ALL;
|
||||
}
|
||||
}
|
|
@ -42,6 +42,10 @@ public class Is extends PlacementFilter {
|
|||
return new Is(predicate, Optional.of(Direction.DOWN.getNormal()));
|
||||
}
|
||||
|
||||
public static Is above(BlockPredicate predicate) {
|
||||
return new Is(predicate, Optional.of(Direction.UP.getNormal()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
|
||||
WorldGenLevel level = ctx.getLevel();
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementContext;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementFilter;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
|
||||
|
||||
import java.util.Optional;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class IsNextTo extends PlacementFilter {
|
||||
public static final Codec<IsNextTo> CODEC = RecordCodecBuilder.create((instance) -> instance
|
||||
.group(
|
||||
BlockPredicate.CODEC
|
||||
.fieldOf("predicate")
|
||||
.forGetter(cfg -> cfg.predicate),
|
||||
Vec3i.CODEC
|
||||
.optionalFieldOf("offset")
|
||||
.forGetter(cfg -> Optional.of(cfg.offset))
|
||||
)
|
||||
.apply(instance, IsNextTo::new));
|
||||
|
||||
private final BlockPredicate predicate;
|
||||
private final Vec3i offset;
|
||||
|
||||
public IsNextTo(BlockPredicate predicate) {
|
||||
this(predicate, Optional.of(Vec3i.ZERO));
|
||||
}
|
||||
|
||||
public IsNextTo(BlockPredicate predicate, Optional<Vec3i> offset) {
|
||||
this(predicate, offset.orElse(Vec3i.ZERO));
|
||||
}
|
||||
|
||||
public IsNextTo(@NotNull BlockPredicate predicate, @NotNull Vec3i offset) {
|
||||
this.predicate = predicate;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public static PlacementFilter simple(BlockPredicate predicate) {
|
||||
return new IsBasin(predicate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
|
||||
WorldGenLevel level = ctx.getLevel();
|
||||
|
||||
pos = pos.offset(this.offset);
|
||||
return predicate.test(level, pos.west())
|
||||
|| predicate.test(level, pos.east())
|
||||
|| predicate.test(level, pos.north())
|
||||
|| predicate.test(level, pos.south());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementModifierType<?> type() {
|
||||
return PlacementModifiers.IS_NEXT_TO;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,11 @@ public class PlacementModifiers {
|
|||
MinEmptyFilter.CODEC
|
||||
);
|
||||
|
||||
public static final PlacementModifierType<ForAll> FOR_ALL = register(
|
||||
"for_all",
|
||||
ForAll.CODEC
|
||||
);
|
||||
|
||||
public static final PlacementModifierType<FindSolidInDirection> SOLID_IN_DIR = register(
|
||||
"solid_in_dir",
|
||||
FindSolidInDirection.CODEC
|
||||
|
@ -39,6 +44,11 @@ public class PlacementModifiers {
|
|||
IsBasin.CODEC
|
||||
);
|
||||
|
||||
public static final PlacementModifierType<IsNextTo> IS_NEXT_TO = register(
|
||||
"is_next_to",
|
||||
IsNextTo.CODEC
|
||||
);
|
||||
|
||||
public static final PlacementModifierType<Is> IS = register(
|
||||
"is",
|
||||
Is.CODEC
|
||||
|
|
|
@ -32,6 +32,7 @@ public class CommonBlockTags {
|
|||
|
||||
public static final TagKey<Block> IS_OBSIDIAN = TagAPI.makeCommonBlockTag("is_obsidian");
|
||||
public static final TagKey<Block> TERRAIN = TagAPI.makeCommonBlockTag("terrain");
|
||||
public static final TagKey<Block> NETHER_TERRAIN = TagAPI.makeCommonBlockTag("nether_terrain");
|
||||
|
||||
static {
|
||||
TagAPI.BLOCKS.add(END_STONES, Blocks.END_STONE);
|
||||
|
@ -67,15 +68,31 @@ public class CommonBlockTags {
|
|||
);
|
||||
TagAPI.BLOCKS.addOtherTags(
|
||||
TERRAIN,
|
||||
NETHER_TERRAIN,
|
||||
BlockTags.DRIPSTONE_REPLACEABLE,
|
||||
BlockTags.BASE_STONE_OVERWORLD,
|
||||
BlockTags.NYLIUM,
|
||||
MYCELIUM,
|
||||
END_STONES
|
||||
);
|
||||
|
||||
TagAPI.BLOCKS.add(
|
||||
NETHER_TERRAIN,
|
||||
Blocks.MAGMA_BLOCK,
|
||||
Blocks.GRAVEL,
|
||||
Blocks.RED_SAND,
|
||||
Blocks.GLOWSTONE,
|
||||
Blocks.BONE_BLOCK,
|
||||
Blocks.SCULK
|
||||
);
|
||||
TagAPI.BLOCKS.addOtherTags(
|
||||
NETHER_TERRAIN,
|
||||
NETHERRACK,
|
||||
BlockTags.NYLIUM,
|
||||
NETHER_STONES,
|
||||
NETHER_ORES,
|
||||
SOUL_GROUND,
|
||||
NETHER_MYCELIUM,
|
||||
MYCELIUM,
|
||||
END_STONES
|
||||
NETHER_MYCELIUM
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,4 +33,12 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
|
|||
this.placedFeature = placed;
|
||||
this.decoration = decoration;
|
||||
}
|
||||
|
||||
public Holder<PlacedFeature> getPlacedFeature() {
|
||||
return placedFeature;
|
||||
}
|
||||
|
||||
public GenerationStep.Decoration getDecoration() {
|
||||
return decoration;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,447 @@
|
|||
package org.betterx.bclib.api.v3.levelgen.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.PillarFeatureConfig;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.SequenceFeatureConfig;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.TemplateFeatureConfig;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.PillarFeature;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.TemplateFeature;
|
||||
import org.betterx.bclib.api.v2.levelgen.structures.StructurePlacementType;
|
||||
import org.betterx.bclib.api.v2.levelgen.structures.StructureWorldNBT;
|
||||
import org.betterx.bclib.api.v2.poi.BCLPoiType;
|
||||
import org.betterx.bclib.blocks.BCLBlockProperties;
|
||||
import org.betterx.bclib.blocks.BlockProperties;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.random.SimpleWeightedRandomList;
|
||||
import net.minecraft.util.valueproviders.ConstantInt;
|
||||
import net.minecraft.util.valueproviders.IntProvider;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
|
||||
import net.minecraft.world.level.levelgen.feature.*;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.*;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockMatchTest;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.RuleTest;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends FeatureConfiguration> {
|
||||
private final ResourceLocation featureID;
|
||||
private final F feature;
|
||||
|
||||
private BCLFeatureBuilder(ResourceLocation featureID, F feature) {
|
||||
this.featureID = featureID;
|
||||
this.feature = feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new {@link BCLFeature} builder.
|
||||
*
|
||||
* @param featureID {@link ResourceLocation} feature identifier.
|
||||
* @param feature {@link Feature} to construct.
|
||||
* @return {@link org.betterx.bclib.api.v2.levelgen.features.BCLFeatureBuilder} instance.
|
||||
*/
|
||||
public static <F extends Feature<FC>, FC extends FeatureConfiguration> WithConfiguration<F, FC> start(
|
||||
ResourceLocation featureID,
|
||||
F feature
|
||||
) {
|
||||
return new WithConfiguration(featureID, feature);
|
||||
}
|
||||
|
||||
public static ForSimpleBlock<SimpleBlockFeature> start(
|
||||
ResourceLocation featureID,
|
||||
Block block
|
||||
) {
|
||||
return start(featureID, BlockStateProvider.simple(block));
|
||||
}
|
||||
|
||||
public static ForSimpleBlock<SimpleBlockFeature> start(
|
||||
ResourceLocation featureID,
|
||||
BlockState state
|
||||
) {
|
||||
return start(featureID, BlockStateProvider.simple(state));
|
||||
}
|
||||
|
||||
public static ForSimpleBlock<SimpleBlockFeature> start(
|
||||
ResourceLocation featureID,
|
||||
BlockStateProvider provider
|
||||
) {
|
||||
ForSimpleBlock<SimpleBlockFeature> builder = new ForSimpleBlock(
|
||||
featureID,
|
||||
Feature.SIMPLE_BLOCK,
|
||||
provider
|
||||
);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static RandomPatch startRandomPatch(
|
||||
ResourceLocation featureID,
|
||||
Holder<PlacedFeature> featureToPlace
|
||||
) {
|
||||
RandomPatch builder = new RandomPatch(
|
||||
featureID,
|
||||
Feature.RANDOM_PATCH,
|
||||
featureToPlace
|
||||
);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static NetherForrestVegetation startNetherVegetation(
|
||||
ResourceLocation featureID
|
||||
) {
|
||||
NetherForrestVegetation builder = new NetherForrestVegetation(
|
||||
featureID,
|
||||
Feature.NETHER_FOREST_VEGETATION
|
||||
);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static WithTemplates<Feature<TemplateFeatureConfig>> startWithTemplates(
|
||||
ResourceLocation featureID
|
||||
) {
|
||||
WithTemplates<Feature<TemplateFeatureConfig>> builder = new WithTemplates<>(
|
||||
featureID,
|
||||
(TemplateFeature) org.betterx.bclib.api.v3.levelgen.features.BCLFeature.TEMPLATE
|
||||
);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static AsBlockColumn<BlockColumnFeature> startColumn(
|
||||
ResourceLocation featureID
|
||||
) {
|
||||
AsBlockColumn<BlockColumnFeature> builder = new AsBlockColumn<>(
|
||||
featureID,
|
||||
(BlockColumnFeature) Feature.BLOCK_COLUMN
|
||||
);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static AsPillar startPillar(
|
||||
ResourceLocation featureID,
|
||||
PillarFeatureConfig.KnownTransformers transformer
|
||||
) {
|
||||
AsPillar builder = new AsPillar(
|
||||
featureID,
|
||||
(PillarFeature) BCLFeature.PILLAR,
|
||||
transformer
|
||||
);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static AsSequence<Feature<SequenceFeatureConfig>> startSequence(
|
||||
ResourceLocation featureID
|
||||
) {
|
||||
AsSequence<Feature<SequenceFeatureConfig>> builder = new AsSequence<>(
|
||||
featureID,
|
||||
org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SEQUENCE
|
||||
);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static AsOre startOre(
|
||||
ResourceLocation featureID
|
||||
) {
|
||||
AsOre builder = new AsOre(
|
||||
featureID,
|
||||
(OreFeature) Feature.ORE
|
||||
);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internally used by the builder. Normally you should not have to call this method directly as it is
|
||||
* handled by {@link #buildAndRegister()}
|
||||
*
|
||||
* @param id The ID to register this feature with
|
||||
* @param cFeature The configured Feature
|
||||
* @param <F> The Feature Class
|
||||
* @param <FC> The FeatureConfiguration Class
|
||||
* @return The Holder for the new Feature
|
||||
*/
|
||||
public static <F extends Feature<FC>, FC extends FeatureConfiguration> Holder<ConfiguredFeature<FC, F>> register(
|
||||
ResourceLocation id,
|
||||
ConfiguredFeature<FC, F> cFeature
|
||||
) {
|
||||
return (Holder<ConfiguredFeature<FC, F>>) (Object) BuiltinRegistries.register(
|
||||
BuiltinRegistries.CONFIGURED_FEATURE,
|
||||
id,
|
||||
cFeature
|
||||
);
|
||||
}
|
||||
|
||||
public abstract FC createConfiguration();
|
||||
|
||||
protected BCLConfigureFeature<F, FC> buildAndRegister(BiFunction<ResourceLocation, ConfiguredFeature<FC, F>, Holder<ConfiguredFeature<FC, F>>> holderBuilder) {
|
||||
FC config = createConfiguration();
|
||||
if (config == null) {
|
||||
throw new IllegalStateException("Feature configuration for " + featureID + " can not be null!");
|
||||
}
|
||||
ConfiguredFeature<FC, F> cFeature = new ConfiguredFeature<FC, F>(feature, config);
|
||||
Holder<ConfiguredFeature<FC, F>> holder = holderBuilder.apply(featureID, cFeature);
|
||||
return new BCLConfigureFeature<>(featureID, holder, true);
|
||||
}
|
||||
|
||||
public BCLConfigureFeature<F, FC> buildAndRegister() {
|
||||
return buildAndRegister(BCLFeatureBuilder::register);
|
||||
}
|
||||
|
||||
public BCLConfigureFeature<F, FC> build() {
|
||||
return buildAndRegister((id, cFeature) -> Holder.direct(cFeature));
|
||||
}
|
||||
|
||||
public BCLInlinePlacedBuilder<F, FC> inlinePlace() {
|
||||
BCLConfigureFeature<F, FC> f = build();
|
||||
return BCLInlinePlacedBuilder.place(f);
|
||||
}
|
||||
|
||||
public Holder<PlacedFeature> inlinePlace(BCLInlinePlacedBuilder<F, FC> placer) {
|
||||
BCLConfigureFeature<F, FC> f = build();
|
||||
return placer.build(f);
|
||||
}
|
||||
|
||||
public static class AsOre extends BCLFeatureBuilder<OreFeature, OreConfiguration> {
|
||||
private final List<OreConfiguration.TargetBlockState> targetStates = new LinkedList<>();
|
||||
private int size = 6;
|
||||
private float discardChanceOnAirExposure = 0;
|
||||
|
||||
private AsOre(ResourceLocation featureID, OreFeature feature) {
|
||||
super(featureID, feature);
|
||||
}
|
||||
|
||||
public AsOre add(Block containedIn, Block ore) {
|
||||
return this.add(containedIn, ore.defaultBlockState());
|
||||
}
|
||||
|
||||
public AsOre add(Block containedIn, BlockState ore) {
|
||||
return this.add(new BlockMatchTest(containedIn), ore);
|
||||
}
|
||||
|
||||
public AsOre add(RuleTest containedIn, Block ore) {
|
||||
return this.add(containedIn, ore.defaultBlockState());
|
||||
}
|
||||
|
||||
public AsOre add(RuleTest containedIn, BlockState ore) {
|
||||
targetStates.add(OreConfiguration.target(
|
||||
containedIn,
|
||||
ore
|
||||
));
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsOre veinSize(int size) {
|
||||
this.size = size;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsOre discardChanceOnAirExposure(float chance) {
|
||||
this.discardChanceOnAirExposure = chance;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OreConfiguration createConfiguration() {
|
||||
return new OreConfiguration(targetStates, size, discardChanceOnAirExposure);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AsPillar extends BCLFeatureBuilder<PillarFeature, PillarFeatureConfig> {
|
||||
private final List<Holder<PlacedFeature>> features = new LinkedList<>();
|
||||
|
||||
private IntProvider height;
|
||||
private BlockStateProvider stateProvider;
|
||||
|
||||
private final PillarFeatureConfig.KnownTransformers transformer;
|
||||
private Direction direction = Direction.UP;
|
||||
private BlockPredicate allowedPlacement = BlockPredicate.ONLY_IN_AIR_PREDICATE;
|
||||
|
||||
private AsPillar(
|
||||
ResourceLocation featureID,
|
||||
PillarFeature feature,
|
||||
PillarFeatureConfig.KnownTransformers transformer
|
||||
) {
|
||||
super(featureID, feature);
|
||||
this.transformer = transformer;
|
||||
}
|
||||
|
||||
public AsPillar allowedPlacement(BlockPredicate predicate) {
|
||||
this.allowedPlacement = predicate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsPillar direction(Direction v) {
|
||||
this.direction = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsPillar blockState(Block v) {
|
||||
return blockState(BlockStateProvider.simple(v.defaultBlockState()));
|
||||
}
|
||||
|
||||
public AsPillar blockState(BlockState v) {
|
||||
return blockState(BlockStateProvider.simple(v));
|
||||
}
|
||||
|
||||
public AsPillar blockState(BlockStateProvider v) {
|
||||
this.stateProvider = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsPillar height(int v) {
|
||||
this.height = ConstantInt.of(v);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsPillar height(IntProvider v) {
|
||||
this.height = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PillarFeatureConfig createConfiguration() {
|
||||
if (stateProvider == null) {
|
||||
throw new IllegalStateException("A Pillar Features need a stateProvider");
|
||||
}
|
||||
if (height == null) {
|
||||
throw new IllegalStateException("A Pillar Features need a height");
|
||||
}
|
||||
return new PillarFeatureConfig(height, direction, allowedPlacement, stateProvider, transformer);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AsSequence<FF extends Feature<SequenceFeatureConfig>> extends BCLFeatureBuilder<FF, SequenceFeatureConfig> {
|
||||
private final List<Holder<PlacedFeature>> features = new LinkedList<>();
|
||||
|
||||
private AsSequence(ResourceLocation featureID, FF feature) {
|
||||
super(featureID, feature);
|
||||
}
|
||||
|
||||
|
||||
public AsSequence add(org.betterx.bclib.api.v3.levelgen.features.BCLFeature p) {
|
||||
return add(p.placedFeature);
|
||||
}
|
||||
|
||||
public AsSequence add(Holder<PlacedFeature> p) {
|
||||
features.add(p);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SequenceFeatureConfig createConfiguration() {
|
||||
return new SequenceFeatureConfig(features);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AsBlockColumn<FF extends Feature<BlockColumnConfiguration>> extends BCLFeatureBuilder<FF, BlockColumnConfiguration> {
|
||||
private final List<BlockColumnConfiguration.Layer> layers = new LinkedList<>();
|
||||
private Direction direction = Direction.UP;
|
||||
private BlockPredicate allowedPlacement = BlockPredicate.ONLY_IN_AIR_PREDICATE;
|
||||
private boolean prioritizeTip = false;
|
||||
|
||||
private AsBlockColumn(ResourceLocation featureID, FF feature) {
|
||||
super(featureID, feature);
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> add(int height, Block block) {
|
||||
return add(ConstantInt.of(height), BlockStateProvider.simple(block));
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> add(int height, BlockState state) {
|
||||
return add(ConstantInt.of(height), BlockStateProvider.simple(state));
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> add(int height, BlockStateProvider state) {
|
||||
return add(ConstantInt.of(height), state);
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> add(IntProvider height, Block block) {
|
||||
return add(height, BlockStateProvider.simple(block));
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> add(IntProvider height, BlockState state) {
|
||||
return add(height, BlockStateProvider.simple(state));
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> add(IntProvider height, BlockStateProvider state) {
|
||||
layers.add(new BlockColumnConfiguration.Layer(height, state));
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> addTripleShape(BlockState state, IntProvider midHeight) {
|
||||
return this
|
||||
.add(1, state.setValue(BCLBlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.BOTTOM))
|
||||
.add(midHeight, state.setValue(BCLBlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.MIDDLE))
|
||||
.add(1, state.setValue(BCLBlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.TOP));
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> addTripleShapeUpsideDown(BlockState state, IntProvider midHeight) {
|
||||
return this
|
||||
.add(1, state.setValue(BCLBlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.TOP))
|
||||
.add(midHeight, state.setValue(BCLBlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.MIDDLE))
|
||||
.add(1, state.setValue(BCLBlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.BOTTOM));
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> direction(Direction dir) {
|
||||
direction = dir;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> prioritizeTip() {
|
||||
return this.prioritizeTip(true);
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> prioritizeTip(boolean v) {
|
||||
prioritizeTip = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsBlockColumn<FF> allowedPlacement(BlockPredicate v) {
|
||||
allowedPlacement = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockColumnConfiguration createConfiguration() {
|
||||
return new BlockColumnConfiguration(layers, direction, allowedPlacement, prioritizeTip);
|
||||
}
|
||||
}
|
||||
|
||||
public static class WithTemplates<FF extends Feature<TemplateFeatureConfig>> extends BCLFeatureBuilder<FF, TemplateFeatureConfig> {
|
||||
private final List<StructureWorldNBT> templates = new LinkedList<>();
|
||||
|
||||
private WithTemplates(ResourceLocation featureID, FF feature) {
|
||||
super(featureID, feature);
|
||||
}
|
||||
|
||||
public WithTemplates<FF> add(
|
||||
ResourceLocation location,
|
||||
int offsetY,
|
||||
StructurePlacementType type,
|
||||
float chance
|
||||
) {
|
||||
templates.add(TemplateFeatureConfig.cfg(location, offsetY, type, chance));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateFeatureConfig createConfiguration() {
|
||||
return new TemplateFeatureConfig(templates);
|
||||
}
|
||||
}
|
||||
|
||||
public static class NetherForrestVegetation<FF extends Feature<NetherForestVegetationConfig>> extends BCLFeatureBuilder<FF, NetherForestVegetationConfig> {
|
||||
private SimpleWeightedRandomList.Builder<BlockState> blocks;
|
||||
private WeightedStateProvider stateProvider;
|
||||
|
@ -64,7 +483,7 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
|
|||
throw new IllegalStateException("You can not add new state once a WeightedStateProvider was built. (" + state + ", " + weight + ")");
|
||||
}
|
||||
if (blocks == null) {
|
||||
blocks = SimpleWeightedRandomList.<BlockState>builder();
|
||||
blocks = SimpleWeightedRandomList.builder();
|
||||
}
|
||||
blocks.add(state, weight);
|
||||
return this;
|
||||
|
@ -90,10 +509,10 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
|
|||
}
|
||||
|
||||
public static class RandomPatch<FF extends Feature<RandomPatchConfiguration>> extends BCLFeatureBuilder<FF, RandomPatchConfiguration> {
|
||||
private final Holder<PlacedFeature> featureToPlace;
|
||||
private int tries = 96;
|
||||
private int xzSpread = 7;
|
||||
private int ySpread = 3;
|
||||
private final Holder<PlacedFeature> featureToPlace;
|
||||
|
||||
private RandomPatch(
|
||||
@NotNull ResourceLocation featureID,
|
||||
|
@ -104,6 +523,17 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
|
|||
this.featureToPlace = featureToPlace;
|
||||
}
|
||||
|
||||
public RandomPatch likeDefaultNetherVegetation() {
|
||||
return likeDefaultNetherVegetation(8, 4);
|
||||
}
|
||||
|
||||
public RandomPatch likeDefaultNetherVegetation(int xzSpread, int ySpread) {
|
||||
this.xzSpread = xzSpread;
|
||||
this.ySpread = ySpread;
|
||||
tries = xzSpread * xzSpread;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RandomPatch tries(int v) {
|
||||
tries = v;
|
||||
return this;
|
||||
|
@ -163,127 +593,6 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
|
|||
return new SimpleBlockConfiguration(provider);
|
||||
}
|
||||
}
|
||||
|
||||
private final ResourceLocation featureID;
|
||||
private final F feature;
|
||||
|
||||
private BCLFeatureBuilder(ResourceLocation featureID, F feature) {
|
||||
this.featureID = featureID;
|
||||
this.feature = feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new {@link BCLFeature} builder.
|
||||
*
|
||||
* @param featureID {@link ResourceLocation} feature identifier.
|
||||
* @param feature {@link Feature} to construct.
|
||||
* @return {@link org.betterx.bclib.api.v2.levelgen.features.BCLFeatureBuilder} instance.
|
||||
*/
|
||||
public static <F extends Feature<FC>, FC extends FeatureConfiguration> WithConfiguration<F, FC> start(
|
||||
ResourceLocation featureID,
|
||||
F feature
|
||||
) {
|
||||
return new WithConfiguration(featureID, feature);
|
||||
}
|
||||
|
||||
public static ForSimpleBlock start(
|
||||
ResourceLocation featureID,
|
||||
Block block
|
||||
) {
|
||||
return start(featureID, BlockStateProvider.simple(block));
|
||||
}
|
||||
|
||||
public static ForSimpleBlock start(
|
||||
ResourceLocation featureID,
|
||||
BlockState state
|
||||
) {
|
||||
return start(featureID, BlockStateProvider.simple(state));
|
||||
}
|
||||
|
||||
public static ForSimpleBlock start(
|
||||
ResourceLocation featureID,
|
||||
BlockStateProvider provider
|
||||
) {
|
||||
ForSimpleBlock builder = new ForSimpleBlock(
|
||||
featureID,
|
||||
Feature.SIMPLE_BLOCK,
|
||||
provider
|
||||
);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static RandomPatch startRandomPatch(
|
||||
ResourceLocation featureID,
|
||||
Holder<PlacedFeature> featureToPlace
|
||||
) {
|
||||
RandomPatch builder = new RandomPatch(
|
||||
featureID,
|
||||
Feature.RANDOM_PATCH,
|
||||
featureToPlace
|
||||
);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static NetherForrestVegetation startNetherVegetation(
|
||||
ResourceLocation featureID
|
||||
) {
|
||||
NetherForrestVegetation builder = new NetherForrestVegetation(
|
||||
featureID,
|
||||
Feature.NETHER_FOREST_VEGETATION
|
||||
);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public abstract FC createConfiguration();
|
||||
|
||||
protected BCLConfigureFeature<F, FC> buildAndRegister(BiFunction<ResourceLocation, ConfiguredFeature<FC, F>, Holder<ConfiguredFeature<FC, F>>> holderBuilder) {
|
||||
FC config = createConfiguration();
|
||||
if (config == null) {
|
||||
throw new IllegalStateException("Feature configuration for " + featureID + " can not be null!");
|
||||
}
|
||||
ConfiguredFeature<FC, F> cFeature = new ConfiguredFeature<FC, F>(feature, config);
|
||||
Holder<ConfiguredFeature<FC, F>> holder = holderBuilder.apply(featureID, cFeature);
|
||||
return new BCLConfigureFeature<>(featureID, holder, true);
|
||||
}
|
||||
|
||||
public BCLConfigureFeature<F, FC> buildAndRegister() {
|
||||
return buildAndRegister(BCLFeatureBuilder::register);
|
||||
}
|
||||
|
||||
public BCLConfigureFeature<F, FC> build() {
|
||||
return buildAndRegister((id, cFeature) -> Holder.direct(cFeature));
|
||||
}
|
||||
|
||||
public BCLInlinePlacedBuilder<F, FC> inlinePlace() {
|
||||
BCLConfigureFeature<F, FC> f = build();
|
||||
return BCLInlinePlacedBuilder.place(f);
|
||||
}
|
||||
|
||||
public Holder<PlacedFeature> inlinePlace(BCLInlinePlacedBuilder<F, FC> placer) {
|
||||
BCLConfigureFeature<F, FC> f = build();
|
||||
return placer.build(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internally used by the builder. Normally you should not have to call this method directly as it is
|
||||
* handled by {@link #buildAndRegister()}
|
||||
*
|
||||
* @param id The ID to register this feature with
|
||||
* @param cFeature The configured Feature
|
||||
* @param <F> The Feature Class
|
||||
* @param <FC> The FeatureConfiguration Class
|
||||
* @return The Holder for the new Feature
|
||||
*/
|
||||
public static <F extends Feature<FC>, FC extends FeatureConfiguration> Holder<ConfiguredFeature<FC, F>> register(
|
||||
ResourceLocation id,
|
||||
ConfiguredFeature<FC, F> cFeature
|
||||
) {
|
||||
return (Holder<ConfiguredFeature<FC, F>>) (Object) BuiltinRegistries.register(
|
||||
BuiltinRegistries.CONFIGURED_FEATURE,
|
||||
id,
|
||||
cFeature
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -80,4 +80,5 @@ public class BCLInlinePlacedBuilder<F extends Feature<FC>, FC extends FeatureCon
|
|||
return PlacementUtils.inlinePlaced(feature, configuration, modifiers);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ public class BCLPlacedFeatureBuilder<F extends Feature<FC>, FC extends FeatureCo
|
|||
*
|
||||
* @return created {@link BCLFeature} instance.
|
||||
*/
|
||||
protected Holder<PlacedFeature> build() {
|
||||
public Holder<PlacedFeature> build() {
|
||||
Holder<PlacedFeature> p = PlacementUtils.register(
|
||||
featureID.toString(),
|
||||
cFeature.configuredFeature,
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package org.betterx.bclib.api.v3.levelgen.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.tag.CommonBlockTags;
|
||||
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
|
||||
public class BlockPredicates {
|
||||
public static final BlockPredicate ONLY_NYLIUM = BlockPredicate.matchesTag(BlockTags.NYLIUM);
|
||||
public static final BlockPredicate ONLY_NETHER_GROUND = BlockPredicate.matchesTag(CommonBlockTags.NETHER_TERRAIN);
|
||||
public static final BlockPredicate ONLY_GROUND = BlockPredicate.matchesTag(CommonBlockTags.TERRAIN);
|
||||
|
||||
public static final BlockPredicate ONLY_LAVA = BlockPredicate.matchesFluids(Fluids.LAVA);
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package org.betterx.bclib.api.v3.levelgen.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.PlaceFacingBlockConfig;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.SequenceFeature;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.placement.*;
|
||||
import org.betterx.bclib.api.v2.tag.CommonBlockTags;
|
||||
|
||||
|
@ -11,9 +12,14 @@ import net.minecraft.data.worldgen.placement.PlacementUtils;
|
|||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.valueproviders.IntProvider;
|
||||
import net.minecraft.util.valueproviders.UniformInt;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.RandomPatchFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.SimpleBlockFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
import net.minecraft.world.level.levelgen.placement.*;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
|
||||
|
@ -334,14 +340,82 @@ abstract class CommonPlacedFeatureBuilder<F extends Feature<FC>, FC extends Feat
|
|||
return modifier(PlacementUtils.HEIGHTMAP_WORLD_SURFACE);
|
||||
}
|
||||
|
||||
public T onlyWhenEmpty() {
|
||||
public T extendXZ(int xzSpread) {
|
||||
IntProvider xz = UniformInt.of(0, xzSpread);
|
||||
return (T) modifier(
|
||||
new ForAll(List.of(
|
||||
new Extend(Direction.NORTH, xz),
|
||||
new Extend(Direction.SOUTH, xz),
|
||||
new Extend(Direction.EAST, xz),
|
||||
new Extend(Direction.WEST, xz)
|
||||
)),
|
||||
new ForAll(List.of(
|
||||
new Extend(Direction.EAST, xz),
|
||||
new Extend(Direction.WEST, xz),
|
||||
new Extend(Direction.NORTH, xz),
|
||||
new Extend(Direction.SOUTH, xz)
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
public T extendXYZ(int xzSpread, int ySpread) {
|
||||
IntProvider xz = UniformInt.of(0, xzSpread);
|
||||
return (T) extendXZ(xzSpread).extendDown(1, ySpread);
|
||||
}
|
||||
|
||||
public T isEmpty() {
|
||||
return modifier(BlockPredicateFilter.forPredicate(BlockPredicate.ONLY_IN_AIR_PREDICATE));
|
||||
}
|
||||
|
||||
public T filtered(BlockPredicate predicate) {
|
||||
|
||||
public T is(BlockPredicate predicate) {
|
||||
return modifier(BlockPredicateFilter.forPredicate(predicate));
|
||||
}
|
||||
|
||||
public T isNextTo(BlockPredicate predicate) {
|
||||
return modifier(new IsNextTo(predicate));
|
||||
}
|
||||
|
||||
public T belowIsNextTo(BlockPredicate predicate) {
|
||||
return modifier(new IsNextTo(predicate, Direction.DOWN.getNormal()));
|
||||
}
|
||||
|
||||
public T isNextTo(BlockPredicate predicate, Vec3i offset) {
|
||||
return modifier(new IsNextTo(predicate, offset));
|
||||
}
|
||||
|
||||
public T isOn(BlockPredicate predicate) {
|
||||
return modifier(Is.below(predicate));
|
||||
}
|
||||
|
||||
public T isEmptyAndOn(BlockPredicate predicate) {
|
||||
return (T) this.isEmpty().isOn(predicate);
|
||||
}
|
||||
|
||||
public T isEmptyAndOnNylium() {
|
||||
return isEmptyAndOn(BlockPredicates.ONLY_NYLIUM);
|
||||
}
|
||||
|
||||
public T isEmptyAndOnNetherGround() {
|
||||
return isEmptyAndOn(BlockPredicates.ONLY_NETHER_GROUND);
|
||||
}
|
||||
|
||||
public T isUnder(BlockPredicate predicate) {
|
||||
return modifier(Is.above(predicate));
|
||||
}
|
||||
|
||||
public T isEmptyAndUnder(BlockPredicate predicate) {
|
||||
return (T) this.isEmpty().isUnder(predicate);
|
||||
}
|
||||
|
||||
public T isEmptyAndUnderNylium() {
|
||||
return isEmptyAndUnder(BlockPredicates.ONLY_NYLIUM);
|
||||
}
|
||||
|
||||
public T isEmptyAndUnderNetherGround() {
|
||||
return isEmptyAndUnder(BlockPredicates.ONLY_NETHER_GROUND);
|
||||
}
|
||||
|
||||
public T vanillaNetherGround(int countPerLayer) {
|
||||
return (T) this.onEveryLayer(countPerLayer).onlyInBiome();
|
||||
}
|
||||
|
@ -369,7 +443,26 @@ abstract class CommonPlacedFeatureBuilder<F extends Feature<FC>, FC extends Feat
|
|||
*/
|
||||
abstract Holder<PlacedFeature> build();
|
||||
|
||||
public BCLFeatureBuilder.RandomPatch inRandomPatch(ResourceLocation id) {
|
||||
public BCLFeatureBuilder.RandomPatch<RandomPatchFeature> inRandomPatch(ResourceLocation id) {
|
||||
return BCLFeatureBuilder.startRandomPatch(id, build());
|
||||
}
|
||||
|
||||
public BCLFeatureBuilder.AsSequence<SequenceFeature> then(ResourceLocation id) {
|
||||
return BCLFeatureBuilder.startSequence(id).add(build());
|
||||
}
|
||||
|
||||
public BCLFeatureBuilder.ForSimpleBlock<SimpleBlockFeature> putBlock(ResourceLocation id, Block block) {
|
||||
return BCLFeatureBuilder.start(id, block);
|
||||
}
|
||||
|
||||
public BCLFeatureBuilder.ForSimpleBlock<SimpleBlockFeature> putBlock(ResourceLocation id, BlockState state) {
|
||||
return BCLFeatureBuilder.start(id, state);
|
||||
}
|
||||
|
||||
public BCLFeatureBuilder.ForSimpleBlock<SimpleBlockFeature> putBlock(
|
||||
ResourceLocation id,
|
||||
BlockStateProvider provider
|
||||
) {
|
||||
return BCLFeatureBuilder.start(id, provider);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package org.betterx.bclib.blocks;
|
||||
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||||
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
||||
|
||||
public class BCLBlockProperties {
|
||||
public static final EnumProperty<BlockProperties.TripleShape> TRIPLE_SHAPE = BlockProperties.TRIPLE_SHAPE;
|
||||
public static final IntegerProperty SIZE = IntegerProperty.create("size", 0, 7);
|
||||
public static final IntegerProperty AGE_THREE = BlockStateProperties.AGE_2;
|
||||
public static final IntegerProperty AGE_FOUR = BlockStateProperties.AGE_3;
|
||||
}
|
Loading…
Reference in a new issue