Marked Deprecated API

This commit is contained in:
Frank 2022-06-29 00:54:56 +02:00
parent 5d85595c5a
commit 4367babec5
67 changed files with 2217 additions and 1721 deletions

View file

@ -9,10 +9,10 @@ import org.betterx.bclib.api.v2.levelgen.LevelGenEvents;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome; import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeBuilder; import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeBuilder;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI; import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.api.v2.levelgen.features.blockpredicates.Types;
import org.betterx.bclib.api.v2.levelgen.features.placement.PlacementModifiers;
import org.betterx.bclib.api.v2.levelgen.structures.TemplatePiece; import org.betterx.bclib.api.v2.levelgen.structures.TemplatePiece;
import org.betterx.bclib.api.v2.levelgen.surface.rules.Conditions; import org.betterx.bclib.api.v2.levelgen.surface.rules.Conditions;
import org.betterx.bclib.api.v3.levelgen.features.blockpredicates.BlockPredicates;
import org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers;
import org.betterx.bclib.commands.CommandRegistry; import org.betterx.bclib.commands.CommandRegistry;
import org.betterx.bclib.config.Configs; import org.betterx.bclib.config.Configs;
import org.betterx.bclib.recipes.AnvilRecipe; import org.betterx.bclib.recipes.AnvilRecipe;
@ -42,7 +42,7 @@ public class BCLib implements ModInitializer {
public void onInitialize() { public void onInitialize() {
LevelGenEvents.register(); LevelGenEvents.register();
WorldsTogether.onInitialize(); WorldsTogether.onInitialize();
Types.ensureStaticInitialization(); BlockPredicates.ensureStaticInitialization();
BaseRegistry.register(); BaseRegistry.register();
GeneratorOptions.init(); GeneratorOptions.init();
BaseBlockEntities.register(); BaseBlockEntities.register();

View file

@ -17,6 +17,7 @@ import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.resources.RegistryOps; import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BiomeTags;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Climate; import net.minecraft.world.level.biome.Climate;
@ -135,11 +136,9 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourc
private static boolean isValidNetherBiome(Holder<Biome> biome, ResourceLocation location) { private static boolean isValidNetherBiome(Holder<Biome> biome, ResourceLocation location) {
return biome.unwrapKey().get().location().toString().contains("upside_down"); return NetherBiomes.canGenerateInNether(biome.unwrapKey().get()) ||
biome.is(BiomeTags.IS_NETHER) ||
// return NetherBiomes.canGenerateInNether(biome.unwrapKey().get()) || BiomeAPI.wasRegisteredAsNetherBiome(location);
// biome.is(BiomeTags.IS_NETHER) ||
// BiomeAPI.wasRegisteredAsNetherBiome(location);
} }
private static boolean isValidNonVanillaNetherBiome(Holder<Biome> biome, ResourceLocation location) { private static boolean isValidNonVanillaNetherBiome(Holder<Biome> biome, ResourceLocation location) {

View file

@ -1,8 +1,16 @@
package org.betterx.bclib.api.v2.levelgen.features; package org.betterx.bclib.api.v2.levelgen.features;
import org.betterx.bclib.api.v2.levelgen.features.config.*; import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.levelgen.features.config.ScatterFeatureConfig;
import org.betterx.bclib.api.v2.levelgen.features.features.ScatterFeature;
import org.betterx.bclib.api.v2.levelgen.features.features.WeightedRandomSelectorFeature;
import org.betterx.bclib.api.v3.levelgen.features.BCLConfigureFeature; import org.betterx.bclib.api.v3.levelgen.features.BCLConfigureFeature;
import org.betterx.bclib.api.v3.levelgen.features.BCLFeatureBuilder; import org.betterx.bclib.api.v3.levelgen.features.BCLFeatureBuilder;
import org.betterx.bclib.api.v3.levelgen.features.UserGrowableFeature;
import org.betterx.bclib.api.v3.levelgen.features.config.ConditionFeatureConfig;
import org.betterx.bclib.api.v3.levelgen.features.config.PlaceFacingBlockConfig;
import org.betterx.bclib.api.v3.levelgen.features.config.SequenceFeatureConfig;
import org.betterx.bclib.api.v3.levelgen.features.config.TemplateFeatureConfig;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
@ -40,26 +48,31 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
*/ */
@Deprecated(forRemoval = true) @Deprecated(forRemoval = true)
public static final Feature<PlaceFacingBlockConfig> PLACE_BLOCK = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.PLACE_BLOCK; public static final Feature<PlaceFacingBlockConfig> PLACE_BLOCK = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.PLACE_BLOCK;
/**
* @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#SCATTER_ON_SOLID}
*/
@Deprecated(forRemoval = true) @Deprecated(forRemoval = true)
public static final Feature<ScatterFeatureConfig.OnSolid> SCATTER_ON_SOLID = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_ON_SOLID; public static final Feature<ScatterFeatureConfig.OnSolid> SCATTER_ON_SOLID = register(
/** BCLib.makeID("scatter_on_solid"),
* @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#SCATTER_EXTEND_TOP} new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC)
*/ );
@Deprecated(forRemoval = true) @Deprecated(forRemoval = true)
public static final Feature<ScatterFeatureConfig.ExtendTop> SCATTER_EXTEND_TOP = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_EXTEND_TOP; public static final Feature<ScatterFeatureConfig.ExtendTop> SCATTER_EXTEND_TOP = register(
/** BCLib.makeID("scatter_extend_top"),
* @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#SCATTER_EXTEND_BOTTOM} new ScatterFeature<>(ScatterFeatureConfig.ExtendTop.CODEC)
*/ );
@Deprecated(forRemoval = true) @Deprecated(forRemoval = true)
public static final Feature<ScatterFeatureConfig.ExtendBottom> SCATTER_EXTEND_BOTTOM = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_EXTEND_BOTTOM; public static final Feature<ScatterFeatureConfig.ExtendBottom> SCATTER_EXTEND_BOTTOM = register(
/** BCLib.makeID("scatter_extend_bottom"),
* @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#RANDOM_SELECTOR} new ScatterFeature<>(ScatterFeatureConfig.ExtendBottom.CODEC)
*/ );
@Deprecated(forRemoval = true) @Deprecated(forRemoval = true)
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.RANDOM_SELECTOR; public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = register(
BCLib.makeID("random_select"),
new WeightedRandomSelectorFeature()
);
/** /**
* @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#TEMPLATE} * @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#TEMPLATE}
*/ */

View file

@ -1,6 +1,9 @@
package org.betterx.bclib.api.v2.levelgen.features; package org.betterx.bclib.api.v2.levelgen.features;
import org.betterx.bclib.api.v2.levelgen.features.placement.*; import org.betterx.bclib.api.v2.levelgen.features.placement.IsEmptyAboveSampledFilter;
import org.betterx.bclib.api.v2.levelgen.features.placement.MinEmptyFilter;
import org.betterx.bclib.api.v2.levelgen.features.placement.Stencil;
import org.betterx.bclib.api.v3.levelgen.features.placement.*;
import org.betterx.worlds.together.tag.v3.CommonBlockTags; import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;

View file

@ -1,257 +1,255 @@
package org.betterx.bclib.api.v2.levelgen.features; package org.betterx.bclib.api.v2.levelgen.features;
import org.betterx.bclib.api.v2.levelgen.features.config.PlaceFacingBlockConfig; @Deprecated(forRemoval = true)
import org.betterx.bclib.api.v2.levelgen.features.config.ScatterFeatureConfig;
import org.betterx.bclib.api.v2.levelgen.features.features.ScatterFeature;
import net.minecraft.data.worldgen.features.FeatureUtils;
import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.resources.ResourceLocation;
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.block.state.properties.IntegerProperty;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.RandomPatchConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.SimpleBlockConfiguration;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import net.minecraft.world.level.levelgen.feature.stateproviders.RandomizedIntStateProvider;
public class FastFeatures { public class FastFeatures {
public static RandomPatchConfiguration grassPatch(BlockStateProvider stateProvider, int tries) { // @Deprecated(forRemoval = true)
return FeatureUtils.simpleRandomPatchConfiguration( // public static RandomPatchConfiguration grassPatch(BlockStateProvider stateProvider, int tries) {
tries, // return FeatureUtils.simpleRandomPatchConfiguration(
PlacementUtils.onlyWhenEmpty(Feature.SIMPLE_BLOCK, new SimpleBlockConfiguration(stateProvider)) // tries,
); // PlacementUtils.onlyWhenEmpty(Feature.SIMPLE_BLOCK, new SimpleBlockConfiguration(stateProvider))
} // );
// }
//
public static BCLFeature<ScatterFeature<ScatterFeatureConfig.OnSolid>, ScatterFeatureConfig.OnSolid> vine( // @Deprecated(forRemoval = true)
ResourceLocation location, // public static BCLFeature<ScatterFeature<ScatterFeatureConfig.OnSolid>, ScatterFeatureConfig.OnSolid> vine(
boolean onFloor, // ResourceLocation location,
boolean sparse, // boolean onFloor,
ScatterFeatureConfig.Builder builder // boolean sparse,
) { // ScatterFeatureConfig.Builder builder
return scatter(location, onFloor, sparse, builder, // ) {
org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_ON_SOLID // return scatter(location, onFloor, sparse, builder,
); // org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_ON_SOLID
} // );
// }
public static BCLFeature scatter( //
ResourceLocation location, // @Deprecated(forRemoval = true)
boolean onFloor, // public static BCLFeature scatter(
boolean sparse, // ResourceLocation location,
ScatterFeatureConfig.Builder builder, // boolean onFloor,
Feature scatterFeature // boolean sparse,
) { // ScatterFeatureConfig.Builder builder,
BCLFeatureBuilder fBuilder = BCLFeatureBuilder.start(location, scatterFeature); // Feature scatterFeature
if (onFloor) { // ) {
fBuilder.findSolidFloor(3).isEmptyAbove2(); // BCLFeatureBuilder fBuilder = BCLFeatureBuilder.start(location, scatterFeature);
builder.onFloor(); // if (onFloor) {
} else { // fBuilder.findSolidFloor(3).isEmptyAbove2();
fBuilder.findSolidCeil(3).isEmptyBelow2(); // builder.onFloor();
builder.onCeil(); // } else {
} // fBuilder.findSolidCeil(3).isEmptyBelow2();
if (sparse) { // builder.onCeil();
fBuilder.onceEvery(3); // }
} // if (sparse) {
// fBuilder.onceEvery(3);
return fBuilder // }
.is(BlockPredicate.ONLY_IN_AIR_PREDICATE) //
.buildAndRegister(builder.build()); // return fBuilder
} // .is(BlockPredicate.ONLY_IN_AIR_PREDICATE)
// .buildAndRegister(builder.build());
public static BCLFeature patch(ResourceLocation location, Block block) { // }
return patch(location, block, 96, 7, 3); //
} // @Deprecated(forRemoval = true)
// public static BCLFeature patch(ResourceLocation location, Block block) {
public static BCLFeature // return patch(location, block, 96, 7, 3);
patch(ResourceLocation location, Block block, int attempts, int xzSpread, int ySpread) { // }
return patch( //
location, // @Deprecated(forRemoval = true)
attempts, // public static BCLFeature
xzSpread, // patch(ResourceLocation location, Block block, int attempts, int xzSpread, int ySpread) {
ySpread, // return patch(
Feature.SIMPLE_BLOCK, // location,
new SimpleBlockConfiguration(BlockStateProvider.simple(block)) // attempts,
); // xzSpread,
} // ySpread,
// Feature.SIMPLE_BLOCK,
public static BCLFeature // new SimpleBlockConfiguration(BlockStateProvider.simple(block))
patch(ResourceLocation location, BlockStateProvider provider, int attempts, int xzSpread, int ySpread) { // );
return patch( // }
location, //
attempts, // @Deprecated(forRemoval = true)
xzSpread, // public static BCLFeature
ySpread, // patch(ResourceLocation location, BlockStateProvider provider, int attempts, int xzSpread, int ySpread) {
Feature.SIMPLE_BLOCK, // return patch(
new SimpleBlockConfiguration(provider) // location,
); // attempts,
} // xzSpread,
// ySpread,
public static BCLFeature patchWitRandomInt(ResourceLocation location, Block block, IntegerProperty prop) { // Feature.SIMPLE_BLOCK,
return patchWitRandomInt(location, block, prop, 96, 7, 3); // new SimpleBlockConfiguration(provider)
} // );
// }
public static BCLFeature //
patchWitRandomInt( // @Deprecated(forRemoval = true)
ResourceLocation location, // public static BCLFeature patchWitRandomInt(ResourceLocation location, Block block, IntegerProperty prop) {
Block block, // return patchWitRandomInt(location, block, prop, 96, 7, 3);
IntegerProperty prop, // }
int attempts, //
int xzSpread, // @Deprecated(forRemoval = true)
int ySpread // public static BCLFeature
) { // patchWitRandomInt(
return patch( // ResourceLocation location,
location, // Block block,
attempts, // IntegerProperty prop,
xzSpread, // int attempts,
ySpread, // int xzSpread,
simple(location, ySpread, false, block.defaultBlockState(), prop) // int ySpread
); // ) {
} // return patch(
// location,
public static BCLFeature // attempts,
simple( // xzSpread,
ResourceLocation location, // ySpread,
int searchDist, // simple(location, ySpread, false, block.defaultBlockState(), prop)
boolean rare, // );
Feature<NoneFeatureConfiguration> feature // }
) { //
return simple(location, searchDist, rare, feature, NoneFeatureConfiguration.NONE); // @Deprecated(forRemoval = true)
} // public static BCLFeature
// simple(
public static BCLFeature // ResourceLocation location,
single(ResourceLocation location, Block block) { // int searchDist,
return single(location, BlockStateProvider.simple(block)); // boolean rare,
// Feature<NoneFeatureConfiguration> feature
} // ) {
// return simple(location, searchDist, rare, feature, NoneFeatureConfiguration.NONE);
public static BCLFeature // }
single(ResourceLocation location, BlockStateProvider provider) { //
return BCLFeatureBuilder // @Deprecated(forRemoval = true)
.start(location, provider) // public static BCLFeature
.buildAndRegister(); // single(ResourceLocation location, Block block) {
} // return single(location, BlockStateProvider.simple(block));
//
public static BCLFeature // }
simple(ResourceLocation location, Feature<NoneFeatureConfiguration> feature) { //
return BCLFeatureBuilder // @Deprecated(forRemoval = true)
.start(location, feature) // public static BCLFeature
.buildAndRegister(); // single(ResourceLocation location, BlockStateProvider provider) {
} // return BCLFeatureBuilder
// .start(location, provider)
public static BCLFeature // .buildAndRegister();
simple( // }
ResourceLocation location, //
int searchDist, // @Deprecated(forRemoval = true)
boolean rare, // public static BCLFeature
BlockState baseState, // simple(ResourceLocation location, Feature<NoneFeatureConfiguration> feature) {
IntegerProperty property // return BCLFeatureBuilder
) { // .start(location, feature)
int min = Integer.MAX_VALUE; // .buildAndRegister();
int max = Integer.MIN_VALUE; // }
//
for (Integer i : property.getPossibleValues()) { // @Deprecated(forRemoval = true)
if (i < min) min = i; // public static BCLFeature
if (i > max) max = i; // simple(
} // ResourceLocation location,
// int searchDist,
return simple( // boolean rare,
location, // BlockState baseState,
searchDist, // IntegerProperty property
rare, // ) {
Feature.SIMPLE_BLOCK, // int min = Integer.MAX_VALUE;
new SimpleBlockConfiguration(new RandomizedIntStateProvider( // int max = Integer.MIN_VALUE;
BlockStateProvider.simple(baseState), //
property, // for (Integer i : property.getPossibleValues()) {
UniformInt.of(min, max) // if (i < min) min = i;
)) // if (i > max) max = i;
); // }
} //
// return simple(
// location,
public static <FC extends FeatureConfiguration> BCLFeature<Feature<FC>, FC> // searchDist,
simple( // rare,
ResourceLocation location, // Feature.SIMPLE_BLOCK,
int searchDist, // new SimpleBlockConfiguration(new RandomizedIntStateProvider(
boolean rare, // BlockStateProvider.simple(baseState),
Feature<FC> feature, // property,
FC config // UniformInt.of(min, max)
) { // ))
BCLFeatureBuilder builder = BCLFeatureBuilder // );
.start(location, feature) // }
.findSolidFloor(Math.min(12, searchDist)) //
.is(BlockPredicate.ONLY_IN_AIR_PREDICATE); // @Deprecated(forRemoval = true)
if (rare) { //
builder.onceEvery(4); // public static <FC extends FeatureConfiguration> BCLFeature<Feature<FC>, FC>
} // simple(
return builder.buildAndRegister(config); // ResourceLocation location,
} // int searchDist,
// boolean rare,
public static BCLFeature // Feature<FC> feature,
patch(ResourceLocation location, Feature<NoneFeatureConfiguration> feature) { // FC config
return patch(location, 96, 7, 3, feature, FeatureConfiguration.NONE); // ) {
} // BCLFeatureBuilder builder = BCLFeatureBuilder
// .start(location, feature)
// .findSolidFloor(Math.min(12, searchDist))
public static BCLFeature // .is(BlockPredicate.ONLY_IN_AIR_PREDICATE);
patch( // if (rare) {
ResourceLocation location, // builder.onceEvery(4);
int attempts, // }
int xzSpread, // return builder.buildAndRegister(config);
int ySpread, // }
Feature<NoneFeatureConfiguration> feature //
) { // @Deprecated(forRemoval = true)
return patch(location, attempts, xzSpread, ySpread, feature, FeatureConfiguration.NONE); // public static BCLFeature
} // patch(ResourceLocation location, Feature<NoneFeatureConfiguration> feature) {
// return patch(location, 96, 7, 3, feature, FeatureConfiguration.NONE);
// }
public static <FC extends FeatureConfiguration> BCLFeature //
patch( //
ResourceLocation location, // @Deprecated(forRemoval = true)
int attempts, // public static BCLFeature
int xzSpread, // patch(
int ySpread, // ResourceLocation location,
Feature<FC> feature, // int attempts,
FC config // int xzSpread,
) { // int ySpread,
final BCLFeature SINGLE = simple(location, ySpread, false, feature, config); // Feature<NoneFeatureConfiguration> feature
return patch(location, attempts, xzSpread, ySpread, SINGLE); // ) {
} // return patch(location, attempts, xzSpread, ySpread, feature, FeatureConfiguration.NONE);
// }
public static BCLFeature //
wallPatch( // @Deprecated(forRemoval = true)
ResourceLocation location, // public static <FC extends FeatureConfiguration> BCLFeature
Block block, // patch(
int attempts, // ResourceLocation location,
int xzSpread, // int attempts,
int ySpread // int xzSpread,
) { // int ySpread,
final BCLFeature SINGLE = simple(location, ySpread, false, // Feature<FC> feature,
org.betterx.bclib.api.v3.levelgen.features.BCLFeature.PLACE_BLOCK, // FC config
new PlaceFacingBlockConfig(block, PlaceFacingBlockConfig.HORIZONTAL) // ) {
); // final BCLFeature SINGLE = simple(location, ySpread, false, feature, config);
return patch(location, attempts, xzSpread, ySpread, SINGLE); // return patch(location, attempts, xzSpread, ySpread, SINGLE);
} // }
//
public static BCLFeature // @Deprecated(forRemoval = true)
patch( // public static BCLFeature
ResourceLocation location, // wallPatch(
int attempts, // ResourceLocation location,
int xzSpread, // Block block,
int ySpread, // int attempts,
BCLFeature single // int xzSpread,
) { // int ySpread
ResourceLocation patchLocation = new ResourceLocation(location.getNamespace(), location.getPath() + "_patch"); // ) {
// final BCLFeature SINGLE = simple(location, ySpread, false,
return BCLFeatureBuilder // org.betterx.bclib.api.v3.levelgen.features.BCLFeature.PLACE_BLOCK,
.start(patchLocation, Feature.RANDOM_PATCH) // new PlaceFacingBlockConfig(block, PlaceFacingBlockConfig.HORIZONTAL)
.buildAndRegister(new RandomPatchConfiguration(attempts, xzSpread, ySpread, single.getPlacedFeature())); // );
} // return patch(location, attempts, xzSpread, ySpread, SINGLE);
// }
//
// @Deprecated(forRemoval = true)
// public static BCLFeature
// patch(
// ResourceLocation location,
// int attempts,
// int xzSpread,
// int ySpread,
// BCLFeature single
// ) {
// ResourceLocation patchLocation = new ResourceLocation(location.getNamespace(), location.getPath() + "_patch");
//
// return BCLFeatureBuilder
// .start(patchLocation, Feature.RANDOM_PATCH)
// .buildAndRegister(new RandomPatchConfiguration(attempts, xzSpread, ySpread, single.getPlacedFeature()));
// }
//
} }

View file

@ -1,15 +1,11 @@
package org.betterx.bclib.api.v2.levelgen.features; package org.betterx.bclib.api.v2.levelgen.features;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
public interface UserGrowableFeature<FC extends FeatureConfiguration> { /**
boolean grow( * @param <FC>
ServerLevelAccessor level, * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.UserGrowableFeature} instead
BlockPos pos, */
RandomSource random, @Deprecated(forRemoval = true)
FC configuration public interface UserGrowableFeature<FC extends FeatureConfiguration> extends org.betterx.bclib.api.v3.levelgen.features.UserGrowableFeature<FC> {
);
} }

View file

@ -1,21 +1,34 @@
package org.betterx.bclib.api.v2.levelgen.features.blockpredicates; package org.betterx.bclib.api.v2.levelgen.features.blockpredicates;
import org.betterx.bclib.BCLib; import org.betterx.bclib.api.v3.levelgen.features.blockpredicates.BlockPredicates;
import org.betterx.bclib.api.v3.levelgen.features.blockpredicates.IsFullShape;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate; import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicateType; import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicateType;
/**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.blockpredicates.BlockPredicates} instead
*/
@Deprecated(forRemoval = true)
public class Types { public class Types {
public static final BlockPredicateType<IsFullShape> FULL_SHAPE = register( /**
BCLib.makeID("full_shape"), * @deprecated Please use {@link BlockPredicates#FULL_SHAPE} instead
IsFullShape.CODEC */
); @Deprecated(forRemoval = true)
public static final BlockPredicateType<IsFullShape> FULL_SHAPE = BlockPredicates.FULL_SHAPE;
/**
* @param location
* @param codec
* @param <P>
* @return
* @deprecated Please use {@link BlockPredicates#register(ResourceLocation, Codec)} instead
*/
@Deprecated(forRemoval = true)
public static <P extends BlockPredicate> BlockPredicateType<P> register(ResourceLocation location, Codec<P> codec) { public static <P extends BlockPredicate> BlockPredicateType<P> register(ResourceLocation location, Codec<P> codec) {
return Registry.register(Registry.BLOCK_PREDICATE_TYPES, location, () -> codec); return BlockPredicates.register(location, codec);
} }
public static void ensureStaticInitialization() { public static void ensureStaticInitialization() {

View file

@ -2,10 +2,7 @@ package org.betterx.bclib.api.v2.levelgen.features.config;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature; import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.PlacementFilter; import net.minecraft.world.level.levelgen.placement.PlacementFilter;
import net.minecraft.world.level.levelgen.placement.PlacementModifier; import net.minecraft.world.level.levelgen.placement.PlacementModifier;
@ -13,25 +10,14 @@ import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import java.util.Optional; import java.util.Optional;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class ConditionFeatureConfig implements FeatureConfiguration { /**
public static final Codec<ConditionFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.config.ConditionFeatureConfig} instead
instance.group( */
PlacementModifier.CODEC.fieldOf("filter").forGetter(p -> p.filter), @Deprecated(forRemoval = true)
PlacedFeature.CODEC.fieldOf("filter_pass").forGetter(p -> p.okFeature), public class ConditionFeatureConfig extends org.betterx.bclib.api.v3.levelgen.features.config.ConditionFeatureConfig {
PlacedFeature.CODEC.optionalFieldOf("filter_fail").forGetter(p -> p.failFeature)
).apply(instance, ConditionFeatureConfig::new)
);
public final PlacementModifier filter;
public final Holder<PlacedFeature> okFeature;
public final Optional<Holder<PlacedFeature>> failFeature;
public ConditionFeatureConfig(
@NotNull PlacementFilter filter,
@NotNull BCLFeature okFeature
) {
this(filter, okFeature.getPlacedFeature(), Optional.empty());
public ConditionFeatureConfig(@NotNull PlacementFilter filter, @NotNull BCLFeature okFeature) {
super(filter, okFeature);
} }
public ConditionFeatureConfig( public ConditionFeatureConfig(
@ -39,15 +25,11 @@ public class ConditionFeatureConfig implements FeatureConfiguration {
@NotNull BCLFeature okFeature, @NotNull BCLFeature okFeature,
@NotNull BCLFeature failFeature @NotNull BCLFeature failFeature
) { ) {
this(filter, okFeature.getPlacedFeature(), Optional.of(failFeature.getPlacedFeature())); super(filter, okFeature, failFeature);
} }
public ConditionFeatureConfig( public ConditionFeatureConfig(@NotNull PlacementFilter filter, @NotNull Holder<PlacedFeature> okFeature) {
@NotNull PlacementFilter filter, super(filter, okFeature);
@NotNull Holder<PlacedFeature> okFeature
) {
this(filter, okFeature, Optional.empty());
} }
public ConditionFeatureConfig( public ConditionFeatureConfig(
@ -55,7 +37,7 @@ public class ConditionFeatureConfig implements FeatureConfiguration {
@NotNull Holder<PlacedFeature> okFeature, @NotNull Holder<PlacedFeature> okFeature,
@NotNull Holder<PlacedFeature> failFeature @NotNull Holder<PlacedFeature> failFeature
) { ) {
this(filter, okFeature, Optional.of(failFeature)); super(filter, okFeature, failFeature);
} }
protected ConditionFeatureConfig( protected ConditionFeatureConfig(
@ -63,8 +45,6 @@ public class ConditionFeatureConfig implements FeatureConfiguration {
@NotNull Holder<PlacedFeature> okFeature, @NotNull Holder<PlacedFeature> okFeature,
@NotNull Optional<Holder<PlacedFeature>> failFeature @NotNull Optional<Holder<PlacedFeature>> failFeature
) { ) {
this.filter = filter; super(filter, okFeature, failFeature);
this.okFeature = okFeature;
this.failFeature = failFeature;
} }
} }

View file

@ -1,78 +1,32 @@
package org.betterx.bclib.api.v2.levelgen.features.config; package org.betterx.bclib.api.v2.levelgen.features.config;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.util.random.SimpleWeightedRandomList; import net.minecraft.util.random.SimpleWeightedRandomList;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider; import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import net.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider;
import java.util.List; import java.util.List;
public abstract class PlaceBlockFeatureConfig implements FeatureConfiguration { @Deprecated(forRemoval = true)
public abstract class PlaceBlockFeatureConfig extends org.betterx.bclib.api.v3.levelgen.features.config.PlaceBlockFeatureConfig {
protected static <T extends PlaceBlockFeatureConfig> RecordCodecBuilder<T, BlockStateProvider> blockStateCodec() {
return BlockStateProvider.CODEC
.fieldOf("entries")
.forGetter((T o) -> o.stateProvider);
}
protected final BlockStateProvider stateProvider;
protected static SimpleWeightedRandomList<BlockState> buildWeightedList(List<BlockState> states) {
var builder = SimpleWeightedRandomList.<BlockState>builder();
for (BlockState s : states) builder.add(s, 1);
return builder.build();
}
protected static SimpleWeightedRandomList<BlockState> buildWeightedList(BlockState state) {
return SimpleWeightedRandomList
.<BlockState>builder()
.add(state, 1)
.build();
}
public PlaceBlockFeatureConfig(Block block) { public PlaceBlockFeatureConfig(Block block) {
this(block.defaultBlockState()); super(block);
} }
public PlaceBlockFeatureConfig(BlockState state) { public PlaceBlockFeatureConfig(BlockState state) {
this(BlockStateProvider.simple(state)); super(state);
} }
public PlaceBlockFeatureConfig(List<BlockState> states) { public PlaceBlockFeatureConfig(List<BlockState> states) {
this(buildWeightedList(states)); super(states);
} }
public PlaceBlockFeatureConfig(SimpleWeightedRandomList<BlockState> blocks) { public PlaceBlockFeatureConfig(SimpleWeightedRandomList<BlockState> blocks) {
this.stateProvider = new WeightedStateProvider(blocks); super(blocks);
} }
public PlaceBlockFeatureConfig(BlockStateProvider blocks) { public PlaceBlockFeatureConfig(BlockStateProvider blocks) {
this.stateProvider = blocks; super(blocks);
} }
public BlockState getRandomBlock(RandomSource random, BlockPos pos) {
return this.stateProvider.getState(random, pos);
}
public boolean place(FeaturePlaceContext<? extends PlaceBlockFeatureConfig> ctx) {
BlockState state = getRandomBlock(ctx.random(), ctx.origin());
return placeBlock(ctx, ctx.level(), ctx.origin(), state);
}
protected abstract boolean placeBlock(
FeaturePlaceContext<? extends PlaceBlockFeatureConfig> ctx,
WorldGenLevel level,
BlockPos pos,
BlockState targetState
);
} }

View file

@ -1,92 +1,37 @@
package org.betterx.bclib.api.v2.levelgen.features.config; package org.betterx.bclib.api.v2.levelgen.features.config;
import org.betterx.bclib.util.BlocksHelper;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.random.SimpleWeightedRandomList; import net.minecraft.util.random.SimpleWeightedRandomList;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider; import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import net.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider;
import java.util.List; import java.util.List;
public class PlaceFacingBlockConfig extends PlaceBlockFeatureConfig {
public static final Codec<PlaceFacingBlockConfig> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
blockStateCodec(),
ExtraCodecs.nonEmptyList(Direction.CODEC.listOf())
.fieldOf("dir")
.orElse(List.of(Direction.NORTH))
.forGetter(a -> a.directions)
).apply(instance, PlaceFacingBlockConfig::new)
);
public static final List<Direction> HORIZONTAL = List.of(
Direction.NORTH,
Direction.EAST,
Direction.WEST,
Direction.SOUTH
);
public static final List<Direction> VERTICAL = List.of(Direction.UP, Direction.DOWN);
public static final List<Direction> ALL = List.of(
Direction.NORTH,
Direction.EAST,
Direction.SOUTH,
Direction.WEST,
Direction.UP,
Direction.DOWN
);
private final List<Direction> directions; /**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.config.PlaceFacingBlockConfig} instead
*/
@Deprecated(forRemoval = true)
public class PlaceFacingBlockConfig extends org.betterx.bclib.api.v3.levelgen.features.config.PlaceFacingBlockConfig {
public PlaceFacingBlockConfig(Block block, List<Direction> dir) { public PlaceFacingBlockConfig(Block block, List<Direction> dir) {
this(block.defaultBlockState(), dir); super(block, dir);
} }
public PlaceFacingBlockConfig(BlockState state, List<Direction> dir) { public PlaceFacingBlockConfig(BlockState state, List<Direction> dir) {
this(BlockStateProvider.simple(state), dir); super(state, dir);
} }
public PlaceFacingBlockConfig(List<BlockState> states, List<Direction> dir) { public PlaceFacingBlockConfig(List<BlockState> states, List<Direction> dir) {
this(buildWeightedList(states), dir); super(states, dir);
} }
public PlaceFacingBlockConfig(SimpleWeightedRandomList<BlockState> blocks, List<Direction> dir) { public PlaceFacingBlockConfig(SimpleWeightedRandomList<BlockState> blocks, List<Direction> dir) {
this(new WeightedStateProvider(blocks), dir); super(blocks, dir);
} }
public PlaceFacingBlockConfig(BlockStateProvider blocks, List<Direction> dir) { public PlaceFacingBlockConfig(BlockStateProvider blocks, List<Direction> dir) {
super(blocks); super(blocks, dir);
directions = dir;
}
@Override
public boolean placeBlock(
FeaturePlaceContext<? extends PlaceBlockFeatureConfig> ctx,
WorldGenLevel level,
BlockPos pos,
BlockState targetState
) {
BlockState lookupState;
BlockPos testPos;
for (Direction dir : directions) {
testPos = pos.relative(dir.getOpposite());
lookupState = targetState.setValue(HorizontalDirectionalBlock.FACING, dir);
if (lookupState.canSurvive(level, testPos) && level.getBlockState(testPos).isAir()) {
BlocksHelper.setWithoutUpdate(level, testPos, lookupState);
//BlocksHelper.setWithoutUpdate(level, pos, level.getBlockState(pos.relative(dir.getOpposite())));
return true;
}
}
return false;
} }
} }

View file

@ -1,46 +1,17 @@
package org.betterx.bclib.api.v2.levelgen.features.config; package org.betterx.bclib.api.v2.levelgen.features.config;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import java.util.List; import java.util.List;
public class SequenceFeatureConfig implements FeatureConfiguration { /**
public static final Codec<SequenceFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.config.SequenceFeatureConfig instead}
instance.group( */
ExtraCodecs.nonEmptyList(PlacedFeature.CODEC.listOf()) @Deprecated(forRemoval = true)
.fieldOf("features") public class SequenceFeatureConfig extends org.betterx.bclib.api.v3.levelgen.features.config.SequenceFeatureConfig {
.forGetter(a -> a.features)
).apply(instance, SequenceFeatureConfig::new)
);
private final List<Holder<PlacedFeature>> features;
public static SequenceFeatureConfig create(List<BCLFeature<?, ?>> features) {
return new SequenceFeatureConfig(features.stream().map(f -> f.getPlacedFeature()).toList());
}
public static SequenceFeatureConfig createSequence(List<org.betterx.bclib.api.v3.levelgen.features.BCLFeature<?, ?>> features) {
return new SequenceFeatureConfig(features.stream().map(f -> f.getPlacedFeature()).toList());
}
public SequenceFeatureConfig(List<Holder<PlacedFeature>> features) { public SequenceFeatureConfig(List<Holder<PlacedFeature>> features) {
this.features = features; super(features);
}
public boolean placeAll(FeaturePlaceContext<SequenceFeatureConfig> ctx) {
boolean placed = false;
for (Holder<PlacedFeature> f : features) {
placed |= f.value().place(ctx.level(), ctx.chunkGenerator(), ctx.random(), ctx.origin());
}
return placed;
} }
} }

View file

@ -3,40 +3,20 @@ package org.betterx.bclib.api.v2.levelgen.features.config;
import org.betterx.bclib.api.v2.levelgen.structures.StructurePlacementType; import org.betterx.bclib.api.v2.levelgen.structures.StructurePlacementType;
import org.betterx.bclib.api.v2.levelgen.structures.StructureWorldNBT; import org.betterx.bclib.api.v2.levelgen.structures.StructureWorldNBT;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import java.util.List; import java.util.List;
public class TemplateFeatureConfig implements FeatureConfiguration { /**
public static final Codec<TemplateFeatureConfig> CODEC = RecordCodecBuilder.create((instance) -> instance * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.config.TemplateFeatureConfig} instead
.group( */
ExtraCodecs.nonEmptyList(StructureWorldNBT.CODEC.listOf()) public class TemplateFeatureConfig extends org.betterx.bclib.api.v3.levelgen.features.config.TemplateFeatureConfig {
.fieldOf("structures")
.forGetter((TemplateFeatureConfig cfg) -> cfg.structures)
)
.apply(instance, TemplateFeatureConfig::new)
);
public final List<StructureWorldNBT> structures;
public static StructureWorldNBT cfg(
ResourceLocation location,
int offsetY,
StructurePlacementType type,
float chance
) {
return StructureWorldNBT.create(location, offsetY, type, chance);
}
public TemplateFeatureConfig(ResourceLocation location, int offsetY, StructurePlacementType type) { public TemplateFeatureConfig(ResourceLocation location, int offsetY, StructurePlacementType type) {
this(List.of(cfg(location, offsetY, type, 1.0f))); super(location, offsetY, type);
} }
public TemplateFeatureConfig(List<StructureWorldNBT> structures) { public TemplateFeatureConfig(List<StructureWorldNBT> structures) {
this.structures = structures; super(structures);
} }
} }

View file

@ -1,38 +1,8 @@
package org.betterx.bclib.api.v2.levelgen.features.features; package org.betterx.bclib.api.v2.levelgen.features.features;
import org.betterx.bclib.api.v2.levelgen.features.config.ConditionFeatureConfig; /**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.features.ConditionFeature} instead.
import net.minecraft.core.BlockPos; */
import net.minecraft.core.Holder; @Deprecated(forRemoval = true)
import net.minecraft.util.RandomSource; public class ConditionFeature extends org.betterx.bclib.api.v3.levelgen.features.features.ConditionFeature {
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.PlacementContext;
import java.util.Optional;
import java.util.stream.Stream;
public class ConditionFeature extends Feature<ConditionFeatureConfig> {
public ConditionFeature() {
super(ConditionFeatureConfig.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<ConditionFeatureConfig> ctx) {
final ConditionFeatureConfig cfg = ctx.config();
final WorldGenLevel level = ctx.level();
final RandomSource random = ctx.random();
final BlockPos pos = ctx.origin();
final PlacementContext c = new PlacementContext(level, ctx.chunkGenerator(), Optional.empty());
Stream<BlockPos> stream = cfg.filter.getPositions(c, ctx.random(), pos);
Holder<PlacedFeature> state = (stream.findFirst().isPresent() ? cfg.okFeature : cfg.failFeature.orElse(null));
if (state != null) {
return state.value().place(level, ctx.chunkGenerator(), random, pos);
}
return false;
}
} }

View file

@ -1,20 +1,8 @@
package org.betterx.bclib.api.v2.levelgen.features.features; package org.betterx.bclib.api.v2.levelgen.features.features;
import net.minecraft.core.BlockPos; /**
import net.minecraft.world.level.levelgen.feature.Feature; * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.features.MarkPostProcessingFeature} instead.
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; */
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; @Deprecated(forRemoval = true)
public class MarkPostProcessingFeature extends org.betterx.bclib.api.v3.levelgen.features.features.MarkPostProcessingFeature {
public class MarkPostProcessingFeature extends Feature<NoneFeatureConfiguration> {
public MarkPostProcessingFeature() {
super(NoneFeatureConfiguration.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> ctx) {
BlockPos pos = ctx.origin();
ctx.level().getChunk(pos.getX() >> 4, pos.getZ() >> 4)
.markPosForPostprocessing(new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15));
return true;
}
} }

View file

@ -1,18 +1,16 @@
package org.betterx.bclib.api.v2.levelgen.features.features; package org.betterx.bclib.api.v2.levelgen.features.features;
import org.betterx.bclib.api.v2.levelgen.features.config.PlaceBlockFeatureConfig; import org.betterx.bclib.api.v3.levelgen.features.config.PlaceBlockFeatureConfig;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
public class PlaceBlockFeature<FC extends PlaceBlockFeatureConfig> extends Feature<FC> { /**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.features.PlaceBlockFeature} instead.
*/
@Deprecated(forRemoval = true)
public class PlaceBlockFeature<FC extends PlaceBlockFeatureConfig> extends org.betterx.bclib.api.v3.levelgen.features.features.PlaceBlockFeature<FC> {
public PlaceBlockFeature(Codec<FC> codec) { public PlaceBlockFeature(Codec<FC> codec) {
super(codec); super(codec);
} }
@Override
public boolean place(FeaturePlaceContext<FC> ctx) {
return ctx.config().place(ctx);
}
} }

View file

@ -1,7 +1,7 @@
package org.betterx.bclib.api.v2.levelgen.features.features; package org.betterx.bclib.api.v2.levelgen.features.features;
import org.betterx.bclib.api.v2.levelgen.features.UserGrowableFeature;
import org.betterx.bclib.api.v2.levelgen.features.config.ScatterFeatureConfig; import org.betterx.bclib.api.v2.levelgen.features.config.ScatterFeatureConfig;
import org.betterx.bclib.api.v3.levelgen.features.UserGrowableFeature;
import org.betterx.bclib.util.BlocksHelper; import org.betterx.bclib.util.BlocksHelper;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
@ -17,6 +17,7 @@ import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import java.util.Optional; import java.util.Optional;
@Deprecated(forRemoval = true)
public class ScatterFeature<FC extends ScatterFeatureConfig> public class ScatterFeature<FC extends ScatterFeatureConfig>
extends Feature<FC> implements UserGrowableFeature<FC> { extends Feature<FC> implements UserGrowableFeature<FC> {

View file

@ -1,17 +1,9 @@
package org.betterx.bclib.api.v2.levelgen.features.features; package org.betterx.bclib.api.v2.levelgen.features.features;
import org.betterx.bclib.api.v2.levelgen.features.config.SequenceFeatureConfig; /**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.features.SequenceFeature} instead.
*/
@Deprecated(forRemoval = true)
public class SequenceFeature extends org.betterx.bclib.api.v3.levelgen.features.features.SequenceFeature {
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
public class SequenceFeature extends Feature<SequenceFeatureConfig> {
public SequenceFeature() {
super(SequenceFeatureConfig.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<SequenceFeatureConfig> featurePlaceContext) {
return featurePlaceContext.config().placeAll(featurePlaceContext);
}
} }

View file

@ -12,6 +12,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConf
import java.util.Optional; import java.util.Optional;
@Deprecated(forRemoval = true)
public abstract class SurfaceFeature<T extends FeatureConfiguration> extends Feature<T> { public abstract class SurfaceFeature<T extends FeatureConfiguration> extends Feature<T> {
public static abstract class DefaultConfiguration extends SurfaceFeature<NoneFeatureConfiguration> { public static abstract class DefaultConfiguration extends SurfaceFeature<NoneFeatureConfiguration> {
protected DefaultConfiguration() { protected DefaultConfiguration() {

View file

@ -1,87 +1,16 @@
package org.betterx.bclib.api.v2.levelgen.features.features; package org.betterx.bclib.api.v2.levelgen.features.features;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature; import org.betterx.bclib.api.v3.levelgen.features.config.TemplateFeatureConfig;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeatureBuilder;
import org.betterx.bclib.api.v2.levelgen.features.config.TemplateFeatureConfig;
import org.betterx.bclib.api.v2.levelgen.structures.StructureNBT;
import org.betterx.bclib.api.v2.levelgen.structures.StructureWorldNBT;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
public class TemplateFeature<FC extends TemplateFeatureConfig> extends Feature<FC> { /**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.features.TemplateFeature} instead.
public static <T extends TemplateFeatureConfig> BCLFeature createAndRegisterRare( */
ResourceLocation location, @Deprecated(forRemoval = true)
TemplateFeatureConfig configuration, public class TemplateFeature<FC extends TemplateFeatureConfig> extends org.betterx.bclib.api.v3.levelgen.features.features.TemplateFeature<FC> {
int onceEveryChunk
) {
return BCLFeatureBuilder
.start(location, org.betterx.bclib.api.v3.levelgen.features.BCLFeature.TEMPLATE)
.decoration(GenerationStep.Decoration.SURFACE_STRUCTURES)
.onceEvery(onceEveryChunk) //discard neighboring chunks
.count(16) //try 16 placements in chunk
.squarePlacement() //randomize x/z in chunk
.randomHeight10FromFloorCeil() //randomize height 10 above and 10 below max vertical
.findSolidFloor(12) //cast downward ray to find solid surface
.isEmptyAbove4() //make sure we have 4 free blocks above
.onlyInBiome() //ensure that we still are in the correct biome
.buildAndRegister(configuration);
}
public static <T extends TemplateFeatureConfig> BCLFeature createAndRegister(
ResourceLocation location,
TemplateFeatureConfig configuration,
int count
) {
return BCLFeatureBuilder
.start(location, org.betterx.bclib.api.v3.levelgen.features.BCLFeature.TEMPLATE)
.decoration(GenerationStep.Decoration.SURFACE_STRUCTURES)
.count(count)
.squarePlacement()
.randomHeight10FromFloorCeil()
.findSolidFloor(12) //cast downward ray to find solid surface
.isEmptyAbove4()
.onlyInBiome()
.buildAndRegister(configuration);
}
public TemplateFeature(Codec<FC> codec) { public TemplateFeature(Codec<FC> codec) {
super(codec); super(codec);
} }
protected StructureWorldNBT randomStructure(TemplateFeatureConfig cfg, RandomSource random) {
if (cfg.structures.size() > 1) {
final float chanceSum = cfg.structures.parallelStream().map(c -> c.chance).reduce(0.0f, (p, c) -> p + c);
float rnd = random.nextFloat() * chanceSum;
for (StructureWorldNBT c : cfg.structures) {
rnd -= c.chance;
if (rnd <= 0) return c;
}
} else {
return cfg.structures.get(0);
}
return null;
}
@Override
public boolean place(FeaturePlaceContext<FC> ctx) {
StructureWorldNBT structure = randomStructure(ctx.config(), ctx.random());
return structure.generateIfPlaceable(
ctx.level(),
ctx.origin(),
StructureNBT.getRandomRotation(ctx.random()),
StructureNBT.getRandomMirror(ctx.random())
);
}
} }

View file

@ -10,6 +10,8 @@ import net.minecraft.world.level.levelgen.feature.WeightedPlacedFeature;
import net.minecraft.world.level.levelgen.feature.configurations.RandomFeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.RandomFeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraft.world.level.levelgen.placement.PlacedFeature;
@Deprecated(forRemoval = true)
public class WeightedRandomSelectorFeature extends Feature<RandomFeatureConfiguration> { public class WeightedRandomSelectorFeature extends Feature<RandomFeatureConfiguration> {
public WeightedRandomSelectorFeature() { public WeightedRandomSelectorFeature() {
super(RandomFeatureConfiguration.CODEC); super(RandomFeatureConfiguration.CODEC);

View file

@ -1,34 +1,9 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; package org.betterx.bclib.api.v2.levelgen.features.placement;
import com.mojang.serialization.Codec; /**
import net.minecraft.core.BlockPos; * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.All} instead.
import net.minecraft.util.RandomSource; */
import net.minecraft.world.level.levelgen.placement.PlacementContext; @Deprecated(forRemoval = true)
import net.minecraft.world.level.levelgen.placement.PlacementModifier; public class All extends org.betterx.bclib.api.v3.levelgen.features.placement.All {
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class All extends PlacementModifier {
private static final All INSTANCE = new All();
public static final Codec<All> CODEC = Codec.unit(All::new);
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
return IntStream.range(0, 16 * 16 - 1).mapToObj(i -> blockPos.offset(i & 0xF, 0, i >> 4));
}
public static PlacementModifier simple() {
return INSTANCE;
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.ALL;
}
} }

View file

@ -1,29 +1,9 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; package org.betterx.bclib.api.v2.levelgen.features.placement;
import com.mojang.serialization.Codec; /**
import net.minecraft.core.BlockPos; * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.Debug} instead.
import net.minecraft.util.RandomSource; */
import net.minecraft.world.level.levelgen.placement.PlacementContext; @Deprecated(forRemoval = true)
import net.minecraft.world.level.levelgen.placement.PlacementModifier; public class Debug extends org.betterx.bclib.api.v3.levelgen.features.placement.Debug {
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
import java.util.stream.Stream;
public class Debug extends PlacementModifier {
public static final Debug INSTANCE = new Debug();
public static final Codec<Debug> CODEC = Codec.unit(Debug::new);
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
return Stream.of(blockPos);
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.DEBUG;
}
} }

View file

@ -1,57 +1,14 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; 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.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.util.valueproviders.IntProvider; import net.minecraft.util.valueproviders.IntProvider;
import net.minecraft.util.valueproviders.UniformInt;
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.stream.Stream;
public class Extend extends PlacementModifier {
public static final Codec<Extend> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
Direction.CODEC
.fieldOf("direction")
.orElse(Direction.DOWN)
.forGetter(cfg -> cfg.direction),
IntProvider.codec(0, 16)
.fieldOf("length")
.orElse(UniformInt.of(0, 3))
.forGetter(cfg -> cfg.length)
)
.apply(instance, Extend::new));
private final Direction direction;
private final IntProvider length;
/**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.Extend} instead.
*/
@Deprecated(forRemoval = true)
public class Extend extends org.betterx.bclib.api.v3.levelgen.features.placement.Extend {
public Extend(Direction direction, IntProvider length) { public Extend(Direction direction, IntProvider length) {
this.direction = direction; super(direction, length);
this.length = length;
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource random,
BlockPos blockPos
) {
var builder = Stream.<BlockPos>builder();
final int count = length.sample(random);
builder.add(blockPos);
for (int y = 1; y < count + 1; y++) {
builder.add(blockPos.relative(direction, y));
}
return builder.build();
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.EXTEND;
} }
} }

View file

@ -1,134 +1,25 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; package org.betterx.bclib.api.v2.levelgen.features.placement;
import org.betterx.bclib.util.BlocksHelper;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.SectionPos;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.RandomSource;
import net.minecraft.util.valueproviders.IntProvider;
import net.minecraft.util.valueproviders.UniformInt;
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.List;
import java.util.stream.Stream;
public class FindSolidInDirection extends PlacementModifier { /**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.FindSolidInDirection} instead.
public static final Codec<FindSolidInDirection> CODEC = RecordCodecBuilder */
.create((instance) -> instance.group( @Deprecated(forRemoval = true)
ExtraCodecs.nonEmptyList(Direction.CODEC.listOf()) public class FindSolidInDirection extends org.betterx.bclib.api.v3.levelgen.features.placement.FindSolidInDirection {
.fieldOf("dir")
.orElse(List.of(Direction.DOWN))
.forGetter(a -> a.direction),
Codec.intRange(1, 32).fieldOf("dist").orElse(12).forGetter((p) -> p.maxSearchDistance),
Codec.BOOL.fieldOf("random:select").orElse(true).forGetter(p -> p.randomSelect)
)
.apply(
instance,
FindSolidInDirection::new
));
protected static final FindSolidInDirection DOWN = new FindSolidInDirection(Direction.DOWN, 6);
protected static final FindSolidInDirection UP = new FindSolidInDirection(Direction.UP, 6);
private final List<Direction> direction;
private final int maxSearchDistance;
private final boolean randomSelect;
private final IntProvider provider;
public FindSolidInDirection(Direction direction, int maxSearchDistance) { public FindSolidInDirection(Direction direction, int maxSearchDistance) {
this(List.of(direction), maxSearchDistance, false); super(direction, maxSearchDistance);
} }
public FindSolidInDirection(List<Direction> direction, int maxSearchDistance) { public FindSolidInDirection(List<Direction> direction, int maxSearchDistance) {
this(direction, maxSearchDistance, direction.size() > 1); super(direction, maxSearchDistance);
} }
public FindSolidInDirection(List<Direction> direction, int maxSearchDistance, boolean randomSelect) { public FindSolidInDirection(List<Direction> direction, int maxSearchDistance, boolean randomSelect) {
this.direction = direction; super(direction, maxSearchDistance, randomSelect);
this.maxSearchDistance = maxSearchDistance;
this.provider = UniformInt.of(0, direction.size() - 1);
this.randomSelect = randomSelect;
}
public static PlacementModifier down() {
return DOWN;
}
public static PlacementModifier up() {
return UP;
}
public static PlacementModifier down(int dist) {
if (dist == DOWN.maxSearchDistance) return DOWN;
return new FindSolidInDirection(Direction.DOWN, dist);
}
public static PlacementModifier up(int dist) {
if (dist == UP.maxSearchDistance) return UP;
return new FindSolidInDirection(Direction.UP, dist);
}
public Direction randomDirection(RandomSource random) {
return direction.get(provider.sample(random));
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
var builder = Stream.<BlockPos>builder();
if (randomSelect) {
submitSingle(placementContext, blockPos, builder, randomDirection(randomSource));
} else {
for (Direction d : direction) {
submitSingle(placementContext, blockPos, builder, d);
}
}
return builder.build();
}
private void submitSingle(
PlacementContext placementContext,
BlockPos blockPos,
Stream.Builder<BlockPos> builder,
Direction d
) {
int searchDist;
BlockPos.MutableBlockPos POS = blockPos.mutable();
if (d == Direction.EAST) { //+x
searchDist = Math.min(maxSearchDistance, 15 - SectionPos.sectionRelative(blockPos.getX()));
} else if (d == Direction.WEST) { //-x
searchDist = Math.min(maxSearchDistance, SectionPos.sectionRelative(blockPos.getX()));
} else if (d == Direction.SOUTH) { //+z
searchDist = Math.min(maxSearchDistance, 15 - SectionPos.sectionRelative(blockPos.getZ()));
} else if (d == Direction.NORTH) { //-z
searchDist = Math.min(maxSearchDistance, SectionPos.sectionRelative(blockPos.getZ()));
} else {
searchDist = maxSearchDistance;
}
if (BlocksHelper.findOnSurroundingSurface(
placementContext.getLevel(),
POS,
d,
searchDist,
BlocksHelper::isTerrain
)) {
builder.add(POS);
}
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.SOLID_IN_DIR;
} }
} }

View file

@ -1,47 +1,16 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; 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.PlacementModifier;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
import java.util.List; import java.util.List;
import java.util.stream.Stream;
public class ForAll extends PlacementModifier { /**
public static final Codec<ForAll> CODEC = RecordCodecBuilder.create(instance -> instance * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.ForAll} instead.
.group( */
ExtraCodecs.nonEmptyList(PlacementModifier.CODEC.listOf()) @Deprecated(forRemoval = true)
.fieldOf("modifiers") public class ForAll extends org.betterx.bclib.api.v3.levelgen.features.placement.ForAll {
.forGetter(a -> a.modifiers)
)
.apply(instance, ForAll::new));
private final List<PlacementModifier> modifiers;
public ForAll(List<PlacementModifier> modifiers) { public ForAll(List<PlacementModifier> modifiers) {
this.modifiers = modifiers; super(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;
} }
} }

View file

@ -1,59 +1,17 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; 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.Direction;
import net.minecraft.core.Vec3i; 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.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 java.util.Optional;
public class Is extends PlacementFilter { /**
public static final Codec<Is> CODEC = RecordCodecBuilder.create((instance) -> instance * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.Is} instead.
.group( */
BlockPredicate.CODEC @Deprecated(forRemoval = true)
.fieldOf("predicate") public class Is extends org.betterx.bclib.api.v3.levelgen.features.placement.Is {
.forGetter(cfg -> cfg.predicate),
Vec3i.CODEC
.optionalFieldOf("offset")
.forGetter(cfg -> cfg.offset)
)
.apply(instance, Is::new));
private final BlockPredicate predicate;
private final Optional<Vec3i> offset;
public Is(BlockPredicate predicate, Optional<Vec3i> offset) { public Is(BlockPredicate predicate, Optional<Vec3i> offset) {
this.predicate = predicate; super(predicate, offset);
this.offset = offset;
}
public static Is simple(BlockPredicate predicate) {
return new Is(predicate, Optional.empty());
}
public static Is below(BlockPredicate predicate) {
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();
return predicate.test(level, offset.map(v -> pos.offset(v.getX(), v.getY(), v.getZ())).orElse(pos));
}
@Override
public PlacementModifierType<Is> type() {
return PlacementModifiers.IS;
} }
} }

View file

@ -1,64 +1,21 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; 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.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate; 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 java.util.Optional;
public class IsBasin extends PlacementFilter {
public static final Codec<IsBasin> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
BlockPredicate.CODEC
.fieldOf("predicate")
.forGetter(cfg -> cfg.predicate),
BlockPredicate.CODEC
.optionalFieldOf("top_predicate")
.orElse(Optional.empty())
.forGetter(cfg -> cfg.topPredicate)
)
.apply(instance, IsBasin::new));
private final BlockPredicate predicate; /**
private final Optional<BlockPredicate> topPredicate; * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.IsBasin} instead.
*/
@Deprecated(forRemoval = true)
public class IsBasin extends org.betterx.bclib.api.v3.levelgen.features.placement.IsBasin {
public IsBasin(BlockPredicate predicate) { public IsBasin(BlockPredicate predicate) {
this(predicate, Optional.empty()); super(predicate);
} }
public IsBasin(BlockPredicate predicate, Optional<BlockPredicate> topPredicate) { public IsBasin(BlockPredicate predicate, Optional<BlockPredicate> topPredicate) {
this.predicate = predicate; super(predicate, topPredicate);
this.topPredicate = topPredicate;
}
public static PlacementFilter simple(BlockPredicate predicate) {
return new IsBasin(predicate);
}
public static IsBasin openTop(BlockPredicate predicate) {
return new IsBasin(predicate, Optional.of(BlockPredicate.ONLY_IN_AIR_PREDICATE));
}
@Override
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
WorldGenLevel level = ctx.getLevel();
if (topPredicate.isPresent() && !topPredicate.get().test(level, pos.above())) return false;
return predicate.test(level, pos.below())
&& 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_BASIN;
} }
} }

View file

@ -12,6 +12,7 @@ import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
/** /**
* Tests if there is air at two locations above the tested block position * Tests if there is air at two locations above the tested block position
*/ */
@Deprecated(forRemoval = true)
public class IsEmptyAboveSampledFilter extends PlacementFilter { public class IsEmptyAboveSampledFilter extends PlacementFilter {
private static final IsEmptyAboveSampledFilter DEFAULT = new IsEmptyAboveSampledFilter(4, 2); private static final IsEmptyAboveSampledFilter DEFAULT = new IsEmptyAboveSampledFilter(4, 2);
private static final IsEmptyAboveSampledFilter DEFAULT1 = new IsEmptyAboveSampledFilter(1, 1); private static final IsEmptyAboveSampledFilter DEFAULT1 = new IsEmptyAboveSampledFilter(1, 1);

View file

@ -12,6 +12,7 @@ import net.minecraft.world.level.levelgen.placement.PlacementFilter;
import net.minecraft.world.level.levelgen.placement.PlacementModifier; import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType; import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
@Deprecated(forRemoval = true)
public class MinEmptyFilter extends PlacementFilter { public class MinEmptyFilter extends PlacementFilter {
private static final MinEmptyFilter DOWN = new MinEmptyFilter(Direction.DOWN, 2); private static final MinEmptyFilter DOWN = new MinEmptyFilter(Direction.DOWN, 2);
private static final MinEmptyFilter UP = new MinEmptyFilter(Direction.UP, 2); private static final MinEmptyFilter UP = new MinEmptyFilter(Direction.UP, 2);

View file

@ -1,56 +1,14 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; 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.Direction;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
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 com.google.common.collect.Maps; /**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.Offset} instead.
import java.util.Map; */
import java.util.stream.Stream; @Deprecated(forRemoval = true)
public class Offset extends org.betterx.bclib.api.v3.levelgen.features.placement.Offset {
public class Offset extends PlacementModifier {
private static final Map<Direction, Offset> DIRECTIONS = Maps.newHashMap();
public static final Codec<Offset> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
Vec3i.CODEC
.fieldOf("blocks")
.forGetter(cfg -> cfg.offset)
)
.apply(instance, Offset::new));
private final Vec3i offset;
public Offset(Vec3i offset) { public Offset(Vec3i offset) {
this.offset = offset; super(offset);
}
public static Offset inDirection(Direction dir) {
return DIRECTIONS.get(dir);
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
return Stream.of(blockPos.offset(offset));
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.OFFSET;
}
static {
for (Direction d : Direction.values())
DIRECTIONS.put(d, new Offset(d.getNormal()));
} }
} }

View file

@ -1,93 +1,14 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; package org.betterx.bclib.api.v2.levelgen.features.placement;
import org.betterx.bclib.util.BlocksHelper;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.Heightmap;
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.Optional; import java.util.Optional;
import java.util.stream.Stream;
public class OnEveryLayer /**
extends PlacementModifier { * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.OnEveryLayer} instead
private static final OnEveryLayer INSTANCE = new OnEveryLayer(Optional.empty(), Optional.empty()); */
private static final OnEveryLayer INSTANCE_MIN_4 = new OnEveryLayer(Optional.of(4), Optional.empty()); @Deprecated(forRemoval = true)
public static final Codec<OnEveryLayer> CODEC = RecordCodecBuilder.create(instance -> instance public class OnEveryLayer extends org.betterx.bclib.api.v3.levelgen.features.placement.OnEveryLayer {
.group(
Codec.INT.optionalFieldOf("min").forGetter(o -> o.minHeight),
Codec.INT.optionalFieldOf("max").forGetter(o -> o.maxHeight)
).apply(instance, OnEveryLayer::new));
protected OnEveryLayer(Optional<Integer> minHeight, Optional<Integer> maxHeight) {
private final Optional<Integer> minHeight; super(minHeight, maxHeight);
private final Optional<Integer> maxHeight;
private OnEveryLayer(Optional<Integer> minHeight, Optional<Integer> maxHeight) {
this.minHeight = minHeight;
this.maxHeight = maxHeight;
}
public static OnEveryLayer simple() {
return INSTANCE;
}
public static OnEveryLayer min4() {
return INSTANCE_MIN_4;
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext ctx,
RandomSource random,
BlockPos pos
) {
Stream.Builder<BlockPos> builder = Stream.builder();
final int z = pos.getZ();
final int x = pos.getX();
final int levelHeight = ctx.getHeight(Heightmap.Types.MOTION_BLOCKING, x, z);
final int minLevelHeight = ctx.getMinBuildHeight();
int y = maxHeight.map(h -> Math.min(levelHeight, h)).orElse(levelHeight);
final int minHeight = this.minHeight.map(h -> Math.max(minLevelHeight, h)).orElse(minLevelHeight);
int layerY;
do {
layerY = OnEveryLayer.findOnGroundYPosition(ctx, x, y, z, minHeight);
if (layerY != Integer.MAX_VALUE) {
builder.add(new BlockPos(x, layerY, z));
y = layerY - 1;
}
} while (layerY != Integer.MAX_VALUE);
return builder.build();
}
@Override
public PlacementModifierType<OnEveryLayer> type() {
return PlacementModifiers.ON_EVERY_LAYER;
}
private static int findOnGroundYPosition(PlacementContext ctx, int x, int startY, int z, int minHeight) {
BlockPos.MutableBlockPos mPos = new BlockPos.MutableBlockPos(x, startY, z);
BlockState nowState = ctx.getBlockState(mPos);
for (int y = startY; y >= minHeight + 1; --y) {
mPos.setY(y - 1);
BlockState belowState = ctx.getBlockState(mPos);
if (BlocksHelper.isTerrain(belowState) && BlocksHelper.isFreeOrFluid(nowState) && !belowState.is(Blocks.BEDROCK)) {
return mPos.getY() + 1;
}
nowState = belowState;
}
return Integer.MAX_VALUE;
} }
} }

View file

@ -1,23 +1,40 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; package org.betterx.bclib.api.v2.levelgen.features.placement;
import org.betterx.bclib.BCLib; import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v3.levelgen.features.placement.NoiseFilter; import org.betterx.bclib.api.v3.levelgen.features.placement.All;
import org.betterx.bclib.api.v3.levelgen.features.placement.Debug;
import org.betterx.bclib.api.v3.levelgen.features.placement.Extend;
import org.betterx.bclib.api.v3.levelgen.features.placement.FindSolidInDirection;
import org.betterx.bclib.api.v3.levelgen.features.placement.ForAll;
import org.betterx.bclib.api.v3.levelgen.features.placement.Is;
import org.betterx.bclib.api.v3.levelgen.features.placement.IsBasin;
import org.betterx.bclib.api.v3.levelgen.features.placement.Offset;
import org.betterx.bclib.api.v3.levelgen.features.placement.OnEveryLayer;
import org.betterx.bclib.api.v3.levelgen.features.placement.Stencil;
import org.betterx.bclib.api.v3.levelgen.features.placement.UnderEveryLayer;
import org.betterx.bclib.api.v3.levelgen.features.placement.*;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.placement.PlacementModifier; import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType; import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
/**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers} instead
*/
@Deprecated(forRemoval = true)
public class PlacementModifiers { public class PlacementModifiers {
public static final PlacementModifierType<NoiseFilter> NOISE_FILTER = register( /**
"noise_filter", * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#NOISE_FILTER} instead
NoiseFilter.CODEC */
); @Deprecated(forRemoval = true)
public static final PlacementModifierType<Debug> DEBUG = register( public static final PlacementModifierType<NoiseFilter> NOISE_FILTER = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.NOISE_FILTER;
"debug", /**
Debug.CODEC * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#DEBUG} instead
); */
@Deprecated(forRemoval = true)
public static final PlacementModifierType<Debug> DEBUG = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.DEBUG;
@Deprecated(forRemoval = true)
public static final PlacementModifierType<IsEmptyAboveSampledFilter> IS_EMPTY_ABOVE_SAMPLED_FILTER = register( public static final PlacementModifierType<IsEmptyAboveSampledFilter> IS_EMPTY_ABOVE_SAMPLED_FILTER = register(
"is_empty_above_sampled_filter", "is_empty_above_sampled_filter",
IsEmptyAboveSampledFilter.CODEC IsEmptyAboveSampledFilter.CODEC
@ -28,73 +45,87 @@ public class PlacementModifiers {
MinEmptyFilter.CODEC MinEmptyFilter.CODEC
); );
public static final PlacementModifierType<ForAll> FOR_ALL = register( /**
"for_all", * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#FOR_ALL} instead
ForAll.CODEC */
); @Deprecated(forRemoval = true)
public static final PlacementModifierType<ForAll> FOR_ALL = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.FOR_ALL;
public static final PlacementModifierType<FindSolidInDirection> SOLID_IN_DIR = register( /**
"solid_in_dir", * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#SOLID_IN_DIR} instead
FindSolidInDirection.CODEC */
); @Deprecated(forRemoval = true)
public static final PlacementModifierType<FindSolidInDirection> SOLID_IN_DIR = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.SOLID_IN_DIR;
public static final PlacementModifierType<Stencil> STENCIL = register( /**
"stencil", * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#STENCIL} instead
Stencil.CODEC */
); @Deprecated(forRemoval = true)
public static final PlacementModifierType<Stencil> STENCIL = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.STENCIL;
public static final PlacementModifierType<All> ALL = register( /**
"all", * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#ALL} instead
All.CODEC */
); @Deprecated(forRemoval = true)
public static final PlacementModifierType<All> ALL = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.ALL;
public static final PlacementModifierType<IsBasin> IS_BASIN = register( /**
"is_basin", * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#IS_BASIN} instead
IsBasin.CODEC */
); @Deprecated(forRemoval = true)
public static final PlacementModifierType<IsBasin> IS_BASIN = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.IS_BASIN;
public static final PlacementModifierType<IsNextTo> IS_NEXT_TO = register( /**
"is_next_to", * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#IS} instead
IsNextTo.CODEC */
); @Deprecated(forRemoval = true)
public static final PlacementModifierType<Is> IS = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.IS;
public static final PlacementModifierType<Is> IS = register( /**
"is", * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#OFFSET} instead
Is.CODEC */
); @Deprecated(forRemoval = true)
public static final PlacementModifierType<Offset> OFFSET = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.OFFSET;
public static final PlacementModifierType<Offset> OFFSET = register( /**
"offset", * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#EXTEND} instead
Offset.CODEC */
); @Deprecated(forRemoval = true)
public static final PlacementModifierType<Extend> EXTEND = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.EXTEND;
public static final PlacementModifierType<Extend> EXTEND = register( /**
"extend", * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#ON_EVERY_LAYER} instead
Extend.CODEC */
); @Deprecated(forRemoval = true)
public static final PlacementModifierType<OnEveryLayer> ON_EVERY_LAYER = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.ON_EVERY_LAYER;
public static final PlacementModifierType<OnEveryLayer> ON_EVERY_LAYER = register(
"on_every_layer",
OnEveryLayer.CODEC
);
public static final PlacementModifierType<UnderEveryLayer> UNDER_EVERY_LAYER = register(
"under_every_layer",
UnderEveryLayer.CODEC
);
/**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#UNDER_EVERY_LAYER} instead
*/
@Deprecated(forRemoval = true)
public static final PlacementModifierType<UnderEveryLayer> UNDER_EVERY_LAYER = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.UNDER_EVERY_LAYER;
private static <P extends PlacementModifier> PlacementModifierType<P> register(String path, Codec<P> codec) { private static <P extends PlacementModifier> PlacementModifierType<P> register(String path, Codec<P> codec) {
return register(BCLib.makeID(path), codec); return register(BCLib.makeID(path), codec);
} }
/**
* @param location
* @param codec
* @param <P>
* @return
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#register(ResourceLocation, Codec)} instead
*/
@Deprecated(forRemoval = true)
public static <P extends PlacementModifier> PlacementModifierType<P> register( public static <P extends PlacementModifier> PlacementModifierType<P> register(
ResourceLocation location, ResourceLocation location,
Codec<P> codec Codec<P> codec
) { ) {
return Registry.register(Registry.PLACEMENT_MODIFIERS, location, () -> codec); return org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.register(location, codec);
} }
@Deprecated(forRemoval = true)
public static void ensureStaticInitialization() { public static void ensureStaticInitialization() {
} }

View file

@ -1,345 +1,19 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; 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.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Stream;
public class Stencil extends PlacementModifier {
public static final Codec<Stencil> CODEC;
private static final Boolean[] BN_STENCIL;
private final List<Boolean> stencil;
private static final Stencil DEFAULT;
private static final Stencil DEFAULT4;
private final int selectOneIn;
private static List<Boolean> convert(Boolean[] s) { /**
return Arrays.stream(s).toList(); * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.Stencil} instead
} */
@Deprecated(forRemoval = true)
public class Stencil extends org.betterx.bclib.api.v3.levelgen.features.placement.Stencil {
public Stencil(Boolean[] stencil, int selectOneIn) { public Stencil(Boolean[] stencil, int selectOneIn) {
this(convert(stencil), selectOneIn); super(stencil, selectOneIn);
} }
public Stencil(List<Boolean> stencil, int selectOneIn) { public Stencil(List<Boolean> stencil, int selectOneIn) {
this.stencil = stencil; super(stencil, selectOneIn);
this.selectOneIn = selectOneIn;
}
public static Stencil all() {
return DEFAULT;
}
public static Stencil oneIn4() {
return DEFAULT4;
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
List<BlockPos> pos = new ArrayList<>(16 * 16);
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
if (stencil.get(x << 4 | y)) {
pos.add(blockPos.offset(x, 0, y));
}
}
}
return pos.stream();
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.STENCIL;
}
static {
BN_STENCIL = new Boolean[]{
false,
true,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
true,
false,
false,
true,
true,
true,
false,
false,
false,
true,
true,
false,
false,
false,
true,
false,
false,
true,
true,
true,
false,
false,
true,
true,
true,
true,
false,
true,
true,
true,
true,
false,
false,
false,
true,
true,
false,
false,
true,
true,
true,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true,
true,
false,
false,
false,
true,
true,
true,
true,
false,
false,
false,
true,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
false,
true,
true,
false,
true,
true,
false,
false,
false,
true,
false,
false,
true,
false,
false,
false,
false,
false,
true,
true,
true,
false,
false,
false,
false,
true,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
false,
true,
false,
false,
false,
true,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
false,
true,
true,
false,
false,
true,
false,
false,
false,
true,
true,
true,
true,
true,
true,
false,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
true,
false,
false,
false,
true,
false,
false,
false,
false,
false,
true,
true,
false,
false
};
DEFAULT = new Stencil(BN_STENCIL, 1);
DEFAULT4 = new Stencil(BN_STENCIL, 4);
CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
ExtraCodecs.nonEmptyList(Codec.BOOL.listOf())
.fieldOf("structures")
.orElse(convert(BN_STENCIL))
.forGetter((Stencil a) -> a.stencil),
Codec.INT
.fieldOf("one_in")
.orElse(1)
.forGetter((Stencil a) -> a.selectOneIn)
)
.apply(instance, Stencil::new)
);
} }
} }

View file

@ -1,93 +1,15 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; package org.betterx.bclib.api.v2.levelgen.features.placement;
import org.betterx.bclib.util.BlocksHelper;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.Heightmap;
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.Optional; import java.util.Optional;
import java.util.stream.Stream;
/**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.UnderEveryLayer} instead
*/
@Deprecated(forRemoval = true)
public class UnderEveryLayer public class UnderEveryLayer
extends PlacementModifier { extends org.betterx.bclib.api.v3.levelgen.features.placement.UnderEveryLayer {
private static final UnderEveryLayer INSTANCE = new UnderEveryLayer(Optional.empty(), Optional.empty());
private static final UnderEveryLayer INSTANCE_MIN_4 = new UnderEveryLayer(Optional.of(4), Optional.empty());
public static final Codec<UnderEveryLayer> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
Codec.INT.optionalFieldOf("min").forGetter(o -> o.minHeight),
Codec.INT.optionalFieldOf("max").forGetter(o -> o.maxHeight)
).apply(instance, UnderEveryLayer::new));
protected UnderEveryLayer(Optional<Integer> minHeight, Optional<Integer> maxHeight) {
private final Optional<Integer> minHeight; super(minHeight, maxHeight);
private final Optional<Integer> maxHeight;
private UnderEveryLayer(Optional<Integer> minHeight, Optional<Integer> maxHeight) {
this.minHeight = minHeight;
this.maxHeight = maxHeight;
}
public static UnderEveryLayer simple() {
return INSTANCE;
}
public static UnderEveryLayer min4() {
return INSTANCE_MIN_4;
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext ctx,
RandomSource random,
BlockPos pos
) {
Stream.Builder<BlockPos> builder = Stream.builder();
final int z = pos.getZ();
final int x = pos.getX();
final int levelHeight = ctx.getHeight(Heightmap.Types.MOTION_BLOCKING, x, z);
final int minLevelHeight = ctx.getMinBuildHeight();
int y = maxHeight.map(h -> Math.min(levelHeight, h)).orElse(levelHeight);
final int minHeight = this.minHeight.map(h -> Math.max(minLevelHeight, h)).orElse(minLevelHeight);
int layerY;
do {
layerY = findUnderGroundYPosition(ctx, x, y, z, minHeight);
if (layerY != Integer.MAX_VALUE) {
builder.add(new BlockPos(x, layerY, z));
y = layerY - 1;
}
} while (layerY != Integer.MAX_VALUE);
return builder.build();
}
@Override
public PlacementModifierType<UnderEveryLayer> type() {
return PlacementModifiers.UNDER_EVERY_LAYER;
}
private static int findUnderGroundYPosition(PlacementContext ctx, int x, int startY, int z, int minHeight) {
BlockPos.MutableBlockPos mPos = new BlockPos.MutableBlockPos(x, startY, z);
BlockState nowState = ctx.getBlockState(mPos);
for (int y = startY; y >= minHeight + 1; --y) {
mPos.setY(y - 1);
BlockState belowState = ctx.getBlockState(mPos);
if (BlocksHelper.isTerrain(nowState) && BlocksHelper.isFreeOrFluid(belowState) && !nowState.is(Blocks.BEDROCK)) {
return mPos.getY();
}
nowState = belowState;
}
return Integer.MAX_VALUE;
} }
} }

View file

@ -1,7 +1,5 @@
package org.betterx.bclib.api.v3.levelgen.features; package org.betterx.bclib.api.v3.levelgen.features;
import org.betterx.bclib.api.v2.levelgen.features.UserGrowableFeature;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;

View file

@ -1,8 +1,8 @@
package org.betterx.bclib.api.v3.levelgen.features; package org.betterx.bclib.api.v3.levelgen.features;
import org.betterx.bclib.BCLib; import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.levelgen.features.config.*; import org.betterx.bclib.api.v3.levelgen.features.config.*;
import org.betterx.bclib.api.v2.levelgen.features.features.*; import org.betterx.bclib.api.v3.levelgen.features.features.*;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
@ -11,7 +11,6 @@ import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.RandomFeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@ -21,25 +20,8 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
BCLib.makeID("place_block"), BCLib.makeID("place_block"),
new PlaceBlockFeature<>(PlaceFacingBlockConfig.CODEC) new PlaceBlockFeature<>(PlaceFacingBlockConfig.CODEC)
); );
public static final Feature<ScatterFeatureConfig.OnSolid> SCATTER_ON_SOLID = register(
BCLib.makeID("scatter_on_solid"),
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC)
);
public static final Feature<ScatterFeatureConfig.ExtendTop> SCATTER_EXTEND_TOP = register(
BCLib.makeID("scatter_extend_top"),
new ScatterFeature<>(ScatterFeatureConfig.ExtendTop.CODEC)
);
public static final Feature<ScatterFeatureConfig.ExtendBottom> SCATTER_EXTEND_BOTTOM = register(
BCLib.makeID("scatter_extend_bottom"),
new ScatterFeature<>(ScatterFeatureConfig.ExtendBottom.CODEC)
);
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = register(
BCLib.makeID("random_select"),
new WeightedRandomSelectorFeature()
);
public static final Feature<TemplateFeatureConfig> TEMPLATE = register( public static final Feature<TemplateFeatureConfig> TEMPLATE = register(
BCLib.makeID("template"), BCLib.makeID("template"),
new TemplateFeature( new TemplateFeature(

View file

@ -1,17 +1,17 @@
package org.betterx.bclib.api.v3.levelgen.features; package org.betterx.bclib.api.v3.levelgen.features;
import org.betterx.bclib.BCLib; import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.levelgen.features.config.PillarFeatureConfig;
import org.betterx.bclib.api.v2.levelgen.features.config.PlaceFacingBlockConfig;
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.PlaceBlockFeature;
import org.betterx.bclib.api.v2.levelgen.features.features.SequenceFeature;
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.StructurePlacementType;
import org.betterx.bclib.api.v2.levelgen.structures.StructureWorldNBT; import org.betterx.bclib.api.v2.levelgen.structures.StructureWorldNBT;
import org.betterx.bclib.api.v2.poi.BCLPoiType; import org.betterx.bclib.api.v2.poi.BCLPoiType;
import org.betterx.bclib.api.v3.levelgen.features.config.PillarFeatureConfig;
import org.betterx.bclib.api.v3.levelgen.features.config.PlaceFacingBlockConfig;
import org.betterx.bclib.api.v3.levelgen.features.config.SequenceFeatureConfig;
import org.betterx.bclib.api.v3.levelgen.features.config.TemplateFeatureConfig;
import org.betterx.bclib.api.v3.levelgen.features.features.PillarFeature;
import org.betterx.bclib.api.v3.levelgen.features.features.PlaceBlockFeature;
import org.betterx.bclib.api.v3.levelgen.features.features.SequenceFeature;
import org.betterx.bclib.api.v3.levelgen.features.features.TemplateFeature;
import org.betterx.bclib.blocks.BlockProperties; import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.util.Triple; import org.betterx.bclib.util.Triple;

View file

@ -1,8 +1,8 @@
package org.betterx.bclib.api.v3.levelgen.features; package org.betterx.bclib.api.v3.levelgen.features;
import org.betterx.bclib.api.v2.levelgen.features.config.PlaceFacingBlockConfig; import org.betterx.bclib.api.v3.levelgen.features.blockpredicates.BlockPredicates;
import org.betterx.bclib.api.v2.levelgen.features.placement.*; import org.betterx.bclib.api.v3.levelgen.features.config.PlaceFacingBlockConfig;
import org.betterx.bclib.api.v3.levelgen.features.placement.NoiseFilter; import org.betterx.bclib.api.v3.levelgen.features.placement.*;
import org.betterx.worlds.together.tag.v3.CommonBlockTags; import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@ -74,24 +74,6 @@ abstract class CommonPlacedFeatureBuilder<F extends Feature<FC>, FC extends Feat
return modifier(CountPlacement.of(UniformInt.of(min, max))); return modifier(CountPlacement.of(UniformInt.of(min, max)));
} }
/**
* Generate points in a stencil pattern
*
* @return same {@link CommonPlacedFeatureBuilder} instance.
*/
public T stencil() {
return modifier(Stencil.all());
}
/**
* Generate points in a stencil pattern and selecting (on average) only every 4th
*
* @return same {@link CommonPlacedFeatureBuilder} instance.
*/
public T stencilOneIn4() {
return modifier(Stencil.oneIn4());
}
/** /**
* Generate points for every xz-Coordinate in a chunk. Be carefuller, this is quite expensive! * Generate points for every xz-Coordinate in a chunk. Be carefuller, this is quite expensive!
* *
@ -101,6 +83,15 @@ abstract class CommonPlacedFeatureBuilder<F extends Feature<FC>, FC extends Feat
return modifier(All.simple()); return modifier(All.simple());
} }
public T stencil() {
return modifier(Stencil.all());
}
public T stencilOneIn4() {
return modifier(Stencil.oneIn4());
}
/** /**
* Generate feature in certain iterations (per chunk). * Generate feature in certain iterations (per chunk).
* Feature will be generated on all layers (example - Nether plants). * Feature will be generated on all layers (example - Nether plants).
@ -218,34 +209,6 @@ abstract class CommonPlacedFeatureBuilder<F extends Feature<FC>, FC extends Feat
return modifier(PlacementUtils.FULL_RANGE); return modifier(PlacementUtils.FULL_RANGE);
} }
public T isEmptyAbove4() {
return modifier(IsEmptyAboveSampledFilter.emptyAbove4());
}
public T isEmptyAbove2() {
return modifier(IsEmptyAboveSampledFilter.emptyAbove2());
}
public T isEmptyAbove() {
return modifier(IsEmptyAboveSampledFilter.emptyAbove());
}
public T isEmptyBelow4() {
return modifier(IsEmptyAboveSampledFilter.emptyBelow4());
}
public T isEmptyBelow2() {
return modifier(IsEmptyAboveSampledFilter.emptyBelow2());
}
public T isEmptyBelow() {
return modifier(IsEmptyAboveSampledFilter.emptyBelow());
}
public T isEmptyAbove(int d1, int d2) {
return modifier(new IsEmptyAboveSampledFilter(d1, d2));
}
public T spreadHorizontal(IntProvider p) { public T spreadHorizontal(IntProvider p) {
return modifier(RandomOffsetPlacement.horizontal(p)); return modifier(RandomOffsetPlacement.horizontal(p));
} }
@ -309,15 +272,6 @@ abstract class CommonPlacedFeatureBuilder<F extends Feature<FC>, FC extends Feat
return modifier(FindSolidInDirection.up(distance)); return modifier(FindSolidInDirection.up(distance));
} }
public T hasMinimumDownwardSpace() {
return modifier(MinEmptyFilter.down());
}
public T hasMinimumUpwardSpace() {
return modifier(MinEmptyFilter.up());
}
/** /**
* Cast a ray with max {@code distance} length to find the next solid Block. The ray will travel through replaceable * Cast a ray with max {@code distance} length to find the next solid Block. The ray will travel through replaceable
* Blocks (see {@link Material#isReplaceable()}) and will be accepted if it hits a block with the * Blocks (see {@link Material#isReplaceable()}) and will be accepted if it hits a block with the

View file

@ -1,6 +1,15 @@
package org.betterx.bclib.api.v3.levelgen.features; package org.betterx.bclib.api.v3.levelgen.features;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
public interface UserGrowableFeature<FC extends FeatureConfiguration> extends org.betterx.bclib.api.v2.levelgen.features.UserGrowableFeature<FC> { public interface UserGrowableFeature<FC extends FeatureConfiguration> {
boolean grow(
ServerLevelAccessor level,
BlockPos pos,
RandomSource random,
FC configuration
);
} }

View file

@ -1,10 +1,15 @@
package org.betterx.bclib.api.v3.levelgen.features; package org.betterx.bclib.api.v3.levelgen.features.blockpredicates;
import org.betterx.bclib.BCLib;
import org.betterx.worlds.together.tag.v3.CommonBlockTags; import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import com.mojang.serialization.Codec;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags; import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate; import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicateType;
import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.material.Fluids;
public class BlockPredicates { public class BlockPredicates {
@ -24,4 +29,16 @@ public class BlockPredicates {
BlockPredicate.matchesTag(CommonBlockTags.TERRAIN), BlockPredicate.matchesTag(CommonBlockTags.TERRAIN),
BlockPredicate.matchesFluids(Fluids.LAVA) BlockPredicate.matchesFluids(Fluids.LAVA)
); );
public static final BlockPredicateType<IsFullShape> FULL_SHAPE = register(
BCLib.makeID("full_shape"),
IsFullShape.CODEC
);
public static <P extends BlockPredicate> BlockPredicateType<P> register(ResourceLocation location, Codec<P> codec) {
return Registry.register(Registry.BLOCK_PREDICATE_TYPES, location, () -> codec);
}
public static void ensureStaticInitialization() {
}
} }

View file

@ -1,4 +1,4 @@
package org.betterx.bclib.api.v2.levelgen.features.blockpredicates; package org.betterx.bclib.api.v3.levelgen.features.blockpredicates;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
@ -30,7 +30,7 @@ public class IsFullShape implements BlockPredicate {
public BlockPredicateType<IsFullShape> type() { public BlockPredicateType<IsFullShape> type() {
return Types.FULL_SHAPE; return BlockPredicates.FULL_SHAPE;
} }
@Override @Override

View file

@ -0,0 +1,70 @@
package org.betterx.bclib.api.v3.levelgen.features.config;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.PlacementFilter;
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import java.util.Optional;
import org.jetbrains.annotations.NotNull;
public class ConditionFeatureConfig implements FeatureConfiguration {
public static final Codec<ConditionFeatureConfig> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
PlacementModifier.CODEC.fieldOf("filter").forGetter(p -> p.filter),
PlacedFeature.CODEC.fieldOf("filter_pass").forGetter(p -> p.okFeature),
PlacedFeature.CODEC.optionalFieldOf("filter_fail").forGetter(p -> p.failFeature)
).apply(instance, ConditionFeatureConfig::new)
);
public final PlacementModifier filter;
public final Holder<PlacedFeature> okFeature;
public final Optional<Holder<PlacedFeature>> failFeature;
public ConditionFeatureConfig(
@NotNull PlacementFilter filter,
@NotNull BCLFeature okFeature
) {
this(filter, okFeature.getPlacedFeature(), Optional.empty());
}
public ConditionFeatureConfig(
@NotNull PlacementFilter filter,
@NotNull BCLFeature okFeature,
@NotNull BCLFeature failFeature
) {
this(filter, okFeature.getPlacedFeature(), Optional.of(failFeature.getPlacedFeature()));
}
public ConditionFeatureConfig(
@NotNull PlacementFilter filter,
@NotNull Holder<PlacedFeature> okFeature
) {
this(filter, okFeature, Optional.empty());
}
public ConditionFeatureConfig(
@NotNull PlacementFilter filter,
@NotNull Holder<PlacedFeature> okFeature,
@NotNull Holder<PlacedFeature> failFeature
) {
this(filter, okFeature, Optional.of(failFeature));
}
protected ConditionFeatureConfig(
@NotNull PlacementModifier filter,
@NotNull Holder<PlacedFeature> okFeature,
@NotNull Optional<Holder<PlacedFeature>> failFeature
) {
this.filter = filter;
this.okFeature = okFeature;
this.failFeature = failFeature;
}
}

View file

@ -1,4 +1,4 @@
package org.betterx.bclib.api.v2.levelgen.features.config; package org.betterx.bclib.api.v3.levelgen.features.config;
import org.betterx.bclib.blocks.BlockProperties; import org.betterx.bclib.blocks.BlockProperties;

View file

@ -0,0 +1,78 @@
package org.betterx.bclib.api.v3.levelgen.features.config;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.util.random.SimpleWeightedRandomList;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import net.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider;
import java.util.List;
public abstract class PlaceBlockFeatureConfig implements FeatureConfiguration {
protected static <T extends PlaceBlockFeatureConfig> RecordCodecBuilder<T, BlockStateProvider> blockStateCodec() {
return BlockStateProvider.CODEC
.fieldOf("entries")
.forGetter((T o) -> o.stateProvider);
}
protected final BlockStateProvider stateProvider;
protected static SimpleWeightedRandomList<BlockState> buildWeightedList(List<BlockState> states) {
var builder = SimpleWeightedRandomList.<BlockState>builder();
for (BlockState s : states) builder.add(s, 1);
return builder.build();
}
protected static SimpleWeightedRandomList<BlockState> buildWeightedList(BlockState state) {
return SimpleWeightedRandomList
.<BlockState>builder()
.add(state, 1)
.build();
}
public PlaceBlockFeatureConfig(Block block) {
this(block.defaultBlockState());
}
public PlaceBlockFeatureConfig(BlockState state) {
this(BlockStateProvider.simple(state));
}
public PlaceBlockFeatureConfig(List<BlockState> states) {
this(buildWeightedList(states));
}
public PlaceBlockFeatureConfig(SimpleWeightedRandomList<BlockState> blocks) {
this.stateProvider = new WeightedStateProvider(blocks);
}
public PlaceBlockFeatureConfig(BlockStateProvider blocks) {
this.stateProvider = blocks;
}
public BlockState getRandomBlock(RandomSource random, BlockPos pos) {
return this.stateProvider.getState(random, pos);
}
public boolean place(FeaturePlaceContext<? extends PlaceBlockFeatureConfig> ctx) {
BlockState state = getRandomBlock(ctx.random(), ctx.origin());
return placeBlock(ctx, ctx.level(), ctx.origin(), state);
}
protected abstract boolean placeBlock(
FeaturePlaceContext<? extends PlaceBlockFeatureConfig> ctx,
WorldGenLevel level,
BlockPos pos,
BlockState targetState
);
}

View file

@ -0,0 +1,92 @@
package org.betterx.bclib.api.v3.levelgen.features.config;
import org.betterx.bclib.util.BlocksHelper;
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.ExtraCodecs;
import net.minecraft.util.random.SimpleWeightedRandomList;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import net.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider;
import java.util.List;
public class PlaceFacingBlockConfig extends PlaceBlockFeatureConfig {
public static final Codec<PlaceFacingBlockConfig> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
blockStateCodec(),
ExtraCodecs.nonEmptyList(Direction.CODEC.listOf())
.fieldOf("dir")
.orElse(List.of(Direction.NORTH))
.forGetter(a -> a.directions)
).apply(instance, PlaceFacingBlockConfig::new)
);
public static final List<Direction> HORIZONTAL = List.of(
Direction.NORTH,
Direction.EAST,
Direction.WEST,
Direction.SOUTH
);
public static final List<Direction> VERTICAL = List.of(Direction.UP, Direction.DOWN);
public static final List<Direction> ALL = List.of(
Direction.NORTH,
Direction.EAST,
Direction.SOUTH,
Direction.WEST,
Direction.UP,
Direction.DOWN
);
private final List<Direction> directions;
public PlaceFacingBlockConfig(Block block, List<Direction> dir) {
this(block.defaultBlockState(), dir);
}
public PlaceFacingBlockConfig(BlockState state, List<Direction> dir) {
this(BlockStateProvider.simple(state), dir);
}
public PlaceFacingBlockConfig(List<BlockState> states, List<Direction> dir) {
this(buildWeightedList(states), dir);
}
public PlaceFacingBlockConfig(SimpleWeightedRandomList<BlockState> blocks, List<Direction> dir) {
this(new WeightedStateProvider(blocks), dir);
}
public PlaceFacingBlockConfig(BlockStateProvider blocks, List<Direction> dir) {
super(blocks);
directions = dir;
}
@Override
public boolean placeBlock(
FeaturePlaceContext<? extends PlaceBlockFeatureConfig> ctx,
WorldGenLevel level,
BlockPos pos,
BlockState targetState
) {
BlockState lookupState;
BlockPos testPos;
for (Direction dir : directions) {
testPos = pos.relative(dir.getOpposite());
lookupState = targetState.setValue(HorizontalDirectionalBlock.FACING, dir);
if (lookupState.canSurvive(level, testPos) && level.getBlockState(testPos).isAir()) {
BlocksHelper.setWithoutUpdate(level, testPos, lookupState);
//BlocksHelper.setWithoutUpdate(level, pos, level.getBlockState(pos.relative(dir.getOpposite())));
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,46 @@
package org.betterx.bclib.api.v3.levelgen.features.config;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import java.util.List;
public class SequenceFeatureConfig implements FeatureConfiguration {
public static final Codec<SequenceFeatureConfig> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
ExtraCodecs.nonEmptyList(PlacedFeature.CODEC.listOf())
.fieldOf("features")
.forGetter(a -> a.features)
).apply(instance, SequenceFeatureConfig::new)
);
private final List<Holder<PlacedFeature>> features;
public static SequenceFeatureConfig create(List<BCLFeature<?, ?>> features) {
return new SequenceFeatureConfig(features.stream().map(f -> f.getPlacedFeature()).toList());
}
public static SequenceFeatureConfig createSequence(List<org.betterx.bclib.api.v3.levelgen.features.BCLFeature<?, ?>> features) {
return new SequenceFeatureConfig(features.stream().map(f -> f.getPlacedFeature()).toList());
}
public SequenceFeatureConfig(List<Holder<PlacedFeature>> features) {
this.features = features;
}
public boolean placeAll(FeaturePlaceContext<SequenceFeatureConfig> ctx) {
boolean placed = false;
for (Holder<PlacedFeature> f : features) {
placed |= f.value().place(ctx.level(), ctx.chunkGenerator(), ctx.random(), ctx.origin());
}
return placed;
}
}

View file

@ -0,0 +1,42 @@
package org.betterx.bclib.api.v3.levelgen.features.config;
import org.betterx.bclib.api.v2.levelgen.structures.StructurePlacementType;
import org.betterx.bclib.api.v2.levelgen.structures.StructureWorldNBT;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import java.util.List;
public class TemplateFeatureConfig implements FeatureConfiguration {
public static final Codec<TemplateFeatureConfig> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
ExtraCodecs.nonEmptyList(StructureWorldNBT.CODEC.listOf())
.fieldOf("structures")
.forGetter((TemplateFeatureConfig cfg) -> cfg.structures)
)
.apply(instance, TemplateFeatureConfig::new)
);
public final List<StructureWorldNBT> structures;
public static StructureWorldNBT cfg(
ResourceLocation location,
int offsetY,
StructurePlacementType type,
float chance
) {
return StructureWorldNBT.create(location, offsetY, type, chance);
}
public TemplateFeatureConfig(ResourceLocation location, int offsetY, StructurePlacementType type) {
this(List.of(cfg(location, offsetY, type, 1.0f)));
}
public TemplateFeatureConfig(List<StructureWorldNBT> structures) {
this.structures = structures;
}
}

View file

@ -0,0 +1,38 @@
package org.betterx.bclib.api.v3.levelgen.features.features;
import org.betterx.bclib.api.v3.levelgen.features.config.ConditionFeatureConfig;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.PlacementContext;
import java.util.Optional;
import java.util.stream.Stream;
public class ConditionFeature extends Feature<ConditionFeatureConfig> {
public ConditionFeature() {
super(ConditionFeatureConfig.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<ConditionFeatureConfig> ctx) {
final ConditionFeatureConfig cfg = ctx.config();
final WorldGenLevel level = ctx.level();
final RandomSource random = ctx.random();
final BlockPos pos = ctx.origin();
final PlacementContext c = new PlacementContext(level, ctx.chunkGenerator(), Optional.empty());
Stream<BlockPos> stream = cfg.filter.getPositions(c, ctx.random(), pos);
Holder<PlacedFeature> state = (stream.findFirst().isPresent() ? cfg.okFeature : cfg.failFeature.orElse(null));
if (state != null) {
return state.value().place(level, ctx.chunkGenerator(), random, pos);
}
return false;
}
}

View file

@ -0,0 +1,20 @@
package org.betterx.bclib.api.v3.levelgen.features.features;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
public class MarkPostProcessingFeature extends Feature<NoneFeatureConfiguration> {
public MarkPostProcessingFeature() {
super(NoneFeatureConfiguration.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> ctx) {
BlockPos pos = ctx.origin();
ctx.level().getChunk(pos.getX() >> 4, pos.getZ() >> 4)
.markPosForPostprocessing(new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15));
return true;
}
}

View file

@ -1,6 +1,6 @@
package org.betterx.bclib.api.v2.levelgen.features.features; package org.betterx.bclib.api.v3.levelgen.features.features;
import org.betterx.bclib.api.v2.levelgen.features.config.PillarFeatureConfig; import org.betterx.bclib.api.v3.levelgen.features.config.PillarFeatureConfig;
import org.betterx.bclib.util.BlocksHelper; import org.betterx.bclib.util.BlocksHelper;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;

View file

@ -0,0 +1,18 @@
package org.betterx.bclib.api.v3.levelgen.features.features;
import org.betterx.bclib.api.v3.levelgen.features.config.PlaceBlockFeatureConfig;
import com.mojang.serialization.Codec;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
public class PlaceBlockFeature<FC extends PlaceBlockFeatureConfig> extends Feature<FC> {
public PlaceBlockFeature(Codec<FC> codec) {
super(codec);
}
@Override
public boolean place(FeaturePlaceContext<FC> ctx) {
return ctx.config().place(ctx);
}
}

View file

@ -0,0 +1,17 @@
package org.betterx.bclib.api.v3.levelgen.features.features;
import org.betterx.bclib.api.v3.levelgen.features.config.SequenceFeatureConfig;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
public class SequenceFeature extends Feature<SequenceFeatureConfig> {
public SequenceFeature() {
super(SequenceFeatureConfig.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<SequenceFeatureConfig> featurePlaceContext) {
return featurePlaceContext.config().placeAll(featurePlaceContext);
}
}

View file

@ -0,0 +1,87 @@
package org.betterx.bclib.api.v3.levelgen.features.features;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeatureBuilder;
import org.betterx.bclib.api.v2.levelgen.structures.StructureNBT;
import org.betterx.bclib.api.v2.levelgen.structures.StructureWorldNBT;
import org.betterx.bclib.api.v3.levelgen.features.config.TemplateFeatureConfig;
import com.mojang.serialization.Codec;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
public class TemplateFeature<FC extends TemplateFeatureConfig> extends Feature<FC> {
public static <T extends TemplateFeatureConfig> BCLFeature createAndRegisterRare(
ResourceLocation location,
TemplateFeatureConfig configuration,
int onceEveryChunk
) {
return BCLFeatureBuilder
.start(location, org.betterx.bclib.api.v3.levelgen.features.BCLFeature.TEMPLATE)
.decoration(GenerationStep.Decoration.SURFACE_STRUCTURES)
.onceEvery(onceEveryChunk) //discard neighboring chunks
.count(16) //try 16 placements in chunk
.squarePlacement() //randomize x/z in chunk
.randomHeight10FromFloorCeil() //randomize height 10 above and 10 below max vertical
.findSolidFloor(12) //cast downward ray to find solid surface
.isEmptyAbove4() //make sure we have 4 free blocks above
.onlyInBiome() //ensure that we still are in the correct biome
.buildAndRegister(configuration);
}
public static <T extends TemplateFeatureConfig> BCLFeature createAndRegister(
ResourceLocation location,
TemplateFeatureConfig configuration,
int count
) {
return BCLFeatureBuilder
.start(location, org.betterx.bclib.api.v3.levelgen.features.BCLFeature.TEMPLATE)
.decoration(GenerationStep.Decoration.SURFACE_STRUCTURES)
.count(count)
.squarePlacement()
.randomHeight10FromFloorCeil()
.findSolidFloor(12) //cast downward ray to find solid surface
.isEmptyAbove4()
.onlyInBiome()
.buildAndRegister(configuration);
}
public TemplateFeature(Codec<FC> codec) {
super(codec);
}
protected StructureWorldNBT randomStructure(TemplateFeatureConfig cfg, RandomSource random) {
if (cfg.structures.size() > 1) {
final float chanceSum = cfg.structures.parallelStream().map(c -> c.chance).reduce(0.0f, (p, c) -> p + c);
float rnd = random.nextFloat() * chanceSum;
for (StructureWorldNBT c : cfg.structures) {
rnd -= c.chance;
if (rnd <= 0) return c;
}
} else {
return cfg.structures.get(0);
}
return null;
}
@Override
public boolean place(FeaturePlaceContext<FC> ctx) {
StructureWorldNBT structure = randomStructure(ctx.config(), ctx.random());
return structure.generateIfPlaceable(
ctx.level(),
ctx.origin(),
StructureNBT.getRandomRotation(ctx.random()),
StructureNBT.getRandomMirror(ctx.random())
);
}
}

View file

@ -0,0 +1,34 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPos;
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.stream.IntStream;
import java.util.stream.Stream;
public class All extends PlacementModifier {
private static final All INSTANCE = new All();
public static final Codec<All> CODEC = Codec.unit(All::new);
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
return IntStream.range(0, 16 * 16 - 1).mapToObj(i -> blockPos.offset(i & 0xF, 0, i >> 4));
}
public static PlacementModifier simple() {
return INSTANCE;
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.ALL;
}
}

View file

@ -0,0 +1,29 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPos;
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.stream.Stream;
public class Debug extends PlacementModifier {
public static final Debug INSTANCE = new Debug();
public static final Codec<Debug> CODEC = Codec.unit(Debug::new);
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
return Stream.of(blockPos);
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.DEBUG;
}
}

View file

@ -0,0 +1,57 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
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.valueproviders.IntProvider;
import net.minecraft.util.valueproviders.UniformInt;
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.stream.Stream;
public class Extend extends PlacementModifier {
public static final Codec<Extend> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
Direction.CODEC
.fieldOf("direction")
.orElse(Direction.DOWN)
.forGetter(cfg -> cfg.direction),
IntProvider.codec(0, 16)
.fieldOf("length")
.orElse(UniformInt.of(0, 3))
.forGetter(cfg -> cfg.length)
)
.apply(instance, Extend::new));
private final Direction direction;
private final IntProvider length;
public Extend(Direction direction, IntProvider length) {
this.direction = direction;
this.length = length;
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource random,
BlockPos blockPos
) {
var builder = Stream.<BlockPos>builder();
final int count = length.sample(random);
builder.add(blockPos);
for (int y = 1; y < count + 1; y++) {
builder.add(blockPos.relative(direction, y));
}
return builder.build();
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.EXTEND;
}
}

View file

@ -0,0 +1,134 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
import org.betterx.bclib.util.BlocksHelper;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.SectionPos;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.RandomSource;
import net.minecraft.util.valueproviders.IntProvider;
import net.minecraft.util.valueproviders.UniformInt;
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 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),
Codec.BOOL.fieldOf("random:select").orElse(true).forGetter(p -> p.randomSelect)
)
.apply(
instance,
FindSolidInDirection::new
));
protected static final FindSolidInDirection DOWN = new FindSolidInDirection(Direction.DOWN, 6);
protected static final FindSolidInDirection UP = new FindSolidInDirection(Direction.UP, 6);
private final List<Direction> direction;
private final int maxSearchDistance;
private final boolean randomSelect;
private final IntProvider provider;
public FindSolidInDirection(Direction direction, int maxSearchDistance) {
this(List.of(direction), maxSearchDistance, false);
}
public FindSolidInDirection(List<Direction> direction, int maxSearchDistance) {
this(direction, maxSearchDistance, direction.size() > 1);
}
public FindSolidInDirection(List<Direction> direction, int maxSearchDistance, boolean randomSelect) {
this.direction = direction;
this.maxSearchDistance = maxSearchDistance;
this.provider = UniformInt.of(0, direction.size() - 1);
this.randomSelect = randomSelect;
}
public static PlacementModifier down() {
return DOWN;
}
public static PlacementModifier up() {
return UP;
}
public static PlacementModifier down(int dist) {
if (dist == DOWN.maxSearchDistance) return DOWN;
return new FindSolidInDirection(Direction.DOWN, dist);
}
public static PlacementModifier up(int dist) {
if (dist == UP.maxSearchDistance) return UP;
return new FindSolidInDirection(Direction.UP, dist);
}
public Direction randomDirection(RandomSource random) {
return direction.get(provider.sample(random));
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
var builder = Stream.<BlockPos>builder();
if (randomSelect) {
submitSingle(placementContext, blockPos, builder, randomDirection(randomSource));
} else {
for (Direction d : direction) {
submitSingle(placementContext, blockPos, builder, d);
}
}
return builder.build();
}
private void submitSingle(
PlacementContext placementContext,
BlockPos blockPos,
Stream.Builder<BlockPos> builder,
Direction d
) {
int searchDist;
BlockPos.MutableBlockPos POS = blockPos.mutable();
if (d == Direction.EAST) { //+x
searchDist = Math.min(maxSearchDistance, 15 - SectionPos.sectionRelative(blockPos.getX()));
} else if (d == Direction.WEST) { //-x
searchDist = Math.min(maxSearchDistance, SectionPos.sectionRelative(blockPos.getX()));
} else if (d == Direction.SOUTH) { //+z
searchDist = Math.min(maxSearchDistance, 15 - SectionPos.sectionRelative(blockPos.getZ()));
} else if (d == Direction.NORTH) { //-z
searchDist = Math.min(maxSearchDistance, SectionPos.sectionRelative(blockPos.getZ()));
} else {
searchDist = maxSearchDistance;
}
if (BlocksHelper.findOnSurroundingSurface(
placementContext.getLevel(),
POS,
d,
searchDist,
BlocksHelper::isTerrain
)) {
builder.add(POS);
}
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.SOLID_IN_DIR;
}
}

View file

@ -0,0 +1,47 @@
package org.betterx.bclib.api.v3.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;
}
}

View file

@ -0,0 +1,59 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
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;
public class Is extends PlacementFilter {
public static final Codec<Is> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
BlockPredicate.CODEC
.fieldOf("predicate")
.forGetter(cfg -> cfg.predicate),
Vec3i.CODEC
.optionalFieldOf("offset")
.forGetter(cfg -> cfg.offset)
)
.apply(instance, Is::new));
private final BlockPredicate predicate;
private final Optional<Vec3i> offset;
public Is(BlockPredicate predicate, Optional<Vec3i> offset) {
this.predicate = predicate;
this.offset = offset;
}
public static Is simple(BlockPredicate predicate) {
return new Is(predicate, Optional.empty());
}
public static Is below(BlockPredicate predicate) {
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();
return predicate.test(level, offset.map(v -> pos.offset(v.getX(), v.getY(), v.getZ())).orElse(pos));
}
@Override
public PlacementModifierType<Is> type() {
return PlacementModifiers.IS;
}
}

View file

@ -0,0 +1,64 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
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;
public class IsBasin extends PlacementFilter {
public static final Codec<IsBasin> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
BlockPredicate.CODEC
.fieldOf("predicate")
.forGetter(cfg -> cfg.predicate),
BlockPredicate.CODEC
.optionalFieldOf("top_predicate")
.orElse(Optional.empty())
.forGetter(cfg -> cfg.topPredicate)
)
.apply(instance, IsBasin::new));
private final BlockPredicate predicate;
private final Optional<BlockPredicate> topPredicate;
public IsBasin(BlockPredicate predicate) {
this(predicate, Optional.empty());
}
public IsBasin(BlockPredicate predicate, Optional<BlockPredicate> topPredicate) {
this.predicate = predicate;
this.topPredicate = topPredicate;
}
public static PlacementFilter simple(BlockPredicate predicate) {
return new IsBasin(predicate);
}
public static IsBasin openTop(BlockPredicate predicate) {
return new IsBasin(predicate, Optional.of(BlockPredicate.ONLY_IN_AIR_PREDICATE));
}
@Override
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
WorldGenLevel level = ctx.getLevel();
if (topPredicate.isPresent() && !topPredicate.get().test(level, pos.above())) return false;
return predicate.test(level, pos.below())
&& 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_BASIN;
}
}

View file

@ -1,4 +1,4 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; package org.betterx.bclib.api.v3.levelgen.features.placement;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;

View file

@ -1,6 +1,5 @@
package org.betterx.bclib.api.v3.levelgen.features.placement; package org.betterx.bclib.api.v3.levelgen.features.placement;
import org.betterx.bclib.api.v2.levelgen.features.placement.PlacementModifiers;
import org.betterx.bclib.noise.Noises; import org.betterx.bclib.noise.Noises;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;

View file

@ -0,0 +1,56 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
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 com.google.common.collect.Maps;
import java.util.Map;
import java.util.stream.Stream;
public class Offset extends PlacementModifier {
private static final Map<Direction, Offset> DIRECTIONS = Maps.newHashMap();
public static final Codec<Offset> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
Vec3i.CODEC
.fieldOf("blocks")
.forGetter(cfg -> cfg.offset)
)
.apply(instance, Offset::new));
private final Vec3i offset;
public Offset(Vec3i offset) {
this.offset = offset;
}
public static Offset inDirection(Direction dir) {
return DIRECTIONS.get(dir);
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
return Stream.of(blockPos.offset(offset));
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.OFFSET;
}
static {
for (Direction d : Direction.values())
DIRECTIONS.put(d, new Offset(d.getNormal()));
}
}

View file

@ -0,0 +1,93 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
import org.betterx.bclib.util.BlocksHelper;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.Heightmap;
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.Optional;
import java.util.stream.Stream;
public class OnEveryLayer
extends PlacementModifier {
private static final OnEveryLayer INSTANCE = new OnEveryLayer(Optional.empty(), Optional.empty());
private static final OnEveryLayer INSTANCE_MIN_4 = new OnEveryLayer(Optional.of(4), Optional.empty());
public static final Codec<OnEveryLayer> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
Codec.INT.optionalFieldOf("min").forGetter(o -> o.minHeight),
Codec.INT.optionalFieldOf("max").forGetter(o -> o.maxHeight)
).apply(instance, OnEveryLayer::new));
private final Optional<Integer> minHeight;
private final Optional<Integer> maxHeight;
protected OnEveryLayer(Optional<Integer> minHeight, Optional<Integer> maxHeight) {
this.minHeight = minHeight;
this.maxHeight = maxHeight;
}
public static OnEveryLayer simple() {
return INSTANCE;
}
public static OnEveryLayer min4() {
return INSTANCE_MIN_4;
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext ctx,
RandomSource random,
BlockPos pos
) {
Stream.Builder<BlockPos> builder = Stream.builder();
final int z = pos.getZ();
final int x = pos.getX();
final int levelHeight = ctx.getHeight(Heightmap.Types.MOTION_BLOCKING, x, z);
final int minLevelHeight = ctx.getMinBuildHeight();
int y = maxHeight.map(h -> Math.min(levelHeight, h)).orElse(levelHeight);
final int minHeight = this.minHeight.map(h -> Math.max(minLevelHeight, h)).orElse(minLevelHeight);
int layerY;
do {
layerY = OnEveryLayer.findOnGroundYPosition(ctx, x, y, z, minHeight);
if (layerY != Integer.MAX_VALUE) {
builder.add(new BlockPos(x, layerY, z));
y = layerY - 1;
}
} while (layerY != Integer.MAX_VALUE);
return builder.build();
}
@Override
public PlacementModifierType<OnEveryLayer> type() {
return PlacementModifiers.ON_EVERY_LAYER;
}
private static int findOnGroundYPosition(PlacementContext ctx, int x, int startY, int z, int minHeight) {
BlockPos.MutableBlockPos mPos = new BlockPos.MutableBlockPos(x, startY, z);
BlockState nowState = ctx.getBlockState(mPos);
for (int y = startY; y >= minHeight + 1; --y) {
mPos.setY(y - 1);
BlockState belowState = ctx.getBlockState(mPos);
if (BlocksHelper.isTerrain(belowState) && BlocksHelper.isFreeOrFluid(nowState) && !belowState.is(Blocks.BEDROCK)) {
return mPos.getY() + 1;
}
nowState = belowState;
}
return Integer.MAX_VALUE;
}
}

View file

@ -0,0 +1,90 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
import org.betterx.bclib.BCLib;
import com.mojang.serialization.Codec;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
public class PlacementModifiers {
public static final PlacementModifierType<Stencil> STENCIL = register(
"stencil",
Stencil.CODEC
);
public static final PlacementModifierType<IsNextTo> IS_NEXT_TO = register(
"is_next_to",
IsNextTo.CODEC
);
public static final PlacementModifierType<NoiseFilter> NOISE_FILTER = register(
"noise_filter",
NoiseFilter.CODEC
);
public static final PlacementModifierType<Debug> DEBUG = register(
"debug",
Debug.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
);
public static final PlacementModifierType<All> ALL = register(
"all",
All.CODEC
);
public static final PlacementModifierType<IsBasin> IS_BASIN = register(
"is_basin",
IsBasin.CODEC
);
public static final PlacementModifierType<Is> IS = register(
"is",
Is.CODEC
);
public static final PlacementModifierType<Offset> OFFSET = register(
"offset",
Offset.CODEC
);
public static final PlacementModifierType<Extend> EXTEND = register(
"extend",
Extend.CODEC
);
public static final PlacementModifierType<OnEveryLayer> ON_EVERY_LAYER = register(
"on_every_layer",
OnEveryLayer.CODEC
);
public static final PlacementModifierType<UnderEveryLayer> UNDER_EVERY_LAYER = register(
"under_every_layer",
UnderEveryLayer.CODEC
);
private static <P extends PlacementModifier> PlacementModifierType<P> register(String path, Codec<P> codec) {
return register(BCLib.makeID(path), codec);
}
public static <P extends PlacementModifier> PlacementModifierType<P> register(
ResourceLocation location,
Codec<P> codec
) {
return Registry.register(Registry.PLACEMENT_MODIFIERS, location, () -> codec);
}
public static void ensureStaticInitialization() {
}
}

View file

@ -0,0 +1,345 @@
package org.betterx.bclib.api.v3.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.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Stencil extends PlacementModifier {
public static final Codec<Stencil> CODEC;
private static final Boolean[] BN_STENCIL;
private final List<Boolean> stencil;
private static final Stencil DEFAULT;
private static final Stencil DEFAULT4;
private final int selectOneIn;
private static List<Boolean> convert(Boolean[] s) {
return Arrays.stream(s).toList();
}
public Stencil(Boolean[] stencil, int selectOneIn) {
this(convert(stencil), selectOneIn);
}
public Stencil(List<Boolean> stencil, int selectOneIn) {
this.stencil = stencil;
this.selectOneIn = selectOneIn;
}
public static Stencil all() {
return DEFAULT;
}
public static Stencil oneIn4() {
return DEFAULT4;
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
List<BlockPos> pos = new ArrayList<>(16 * 16);
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
if (stencil.get(x << 4 | y)) {
pos.add(blockPos.offset(x, 0, y));
}
}
}
return pos.stream();
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.STENCIL;
}
static {
BN_STENCIL = new Boolean[]{
false,
true,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
true,
false,
false,
true,
true,
true,
false,
false,
false,
true,
true,
false,
false,
false,
true,
false,
false,
true,
true,
true,
false,
false,
true,
true,
true,
true,
false,
true,
true,
true,
true,
false,
false,
false,
true,
true,
false,
false,
true,
true,
true,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true,
true,
false,
false,
false,
true,
true,
true,
true,
false,
false,
false,
true,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
false,
true,
true,
false,
true,
true,
false,
false,
false,
true,
false,
false,
true,
false,
false,
false,
false,
false,
true,
true,
true,
false,
false,
false,
false,
true,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
false,
true,
false,
false,
false,
true,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
false,
true,
true,
false,
false,
true,
false,
false,
false,
true,
true,
true,
true,
true,
true,
false,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true,
true,
false,
false,
false,
true,
false,
false,
false,
false,
false,
true,
true,
false,
false
};
DEFAULT = new Stencil(BN_STENCIL, 1);
DEFAULT4 = new Stencil(BN_STENCIL, 4);
CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
ExtraCodecs.nonEmptyList(Codec.BOOL.listOf())
.fieldOf("structures")
.orElse(convert(BN_STENCIL))
.forGetter((Stencil a) -> a.stencil),
Codec.INT
.fieldOf("one_in")
.orElse(1)
.forGetter((Stencil a) -> a.selectOneIn)
)
.apply(instance, Stencil::new)
);
}
}

View file

@ -0,0 +1,93 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
import org.betterx.bclib.util.BlocksHelper;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.Heightmap;
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.Optional;
import java.util.stream.Stream;
public class UnderEveryLayer
extends PlacementModifier {
private static final UnderEveryLayer INSTANCE = new UnderEveryLayer(Optional.empty(), Optional.empty());
private static final UnderEveryLayer INSTANCE_MIN_4 = new UnderEveryLayer(Optional.of(4), Optional.empty());
public static final Codec<UnderEveryLayer> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
Codec.INT.optionalFieldOf("min").forGetter(o -> o.minHeight),
Codec.INT.optionalFieldOf("max").forGetter(o -> o.maxHeight)
).apply(instance, UnderEveryLayer::new));
private final Optional<Integer> minHeight;
private final Optional<Integer> maxHeight;
protected UnderEveryLayer(Optional<Integer> minHeight, Optional<Integer> maxHeight) {
this.minHeight = minHeight;
this.maxHeight = maxHeight;
}
public static UnderEveryLayer simple() {
return INSTANCE;
}
public static UnderEveryLayer min4() {
return INSTANCE_MIN_4;
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext ctx,
RandomSource random,
BlockPos pos
) {
Stream.Builder<BlockPos> builder = Stream.builder();
final int z = pos.getZ();
final int x = pos.getX();
final int levelHeight = ctx.getHeight(Heightmap.Types.MOTION_BLOCKING, x, z);
final int minLevelHeight = ctx.getMinBuildHeight();
int y = maxHeight.map(h -> Math.min(levelHeight, h)).orElse(levelHeight);
final int minHeight = this.minHeight.map(h -> Math.max(minLevelHeight, h)).orElse(minLevelHeight);
int layerY;
do {
layerY = findUnderGroundYPosition(ctx, x, y, z, minHeight);
if (layerY != Integer.MAX_VALUE) {
builder.add(new BlockPos(x, layerY, z));
y = layerY - 1;
}
} while (layerY != Integer.MAX_VALUE);
return builder.build();
}
@Override
public PlacementModifierType<UnderEveryLayer> type() {
return PlacementModifiers.UNDER_EVERY_LAYER;
}
private static int findUnderGroundYPosition(PlacementContext ctx, int x, int startY, int z, int minHeight) {
BlockPos.MutableBlockPos mPos = new BlockPos.MutableBlockPos(x, startY, z);
BlockState nowState = ctx.getBlockState(mPos);
for (int y = startY; y >= minHeight + 1; --y) {
mPos.setY(y - 1);
BlockState belowState = ctx.getBlockState(mPos);
if (BlocksHelper.isTerrain(nowState) && BlocksHelper.isFreeOrFluid(belowState) && !nowState.is(Blocks.BEDROCK)) {
return mPos.getY();
}
nowState = belowState;
}
return Integer.MAX_VALUE;
}
}