diff --git a/src/main/java/org/betterx/bclib/BCLib.java b/src/main/java/org/betterx/bclib/BCLib.java index 3e943d32..dbf56276 100644 --- a/src/main/java/org/betterx/bclib/BCLib.java +++ b/src/main/java/org/betterx/bclib/BCLib.java @@ -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.BCLBiomeBuilder; 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.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.config.Configs; import org.betterx.bclib.recipes.AnvilRecipe; @@ -42,7 +42,7 @@ public class BCLib implements ModInitializer { public void onInitialize() { LevelGenEvents.register(); WorldsTogether.onInitialize(); - Types.ensureStaticInitialization(); + BlockPredicates.ensureStaticInitialization(); BaseRegistry.register(); GeneratorOptions.init(); BaseBlockEntities.register(); diff --git a/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java b/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java index f045199c..e61257f5 100644 --- a/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java +++ b/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java @@ -17,6 +17,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.BiomeTags; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.Climate; @@ -135,11 +136,9 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourc private static boolean isValidNetherBiome(Holder biome, ResourceLocation location) { - return biome.unwrapKey().get().location().toString().contains("upside_down"); - -// return NetherBiomes.canGenerateInNether(biome.unwrapKey().get()) || -// biome.is(BiomeTags.IS_NETHER) || -// BiomeAPI.wasRegisteredAsNetherBiome(location); + return NetherBiomes.canGenerateInNether(biome.unwrapKey().get()) || + biome.is(BiomeTags.IS_NETHER) || + BiomeAPI.wasRegisteredAsNetherBiome(location); } private static boolean isValidNonVanillaNetherBiome(Holder biome, ResourceLocation location) { diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeature.java index ee6d5be9..2632905c 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeature.java @@ -1,8 +1,16 @@ 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.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.Holder; @@ -40,26 +48,31 @@ public class BCLFeature, FC extends FeatureConfiguration> */ @Deprecated(forRemoval = true) public static final Feature 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) - public static final Feature SCATTER_ON_SOLID = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_ON_SOLID; - /** - * @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#SCATTER_EXTEND_TOP} - */ + public static final Feature SCATTER_ON_SOLID = register( + BCLib.makeID("scatter_on_solid"), + new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC) + ); + @Deprecated(forRemoval = true) - public static final Feature SCATTER_EXTEND_TOP = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_EXTEND_TOP; - /** - * @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#SCATTER_EXTEND_BOTTOM} - */ + public static final Feature SCATTER_EXTEND_TOP = register( + BCLib.makeID("scatter_extend_top"), + new ScatterFeature<>(ScatterFeatureConfig.ExtendTop.CODEC) + ); + @Deprecated(forRemoval = true) - public static final Feature SCATTER_EXTEND_BOTTOM = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_EXTEND_BOTTOM; - /** - * @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#RANDOM_SELECTOR} - */ + public static final Feature SCATTER_EXTEND_BOTTOM = register( + BCLib.makeID("scatter_extend_bottom"), + new ScatterFeature<>(ScatterFeatureConfig.ExtendBottom.CODEC) + ); + @Deprecated(forRemoval = true) - public static final Feature RANDOM_SELECTOR = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.RANDOM_SELECTOR; + public static final Feature RANDOM_SELECTOR = register( + BCLib.makeID("random_select"), + new WeightedRandomSelectorFeature() + ); + /** * @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#TEMPLATE} */ diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeatureBuilder.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeatureBuilder.java index de130886..7bee7006 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeatureBuilder.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeatureBuilder.java @@ -1,6 +1,9 @@ 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 net.minecraft.core.Direction; diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/FastFeatures.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/FastFeatures.java index fe97cb83..dd994fed 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/FastFeatures.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/FastFeatures.java @@ -1,257 +1,255 @@ package org.betterx.bclib.api.v2.levelgen.features; -import org.betterx.bclib.api.v2.levelgen.features.config.PlaceFacingBlockConfig; -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; - +@Deprecated(forRemoval = true) public class FastFeatures { - public static RandomPatchConfiguration grassPatch(BlockStateProvider stateProvider, int tries) { - return FeatureUtils.simpleRandomPatchConfiguration( - tries, - PlacementUtils.onlyWhenEmpty(Feature.SIMPLE_BLOCK, new SimpleBlockConfiguration(stateProvider)) - ); - } - - - public static BCLFeature, ScatterFeatureConfig.OnSolid> vine( - ResourceLocation location, - boolean onFloor, - boolean sparse, - ScatterFeatureConfig.Builder builder - ) { - return scatter(location, onFloor, sparse, builder, - org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_ON_SOLID - ); - } - - public static BCLFeature scatter( - ResourceLocation location, - boolean onFloor, - boolean sparse, - ScatterFeatureConfig.Builder builder, - Feature scatterFeature - ) { - BCLFeatureBuilder fBuilder = BCLFeatureBuilder.start(location, scatterFeature); - if (onFloor) { - fBuilder.findSolidFloor(3).isEmptyAbove2(); - builder.onFloor(); - } else { - fBuilder.findSolidCeil(3).isEmptyBelow2(); - builder.onCeil(); - } - if (sparse) { - fBuilder.onceEvery(3); - } - - 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); - } - - public static BCLFeature - patch(ResourceLocation location, Block block, int attempts, int xzSpread, int ySpread) { - return patch( - location, - attempts, - xzSpread, - ySpread, - Feature.SIMPLE_BLOCK, - new SimpleBlockConfiguration(BlockStateProvider.simple(block)) - ); - } - - public static BCLFeature - patch(ResourceLocation location, BlockStateProvider provider, int attempts, int xzSpread, int ySpread) { - return patch( - location, - attempts, - xzSpread, - ySpread, - Feature.SIMPLE_BLOCK, - new SimpleBlockConfiguration(provider) - ); - } - - public static BCLFeature patchWitRandomInt(ResourceLocation location, Block block, IntegerProperty prop) { - return patchWitRandomInt(location, block, prop, 96, 7, 3); - } - - public static BCLFeature - patchWitRandomInt( - ResourceLocation location, - Block block, - IntegerProperty prop, - int attempts, - int xzSpread, - int ySpread - ) { - return patch( - location, - attempts, - xzSpread, - ySpread, - simple(location, ySpread, false, block.defaultBlockState(), prop) - ); - } - - public static BCLFeature - simple( - ResourceLocation location, - int searchDist, - boolean rare, - Feature feature - ) { - return simple(location, searchDist, rare, feature, NoneFeatureConfiguration.NONE); - } - - public static BCLFeature - single(ResourceLocation location, Block block) { - return single(location, BlockStateProvider.simple(block)); - - } - - public static BCLFeature - single(ResourceLocation location, BlockStateProvider provider) { - return BCLFeatureBuilder - .start(location, provider) - .buildAndRegister(); - } - - public static BCLFeature - simple(ResourceLocation location, Feature feature) { - return BCLFeatureBuilder - .start(location, feature) - .buildAndRegister(); - } - - public static BCLFeature - simple( - ResourceLocation location, - int searchDist, - boolean rare, - BlockState baseState, - IntegerProperty property - ) { - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - - for (Integer i : property.getPossibleValues()) { - if (i < min) min = i; - if (i > max) max = i; - } - - return simple( - location, - searchDist, - rare, - Feature.SIMPLE_BLOCK, - new SimpleBlockConfiguration(new RandomizedIntStateProvider( - BlockStateProvider.simple(baseState), - property, - UniformInt.of(min, max) - )) - ); - } - - - public static BCLFeature, FC> - simple( - ResourceLocation location, - int searchDist, - boolean rare, - Feature feature, - FC config - ) { - BCLFeatureBuilder builder = BCLFeatureBuilder - .start(location, feature) - .findSolidFloor(Math.min(12, searchDist)) - .is(BlockPredicate.ONLY_IN_AIR_PREDICATE); - if (rare) { - builder.onceEvery(4); - } - return builder.buildAndRegister(config); - } - - public static BCLFeature - patch(ResourceLocation location, Feature feature) { - return patch(location, 96, 7, 3, feature, FeatureConfiguration.NONE); - } - - - public static BCLFeature - patch( - ResourceLocation location, - int attempts, - int xzSpread, - int ySpread, - Feature feature - ) { - return patch(location, attempts, xzSpread, ySpread, feature, FeatureConfiguration.NONE); - } - - - public static BCLFeature - patch( - ResourceLocation location, - int attempts, - int xzSpread, - int ySpread, - Feature feature, - FC config - ) { - final BCLFeature SINGLE = simple(location, ySpread, false, feature, config); - return patch(location, attempts, xzSpread, ySpread, SINGLE); - } - - public static BCLFeature - wallPatch( - ResourceLocation location, - Block block, - int attempts, - int xzSpread, - int ySpread - ) { - final BCLFeature SINGLE = simple(location, ySpread, false, - org.betterx.bclib.api.v3.levelgen.features.BCLFeature.PLACE_BLOCK, - new PlaceFacingBlockConfig(block, PlaceFacingBlockConfig.HORIZONTAL) - ); - return patch(location, attempts, xzSpread, ySpread, SINGLE); - } - - 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())); - } - +// @Deprecated(forRemoval = true) +// public static RandomPatchConfiguration grassPatch(BlockStateProvider stateProvider, int tries) { +// return FeatureUtils.simpleRandomPatchConfiguration( +// tries, +// PlacementUtils.onlyWhenEmpty(Feature.SIMPLE_BLOCK, new SimpleBlockConfiguration(stateProvider)) +// ); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature, ScatterFeatureConfig.OnSolid> vine( +// ResourceLocation location, +// boolean onFloor, +// boolean sparse, +// ScatterFeatureConfig.Builder builder +// ) { +// return scatter(location, onFloor, sparse, builder, +// org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_ON_SOLID +// ); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature scatter( +// ResourceLocation location, +// boolean onFloor, +// boolean sparse, +// ScatterFeatureConfig.Builder builder, +// Feature scatterFeature +// ) { +// BCLFeatureBuilder fBuilder = BCLFeatureBuilder.start(location, scatterFeature); +// if (onFloor) { +// fBuilder.findSolidFloor(3).isEmptyAbove2(); +// builder.onFloor(); +// } else { +// fBuilder.findSolidCeil(3).isEmptyBelow2(); +// builder.onCeil(); +// } +// if (sparse) { +// fBuilder.onceEvery(3); +// } +// +// return fBuilder +// .is(BlockPredicate.ONLY_IN_AIR_PREDICATE) +// .buildAndRegister(builder.build()); +// } +// +// @Deprecated(forRemoval = true) +// 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, int attempts, int xzSpread, int ySpread) { +// return patch( +// location, +// attempts, +// xzSpread, +// ySpread, +// Feature.SIMPLE_BLOCK, +// new SimpleBlockConfiguration(BlockStateProvider.simple(block)) +// ); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature +// patch(ResourceLocation location, BlockStateProvider provider, int attempts, int xzSpread, int ySpread) { +// return patch( +// location, +// attempts, +// xzSpread, +// ySpread, +// Feature.SIMPLE_BLOCK, +// new SimpleBlockConfiguration(provider) +// ); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature patchWitRandomInt(ResourceLocation location, Block block, IntegerProperty prop) { +// return patchWitRandomInt(location, block, prop, 96, 7, 3); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature +// patchWitRandomInt( +// ResourceLocation location, +// Block block, +// IntegerProperty prop, +// int attempts, +// int xzSpread, +// int ySpread +// ) { +// return patch( +// location, +// attempts, +// xzSpread, +// ySpread, +// simple(location, ySpread, false, block.defaultBlockState(), prop) +// ); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature +// simple( +// ResourceLocation location, +// int searchDist, +// boolean rare, +// Feature feature +// ) { +// return simple(location, searchDist, rare, feature, NoneFeatureConfiguration.NONE); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature +// single(ResourceLocation location, Block block) { +// return single(location, BlockStateProvider.simple(block)); +// +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature +// single(ResourceLocation location, BlockStateProvider provider) { +// return BCLFeatureBuilder +// .start(location, provider) +// .buildAndRegister(); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature +// simple(ResourceLocation location, Feature feature) { +// return BCLFeatureBuilder +// .start(location, feature) +// .buildAndRegister(); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature +// simple( +// ResourceLocation location, +// int searchDist, +// boolean rare, +// BlockState baseState, +// IntegerProperty property +// ) { +// int min = Integer.MAX_VALUE; +// int max = Integer.MIN_VALUE; +// +// for (Integer i : property.getPossibleValues()) { +// if (i < min) min = i; +// if (i > max) max = i; +// } +// +// return simple( +// location, +// searchDist, +// rare, +// Feature.SIMPLE_BLOCK, +// new SimpleBlockConfiguration(new RandomizedIntStateProvider( +// BlockStateProvider.simple(baseState), +// property, +// UniformInt.of(min, max) +// )) +// ); +// } +// +// @Deprecated(forRemoval = true) +// +// public static BCLFeature, FC> +// simple( +// ResourceLocation location, +// int searchDist, +// boolean rare, +// Feature feature, +// FC config +// ) { +// BCLFeatureBuilder builder = BCLFeatureBuilder +// .start(location, feature) +// .findSolidFloor(Math.min(12, searchDist)) +// .is(BlockPredicate.ONLY_IN_AIR_PREDICATE); +// if (rare) { +// builder.onceEvery(4); +// } +// return builder.buildAndRegister(config); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature +// patch(ResourceLocation location, Feature feature) { +// return patch(location, 96, 7, 3, feature, FeatureConfiguration.NONE); +// } +// +// +// @Deprecated(forRemoval = true) +// public static BCLFeature +// patch( +// ResourceLocation location, +// int attempts, +// int xzSpread, +// int ySpread, +// Feature feature +// ) { +// return patch(location, attempts, xzSpread, ySpread, feature, FeatureConfiguration.NONE); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature +// patch( +// ResourceLocation location, +// int attempts, +// int xzSpread, +// int ySpread, +// Feature feature, +// FC config +// ) { +// final BCLFeature SINGLE = simple(location, ySpread, false, feature, config); +// return patch(location, attempts, xzSpread, ySpread, SINGLE); +// } +// +// @Deprecated(forRemoval = true) +// public static BCLFeature +// wallPatch( +// ResourceLocation location, +// Block block, +// int attempts, +// int xzSpread, +// int ySpread +// ) { +// final BCLFeature SINGLE = simple(location, ySpread, false, +// org.betterx.bclib.api.v3.levelgen.features.BCLFeature.PLACE_BLOCK, +// new PlaceFacingBlockConfig(block, PlaceFacingBlockConfig.HORIZONTAL) +// ); +// 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())); +// } +// } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/UserGrowableFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/UserGrowableFeature.java index 21450edd..0935ab8d 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/UserGrowableFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/UserGrowableFeature.java @@ -1,15 +1,11 @@ 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; -public interface UserGrowableFeature { - boolean grow( - ServerLevelAccessor level, - BlockPos pos, - RandomSource random, - FC configuration - ); +/** + * @param + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.UserGrowableFeature} instead + */ +@Deprecated(forRemoval = true) +public interface UserGrowableFeature extends org.betterx.bclib.api.v3.levelgen.features.UserGrowableFeature { } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/blockpredicates/Types.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/blockpredicates/Types.java index 2899d137..c4f3f704 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/blockpredicates/Types.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/blockpredicates/Types.java @@ -1,21 +1,34 @@ 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 net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate; 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 static final BlockPredicateType FULL_SHAPE = register( - BCLib.makeID("full_shape"), - IsFullShape.CODEC - ); + /** + * @deprecated Please use {@link BlockPredicates#FULL_SHAPE} instead + */ + @Deprecated(forRemoval = true) + public static final BlockPredicateType FULL_SHAPE = BlockPredicates.FULL_SHAPE; + /** + * @param location + * @param codec + * @param

+ * @return + * @deprecated Please use {@link BlockPredicates#register(ResourceLocation, Codec)} instead + */ + @Deprecated(forRemoval = true) public static

BlockPredicateType

register(ResourceLocation location, Codec

codec) { - return Registry.register(Registry.BLOCK_PREDICATE_TYPES, location, () -> codec); + return BlockPredicates.register(location, codec); } public static void ensureStaticInitialization() { diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/ConditionFeatureConfig.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/ConditionFeatureConfig.java index 1eba834d..1161cb3a 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/ConditionFeatureConfig.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/ConditionFeatureConfig.java @@ -2,10 +2,7 @@ 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.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; @@ -13,25 +10,14 @@ 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 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 okFeature; - public final Optional> failFeature; - - public ConditionFeatureConfig( - @NotNull PlacementFilter filter, - @NotNull BCLFeature okFeature - ) { - this(filter, okFeature.getPlacedFeature(), Optional.empty()); +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.config.ConditionFeatureConfig} instead + */ +@Deprecated(forRemoval = true) +public class ConditionFeatureConfig extends org.betterx.bclib.api.v3.levelgen.features.config.ConditionFeatureConfig { + public ConditionFeatureConfig(@NotNull PlacementFilter filter, @NotNull BCLFeature okFeature) { + super(filter, okFeature); } public ConditionFeatureConfig( @@ -39,15 +25,11 @@ public class ConditionFeatureConfig implements FeatureConfiguration { @NotNull BCLFeature okFeature, @NotNull BCLFeature failFeature ) { - this(filter, okFeature.getPlacedFeature(), Optional.of(failFeature.getPlacedFeature())); + super(filter, okFeature, failFeature); } - public ConditionFeatureConfig( - @NotNull PlacementFilter filter, - @NotNull Holder okFeature - ) { - this(filter, okFeature, Optional.empty()); - + public ConditionFeatureConfig(@NotNull PlacementFilter filter, @NotNull Holder okFeature) { + super(filter, okFeature); } public ConditionFeatureConfig( @@ -55,7 +37,7 @@ public class ConditionFeatureConfig implements FeatureConfiguration { @NotNull Holder okFeature, @NotNull Holder failFeature ) { - this(filter, okFeature, Optional.of(failFeature)); + super(filter, okFeature, failFeature); } protected ConditionFeatureConfig( @@ -63,8 +45,6 @@ public class ConditionFeatureConfig implements FeatureConfiguration { @NotNull Holder okFeature, @NotNull Optional> failFeature ) { - this.filter = filter; - this.okFeature = okFeature; - this.failFeature = failFeature; + super(filter, okFeature, failFeature); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PlaceBlockFeatureConfig.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PlaceBlockFeatureConfig.java index fb77bf37..8593750f 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PlaceBlockFeatureConfig.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PlaceBlockFeatureConfig.java @@ -1,78 +1,32 @@ 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.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 RecordCodecBuilder blockStateCodec() { - return BlockStateProvider.CODEC - .fieldOf("entries") - .forGetter((T o) -> o.stateProvider); - } - - protected final BlockStateProvider stateProvider; - - - protected static SimpleWeightedRandomList buildWeightedList(List states) { - var builder = SimpleWeightedRandomList.builder(); - for (BlockState s : states) builder.add(s, 1); - return builder.build(); - } - - protected static SimpleWeightedRandomList buildWeightedList(BlockState state) { - return SimpleWeightedRandomList - .builder() - .add(state, 1) - .build(); - } +@Deprecated(forRemoval = true) +public abstract class PlaceBlockFeatureConfig extends org.betterx.bclib.api.v3.levelgen.features.config.PlaceBlockFeatureConfig { public PlaceBlockFeatureConfig(Block block) { - this(block.defaultBlockState()); + super(block); } public PlaceBlockFeatureConfig(BlockState state) { - this(BlockStateProvider.simple(state)); + super(state); } - public PlaceBlockFeatureConfig(List states) { - this(buildWeightedList(states)); + super(states); } public PlaceBlockFeatureConfig(SimpleWeightedRandomList blocks) { - this.stateProvider = new WeightedStateProvider(blocks); + super(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 ctx) { - BlockState state = getRandomBlock(ctx.random(), ctx.origin()); - return placeBlock(ctx, ctx.level(), ctx.origin(), state); - } - - - protected abstract boolean placeBlock( - FeaturePlaceContext ctx, - WorldGenLevel level, - BlockPos pos, - BlockState targetState - ); } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PlaceFacingBlockConfig.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PlaceFacingBlockConfig.java index be57714f..d4790e59 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PlaceFacingBlockConfig.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PlaceFacingBlockConfig.java @@ -1,92 +1,37 @@ 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.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 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 HORIZONTAL = List.of( - Direction.NORTH, - Direction.EAST, - Direction.WEST, - Direction.SOUTH - ); - public static final List VERTICAL = List.of(Direction.UP, Direction.DOWN); - public static final List ALL = List.of( - Direction.NORTH, - Direction.EAST, - Direction.SOUTH, - Direction.WEST, - Direction.UP, - Direction.DOWN - ); - private final List 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 dir) { - this(block.defaultBlockState(), dir); + super(block, dir); } public PlaceFacingBlockConfig(BlockState state, List dir) { - this(BlockStateProvider.simple(state), dir); + super(state, dir); } public PlaceFacingBlockConfig(List states, List dir) { - this(buildWeightedList(states), dir); + super(states, dir); } public PlaceFacingBlockConfig(SimpleWeightedRandomList blocks, List dir) { - this(new WeightedStateProvider(blocks), dir); + super(blocks, dir); } public PlaceFacingBlockConfig(BlockStateProvider blocks, List dir) { - super(blocks); - directions = dir; - } - - @Override - - public boolean placeBlock( - FeaturePlaceContext 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; + super(blocks, dir); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/SequenceFeatureConfig.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/SequenceFeatureConfig.java index 4479e9db..6487cd77 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/SequenceFeatureConfig.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/SequenceFeatureConfig.java @@ -1,46 +1,17 @@ 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.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 CODEC = RecordCodecBuilder.create(instance -> - instance.group( - ExtraCodecs.nonEmptyList(PlacedFeature.CODEC.listOf()) - .fieldOf("features") - .forGetter(a -> a.features) - ).apply(instance, SequenceFeatureConfig::new) - ); - - private final List> features; - - public static SequenceFeatureConfig create(List> features) { - return new SequenceFeatureConfig(features.stream().map(f -> f.getPlacedFeature()).toList()); - } - - public static SequenceFeatureConfig createSequence(List> features) { - return new SequenceFeatureConfig(features.stream().map(f -> f.getPlacedFeature()).toList()); - } +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.config.SequenceFeatureConfig instead} + */ +@Deprecated(forRemoval = true) +public class SequenceFeatureConfig extends org.betterx.bclib.api.v3.levelgen.features.config.SequenceFeatureConfig { public SequenceFeatureConfig(List> features) { - this.features = features; - } - - public boolean placeAll(FeaturePlaceContext ctx) { - boolean placed = false; - for (Holder f : features) { - placed |= f.value().place(ctx.level(), ctx.chunkGenerator(), ctx.random(), ctx.origin()); - } - return placed; - + super(features); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/TemplateFeatureConfig.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/TemplateFeatureConfig.java index 6786fd65..2a434388 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/TemplateFeatureConfig.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/TemplateFeatureConfig.java @@ -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.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 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 structures; - - public static StructureWorldNBT cfg( - ResourceLocation location, - int offsetY, - StructurePlacementType type, - float chance - ) { - return StructureWorldNBT.create(location, offsetY, type, chance); - } +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.config.TemplateFeatureConfig} instead + */ +public class TemplateFeatureConfig extends org.betterx.bclib.api.v3.levelgen.features.config.TemplateFeatureConfig { public TemplateFeatureConfig(ResourceLocation location, int offsetY, StructurePlacementType type) { - this(List.of(cfg(location, offsetY, type, 1.0f))); + super(location, offsetY, type); } public TemplateFeatureConfig(List structures) { - this.structures = structures; + super(structures); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/ConditionFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/ConditionFeature.java index 5e6132f1..cefc2c70 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/ConditionFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/ConditionFeature.java @@ -1,38 +1,8 @@ package org.betterx.bclib.api.v2.levelgen.features.features; -import org.betterx.bclib.api.v2.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 { - public ConditionFeature() { - super(ConditionFeatureConfig.CODEC); - } - - @Override - public boolean place(FeaturePlaceContext 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 stream = cfg.filter.getPositions(c, ctx.random(), pos); - Holder state = (stream.findFirst().isPresent() ? cfg.okFeature : cfg.failFeature.orElse(null)); - if (state != null) { - return state.value().place(level, ctx.chunkGenerator(), random, pos); - } - return false; - } +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.features.ConditionFeature} instead. + */ +@Deprecated(forRemoval = true) +public class ConditionFeature extends org.betterx.bclib.api.v3.levelgen.features.features.ConditionFeature { } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/MarkPostProcessingFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/MarkPostProcessingFeature.java index 6a423fb0..182c32c0 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/MarkPostProcessingFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/MarkPostProcessingFeature.java @@ -1,20 +1,8 @@ package org.betterx.bclib.api.v2.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 { - public MarkPostProcessingFeature() { - super(NoneFeatureConfiguration.CODEC); - } - - @Override - public boolean place(FeaturePlaceContext 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; - } +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.features.MarkPostProcessingFeature} instead. + */ +@Deprecated(forRemoval = true) +public class MarkPostProcessingFeature extends org.betterx.bclib.api.v3.levelgen.features.features.MarkPostProcessingFeature { } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/PlaceBlockFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/PlaceBlockFeature.java index 2b5c3897..a7073933 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/PlaceBlockFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/PlaceBlockFeature.java @@ -1,18 +1,16 @@ 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 net.minecraft.world.level.levelgen.feature.Feature; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -public class PlaceBlockFeature extends Feature { +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.features.PlaceBlockFeature} instead. + */ +@Deprecated(forRemoval = true) +public class PlaceBlockFeature extends org.betterx.bclib.api.v3.levelgen.features.features.PlaceBlockFeature { + public PlaceBlockFeature(Codec codec) { super(codec); } - - @Override - public boolean place(FeaturePlaceContext ctx) { - return ctx.config().place(ctx); - } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/ScatterFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/ScatterFeature.java index 3c4dbb34..016ece3f 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/ScatterFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/ScatterFeature.java @@ -1,7 +1,7 @@ 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.v3.levelgen.features.UserGrowableFeature; import org.betterx.bclib.util.BlocksHelper; import com.mojang.serialization.Codec; @@ -17,6 +17,7 @@ import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; import java.util.Optional; +@Deprecated(forRemoval = true) public class ScatterFeature extends Feature implements UserGrowableFeature { diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/SequenceFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/SequenceFeature.java index 131c0a08..908062aa 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/SequenceFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/SequenceFeature.java @@ -1,17 +1,9 @@ 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 { - public SequenceFeature() { - super(SequenceFeatureConfig.CODEC); - } - - @Override - public boolean place(FeaturePlaceContext featurePlaceContext) { - return featurePlaceContext.config().placeAll(featurePlaceContext); - } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/SurfaceFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/SurfaceFeature.java index 622ff224..df6117b0 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/SurfaceFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/SurfaceFeature.java @@ -12,6 +12,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConf import java.util.Optional; +@Deprecated(forRemoval = true) public abstract class SurfaceFeature extends Feature { public static abstract class DefaultConfiguration extends SurfaceFeature { protected DefaultConfiguration() { diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/TemplateFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/TemplateFeature.java index 14d7a25a..e7a86062 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/TemplateFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/TemplateFeature.java @@ -1,87 +1,16 @@ package org.betterx.bclib.api.v2.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.features.config.TemplateFeatureConfig; -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 extends Feature { - - public static 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 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); - } +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.features.TemplateFeature} instead. + */ +@Deprecated(forRemoval = true) +public class TemplateFeature extends org.betterx.bclib.api.v3.levelgen.features.features.TemplateFeature { public TemplateFeature(Codec 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 ctx) { - StructureWorldNBT structure = randomStructure(ctx.config(), ctx.random()); - return structure.generateIfPlaceable( - ctx.level(), - ctx.origin(), - StructureNBT.getRandomRotation(ctx.random()), - StructureNBT.getRandomMirror(ctx.random()) - ); - } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/WeightedRandomSelectorFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/WeightedRandomSelectorFeature.java index efa8117e..74aa362e 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/WeightedRandomSelectorFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/WeightedRandomSelectorFeature.java @@ -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.placement.PlacedFeature; + +@Deprecated(forRemoval = true) public class WeightedRandomSelectorFeature extends Feature { public WeightedRandomSelectorFeature() { super(RandomFeatureConfiguration.CODEC); diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/All.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/All.java index f577218e..0d89537d 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/All.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/All.java @@ -1,34 +1,9 @@ package org.betterx.bclib.api.v2.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; +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.All} instead. + */ +@Deprecated(forRemoval = true) +public class All extends org.betterx.bclib.api.v3.levelgen.features.placement.All { -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 CODEC = Codec.unit(All::new); - - @Override - public Stream 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; - } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Debug.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Debug.java index 12819c30..d81a8c52 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Debug.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Debug.java @@ -1,29 +1,9 @@ package org.betterx.bclib.api.v2.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; +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.Debug} instead. + */ +@Deprecated(forRemoval = true) +public class Debug extends org.betterx.bclib.api.v3.levelgen.features.placement.Debug { -import java.util.stream.Stream; - -public class Debug extends PlacementModifier { - public static final Debug INSTANCE = new Debug(); - public static final Codec CODEC = Codec.unit(Debug::new); - - @Override - public Stream getPositions( - PlacementContext placementContext, - RandomSource randomSource, - BlockPos blockPos - ) { - return Stream.of(blockPos); - } - - @Override - public PlacementModifierType type() { - return PlacementModifiers.DEBUG; - } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Extend.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Extend.java index 92e1c337..c431d980 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Extend.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Extend.java @@ -1,57 +1,14 @@ 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.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 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) { - this.direction = direction; - this.length = length; - } - - @Override - public Stream getPositions( - PlacementContext placementContext, - RandomSource random, - BlockPos blockPos - ) { - var builder = Stream.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; + super(direction, length); } } \ No newline at end of file diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/FindSolidInDirection.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/FindSolidInDirection.java index 266aba20..a7b88032 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/FindSolidInDirection.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/FindSolidInDirection.java @@ -1,134 +1,25 @@ 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.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 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; - private final int maxSearchDistance; - - private final boolean randomSelect; - private final IntProvider provider; +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.FindSolidInDirection} instead. + */ +@Deprecated(forRemoval = true) +public class FindSolidInDirection extends org.betterx.bclib.api.v3.levelgen.features.placement.FindSolidInDirection { public FindSolidInDirection(Direction direction, int maxSearchDistance) { - this(List.of(direction), maxSearchDistance, false); + super(direction, maxSearchDistance); } public FindSolidInDirection(List direction, int maxSearchDistance) { - this(direction, maxSearchDistance, direction.size() > 1); + super(direction, maxSearchDistance); } public FindSolidInDirection(List 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 getPositions( - PlacementContext placementContext, - RandomSource randomSource, - BlockPos blockPos - ) { - var builder = Stream.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 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; + super(direction, maxSearchDistance, randomSelect); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/ForAll.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/ForAll.java index a6ec9b17..5f6ac277 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/ForAll.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/ForAll.java @@ -1,47 +1,16 @@ package org.betterx.bclib.api.v2.levelgen.features.placement; -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.core.BlockPos; -import net.minecraft.util.ExtraCodecs; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.levelgen.placement.PlacementContext; import net.minecraft.world.level.levelgen.placement.PlacementModifier; -import net.minecraft.world.level.levelgen.placement.PlacementModifierType; import java.util.List; -import java.util.stream.Stream; -public class ForAll extends PlacementModifier { - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance - .group( - ExtraCodecs.nonEmptyList(PlacementModifier.CODEC.listOf()) - .fieldOf("modifiers") - .forGetter(a -> a.modifiers) - ) - .apply(instance, ForAll::new)); - - private final List modifiers; +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.ForAll} instead. + */ +@Deprecated(forRemoval = true) +public class ForAll extends org.betterx.bclib.api.v3.levelgen.features.placement.ForAll { public ForAll(List modifiers) { - this.modifiers = modifiers; - } - - @Override - public Stream getPositions( - PlacementContext placementContext, - RandomSource randomSource, - BlockPos blockPos - ) { - Stream.Builder 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; + super(modifiers); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Is.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Is.java index 0ef4af06..360dadf2 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Is.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Is.java @@ -1,59 +1,17 @@ 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.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 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 offset; +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.Is} instead. + */ +@Deprecated(forRemoval = true) +public class Is extends org.betterx.bclib.api.v3.levelgen.features.placement.Is { public Is(BlockPredicate predicate, Optional 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 type() { - return PlacementModifiers.IS; + super(predicate, offset); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/IsBasin.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/IsBasin.java index e0334a8c..c96d3506 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/IsBasin.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/IsBasin.java @@ -1,64 +1,21 @@ 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.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 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 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) { - this(predicate, Optional.empty()); + super(predicate); } public IsBasin(BlockPredicate predicate, Optional 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; + super(predicate, topPredicate); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/IsEmptyAboveSampledFilter.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/IsEmptyAboveSampledFilter.java index 30dfc369..d1f587b0 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/IsEmptyAboveSampledFilter.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/IsEmptyAboveSampledFilter.java @@ -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 */ +@Deprecated(forRemoval = true) public class IsEmptyAboveSampledFilter extends PlacementFilter { private static final IsEmptyAboveSampledFilter DEFAULT = new IsEmptyAboveSampledFilter(4, 2); private static final IsEmptyAboveSampledFilter DEFAULT1 = new IsEmptyAboveSampledFilter(1, 1); diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/MinEmptyFilter.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/MinEmptyFilter.java index 1134e892..51d5cc87 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/MinEmptyFilter.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/MinEmptyFilter.java @@ -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.PlacementModifierType; +@Deprecated(forRemoval = true) public class MinEmptyFilter extends PlacementFilter { private static final MinEmptyFilter DOWN = new MinEmptyFilter(Direction.DOWN, 2); private static final MinEmptyFilter UP = new MinEmptyFilter(Direction.UP, 2); diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Offset.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Offset.java index 2f9e6b39..388515c2 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Offset.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Offset.java @@ -1,56 +1,14 @@ 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.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 DIRECTIONS = Maps.newHashMap(); - public static final Codec CODEC = RecordCodecBuilder.create((instance) -> instance - .group( - Vec3i.CODEC - .fieldOf("blocks") - .forGetter(cfg -> cfg.offset) - ) - .apply(instance, Offset::new)); - - private final Vec3i offset; +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.Offset} instead. + */ +@Deprecated(forRemoval = true) +public class Offset extends org.betterx.bclib.api.v3.levelgen.features.placement.Offset { public Offset(Vec3i offset) { - this.offset = offset; - } - - public static Offset inDirection(Direction dir) { - return DIRECTIONS.get(dir); - } - - @Override - public Stream 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())); + super(offset); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/OnEveryLayer.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/OnEveryLayer.java index f4572213..b4d89677 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/OnEveryLayer.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/OnEveryLayer.java @@ -1,93 +1,14 @@ 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.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 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)); +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.OnEveryLayer} instead + */ +@Deprecated(forRemoval = true) +public class OnEveryLayer extends org.betterx.bclib.api.v3.levelgen.features.placement.OnEveryLayer { - - private final Optional minHeight; - private final Optional maxHeight; - - private OnEveryLayer(Optional minHeight, Optional maxHeight) { - this.minHeight = minHeight; - - this.maxHeight = maxHeight; - } - - public static OnEveryLayer simple() { - return INSTANCE; - } - - public static OnEveryLayer min4() { - return INSTANCE_MIN_4; - } - - @Override - public Stream getPositions( - PlacementContext ctx, - RandomSource random, - BlockPos pos - ) { - - Stream.Builder 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 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; + protected OnEveryLayer(Optional minHeight, Optional maxHeight) { + super(minHeight, maxHeight); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/PlacementModifiers.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/PlacementModifiers.java index 8690d211..7977cfbd 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/PlacementModifiers.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/PlacementModifiers.java @@ -1,23 +1,40 @@ package org.betterx.bclib.api.v2.levelgen.features.placement; 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 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; +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers} instead + */ +@Deprecated(forRemoval = true) public class PlacementModifiers { - public static final PlacementModifierType NOISE_FILTER = register( - "noise_filter", - NoiseFilter.CODEC - ); - public static final PlacementModifierType DEBUG = register( - "debug", - Debug.CODEC - ); + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#NOISE_FILTER} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType NOISE_FILTER = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.NOISE_FILTER; + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#DEBUG} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType DEBUG = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.DEBUG; + @Deprecated(forRemoval = true) public static final PlacementModifierType IS_EMPTY_ABOVE_SAMPLED_FILTER = register( "is_empty_above_sampled_filter", IsEmptyAboveSampledFilter.CODEC @@ -28,73 +45,87 @@ public class PlacementModifiers { MinEmptyFilter.CODEC ); - public static final PlacementModifierType FOR_ALL = register( - "for_all", - ForAll.CODEC - ); + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#FOR_ALL} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType FOR_ALL = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.FOR_ALL; - public static final PlacementModifierType SOLID_IN_DIR = register( - "solid_in_dir", - FindSolidInDirection.CODEC - ); + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#SOLID_IN_DIR} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType SOLID_IN_DIR = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.SOLID_IN_DIR; - public static final PlacementModifierType STENCIL = register( - "stencil", - Stencil.CODEC - ); + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#STENCIL} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType STENCIL = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.STENCIL; - public static final PlacementModifierType ALL = register( - "all", - All.CODEC - ); + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#ALL} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType ALL = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.ALL; - public static final PlacementModifierType IS_BASIN = register( - "is_basin", - IsBasin.CODEC - ); + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#IS_BASIN} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType IS_BASIN = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.IS_BASIN; - public static final PlacementModifierType IS_NEXT_TO = register( - "is_next_to", - IsNextTo.CODEC - ); + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#IS} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType IS = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.IS; - public static final PlacementModifierType IS = register( - "is", - Is.CODEC - ); + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#OFFSET} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType OFFSET = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.OFFSET; - public static final PlacementModifierType OFFSET = register( - "offset", - Offset.CODEC - ); + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#EXTEND} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType EXTEND = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.EXTEND; - public static final PlacementModifierType EXTEND = register( - "extend", - Extend.CODEC - ); - - public static final PlacementModifierType ON_EVERY_LAYER = register( - "on_every_layer", - OnEveryLayer.CODEC - ); - - public static final PlacementModifierType UNDER_EVERY_LAYER = register( - "under_every_layer", - UnderEveryLayer.CODEC - ); + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#ON_EVERY_LAYER} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType ON_EVERY_LAYER = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.ON_EVERY_LAYER; + /** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#UNDER_EVERY_LAYER} instead + */ + @Deprecated(forRemoval = true) + public static final PlacementModifierType UNDER_EVERY_LAYER = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.UNDER_EVERY_LAYER; private static

PlacementModifierType

register(String path, Codec

codec) { return register(BCLib.makeID(path), codec); } + + /** + * @param location + * @param codec + * @param

+ * @return + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#register(ResourceLocation, Codec)} instead + */ + @Deprecated(forRemoval = true) public static

PlacementModifierType

register( ResourceLocation location, Codec

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() { } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Stencil.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Stencil.java index c713fed1..c6f91c4d 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Stencil.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/Stencil.java @@ -1,345 +1,19 @@ 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.stream.Stream; -public class Stencil extends PlacementModifier { - public static final Codec CODEC; - private static final Boolean[] BN_STENCIL; - private final List stencil; - private static final Stencil DEFAULT; - private static final Stencil DEFAULT4; - private final int selectOneIn; - private static List 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) { - this(convert(stencil), selectOneIn); + super(stencil, selectOneIn); } public Stencil(List stencil, int selectOneIn) { - this.stencil = stencil; - this.selectOneIn = selectOneIn; - } - - public static Stencil all() { - return DEFAULT; - } - - public static Stencil oneIn4() { - return DEFAULT4; - } - - @Override - public Stream getPositions( - PlacementContext placementContext, - RandomSource randomSource, - BlockPos blockPos - ) { - List 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) - ); + super(stencil, selectOneIn); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/UnderEveryLayer.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/UnderEveryLayer.java index ea4fd12f..36259571 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/UnderEveryLayer.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/UnderEveryLayer.java @@ -1,93 +1,15 @@ 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.stream.Stream; +/** + * @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.UnderEveryLayer} instead + */ +@Deprecated(forRemoval = true) 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 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)); + extends org.betterx.bclib.api.v3.levelgen.features.placement.UnderEveryLayer { - - private final Optional minHeight; - private final Optional maxHeight; - - private UnderEveryLayer(Optional minHeight, Optional maxHeight) { - this.minHeight = minHeight; - - this.maxHeight = maxHeight; - } - - public static UnderEveryLayer simple() { - return INSTANCE; - } - - public static UnderEveryLayer min4() { - return INSTANCE_MIN_4; - } - - @Override - public Stream getPositions( - PlacementContext ctx, - RandomSource random, - BlockPos pos - ) { - - Stream.Builder 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 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; + protected UnderEveryLayer(Optional minHeight, Optional maxHeight) { + super(minHeight, maxHeight); } } diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLConfigureFeature.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLConfigureFeature.java index 84fa892e..e3442c50 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLConfigureFeature.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLConfigureFeature.java @@ -1,7 +1,5 @@ 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.Holder; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeature.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeature.java index 058d94a6..fa2cf696 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeature.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeature.java @@ -1,8 +1,8 @@ package org.betterx.bclib.api.v3.levelgen.features; import org.betterx.bclib.BCLib; -import org.betterx.bclib.api.v2.levelgen.features.config.*; -import org.betterx.bclib.api.v2.levelgen.features.features.*; +import org.betterx.bclib.api.v3.levelgen.features.config.*; +import org.betterx.bclib.api.v3.levelgen.features.features.*; import net.minecraft.core.Holder; 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.configurations.FeatureConfiguration; 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 org.jetbrains.annotations.ApiStatus; @@ -21,25 +20,8 @@ public class BCLFeature, FC extends FeatureConfiguration> BCLib.makeID("place_block"), new PlaceBlockFeature<>(PlaceFacingBlockConfig.CODEC) ); - public static final Feature SCATTER_ON_SOLID = register( - BCLib.makeID("scatter_on_solid"), - new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC) - ); - public static final Feature SCATTER_EXTEND_TOP = register( - BCLib.makeID("scatter_extend_top"), - new ScatterFeature<>(ScatterFeatureConfig.ExtendTop.CODEC) - ); - - public static final Feature SCATTER_EXTEND_BOTTOM = register( - BCLib.makeID("scatter_extend_bottom"), - new ScatterFeature<>(ScatterFeatureConfig.ExtendBottom.CODEC) - ); - - public static final Feature RANDOM_SELECTOR = register( - BCLib.makeID("random_select"), - new WeightedRandomSelectorFeature() - ); + public static final Feature TEMPLATE = register( BCLib.makeID("template"), new TemplateFeature( diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java index bf754f8a..7666938f 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java @@ -1,17 +1,17 @@ package org.betterx.bclib.api.v3.levelgen.features; 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.StructureWorldNBT; 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.util.Triple; diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/CommonPlacedFeatureBuilder.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/CommonPlacedFeatureBuilder.java index 3543cf1a..ab009e10 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/CommonPlacedFeatureBuilder.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/CommonPlacedFeatureBuilder.java @@ -1,8 +1,8 @@ package org.betterx.bclib.api.v3.levelgen.features; -import org.betterx.bclib.api.v2.levelgen.features.config.PlaceFacingBlockConfig; -import org.betterx.bclib.api.v2.levelgen.features.placement.*; -import org.betterx.bclib.api.v3.levelgen.features.placement.NoiseFilter; +import org.betterx.bclib.api.v3.levelgen.features.blockpredicates.BlockPredicates; +import org.betterx.bclib.api.v3.levelgen.features.config.PlaceFacingBlockConfig; +import org.betterx.bclib.api.v3.levelgen.features.placement.*; import org.betterx.worlds.together.tag.v3.CommonBlockTags; import net.minecraft.core.Direction; @@ -74,24 +74,6 @@ abstract class CommonPlacedFeatureBuilder, FC extends Feat 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! * @@ -101,6 +83,15 @@ abstract class CommonPlacedFeatureBuilder, FC extends Feat 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). * Feature will be generated on all layers (example - Nether plants). @@ -218,34 +209,6 @@ abstract class CommonPlacedFeatureBuilder, FC extends Feat 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) { return modifier(RandomOffsetPlacement.horizontal(p)); } @@ -309,15 +272,6 @@ abstract class CommonPlacedFeatureBuilder, FC extends Feat 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 * Blocks (see {@link Material#isReplaceable()}) and will be accepted if it hits a block with the diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/UserGrowableFeature.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/UserGrowableFeature.java index 874bc07c..09335bff 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/UserGrowableFeature.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/UserGrowableFeature.java @@ -1,6 +1,15 @@ 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; -public interface UserGrowableFeature extends org.betterx.bclib.api.v2.levelgen.features.UserGrowableFeature { +public interface UserGrowableFeature { + boolean grow( + ServerLevelAccessor level, + BlockPos pos, + RandomSource random, + FC configuration + ); } diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BlockPredicates.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/blockpredicates/BlockPredicates.java similarity index 64% rename from src/main/java/org/betterx/bclib/api/v3/levelgen/features/BlockPredicates.java rename to src/main/java/org/betterx/bclib/api/v3/levelgen/features/blockpredicates/BlockPredicates.java index 483bc451..cb3df9f7 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BlockPredicates.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/blockpredicates/BlockPredicates.java @@ -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 com.mojang.serialization.Codec; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate; +import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicateType; import net.minecraft.world.level.material.Fluids; public class BlockPredicates { @@ -24,4 +29,16 @@ public class BlockPredicates { BlockPredicate.matchesTag(CommonBlockTags.TERRAIN), BlockPredicate.matchesFluids(Fluids.LAVA) ); + public static final BlockPredicateType FULL_SHAPE = register( + BCLib.makeID("full_shape"), + IsFullShape.CODEC + ); + + public static

BlockPredicateType

register(ResourceLocation location, Codec

codec) { + return Registry.register(Registry.BLOCK_PREDICATE_TYPES, location, () -> codec); + } + + public static void ensureStaticInitialization() { + + } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/blockpredicates/IsFullShape.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/blockpredicates/IsFullShape.java similarity index 92% rename from src/main/java/org/betterx/bclib/api/v2/levelgen/features/blockpredicates/IsFullShape.java rename to src/main/java/org/betterx/bclib/api/v3/levelgen/features/blockpredicates/IsFullShape.java index 39fc3b3d..10dc7e21 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/blockpredicates/IsFullShape.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/blockpredicates/IsFullShape.java @@ -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.codecs.RecordCodecBuilder; @@ -30,7 +30,7 @@ public class IsFullShape implements BlockPredicate { public BlockPredicateType type() { - return Types.FULL_SHAPE; + return BlockPredicates.FULL_SHAPE; } @Override diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/ConditionFeatureConfig.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/ConditionFeatureConfig.java new file mode 100644 index 00000000..8dd40dfd --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/ConditionFeatureConfig.java @@ -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 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 okFeature; + public final Optional> 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 okFeature + ) { + this(filter, okFeature, Optional.empty()); + + } + + public ConditionFeatureConfig( + @NotNull PlacementFilter filter, + @NotNull Holder okFeature, + @NotNull Holder failFeature + ) { + this(filter, okFeature, Optional.of(failFeature)); + } + + protected ConditionFeatureConfig( + @NotNull PlacementModifier filter, + @NotNull Holder okFeature, + @NotNull Optional> failFeature + ) { + this.filter = filter; + this.okFeature = okFeature; + this.failFeature = failFeature; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PillarFeatureConfig.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/PillarFeatureConfig.java similarity index 98% rename from src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PillarFeatureConfig.java rename to src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/PillarFeatureConfig.java index 271f9c59..030387ed 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/config/PillarFeatureConfig.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/PillarFeatureConfig.java @@ -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; diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/PlaceBlockFeatureConfig.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/PlaceBlockFeatureConfig.java new file mode 100644 index 00000000..8341bbfd --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/PlaceBlockFeatureConfig.java @@ -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 RecordCodecBuilder blockStateCodec() { + return BlockStateProvider.CODEC + .fieldOf("entries") + .forGetter((T o) -> o.stateProvider); + } + + protected final BlockStateProvider stateProvider; + + + protected static SimpleWeightedRandomList buildWeightedList(List states) { + var builder = SimpleWeightedRandomList.builder(); + for (BlockState s : states) builder.add(s, 1); + return builder.build(); + } + + protected static SimpleWeightedRandomList buildWeightedList(BlockState state) { + return SimpleWeightedRandomList + .builder() + .add(state, 1) + .build(); + } + + public PlaceBlockFeatureConfig(Block block) { + this(block.defaultBlockState()); + } + + public PlaceBlockFeatureConfig(BlockState state) { + this(BlockStateProvider.simple(state)); + } + + + public PlaceBlockFeatureConfig(List states) { + this(buildWeightedList(states)); + } + + public PlaceBlockFeatureConfig(SimpleWeightedRandomList 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 ctx) { + BlockState state = getRandomBlock(ctx.random(), ctx.origin()); + return placeBlock(ctx, ctx.level(), ctx.origin(), state); + } + + + protected abstract boolean placeBlock( + FeaturePlaceContext ctx, + WorldGenLevel level, + BlockPos pos, + BlockState targetState + ); +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/PlaceFacingBlockConfig.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/PlaceFacingBlockConfig.java new file mode 100644 index 00000000..1d19f3b9 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/PlaceFacingBlockConfig.java @@ -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 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 HORIZONTAL = List.of( + Direction.NORTH, + Direction.EAST, + Direction.WEST, + Direction.SOUTH + ); + public static final List VERTICAL = List.of(Direction.UP, Direction.DOWN); + public static final List ALL = List.of( + Direction.NORTH, + Direction.EAST, + Direction.SOUTH, + Direction.WEST, + Direction.UP, + Direction.DOWN + ); + + private final List directions; + + public PlaceFacingBlockConfig(Block block, List dir) { + this(block.defaultBlockState(), dir); + } + + public PlaceFacingBlockConfig(BlockState state, List dir) { + this(BlockStateProvider.simple(state), dir); + } + + public PlaceFacingBlockConfig(List states, List dir) { + this(buildWeightedList(states), dir); + } + + public PlaceFacingBlockConfig(SimpleWeightedRandomList blocks, List dir) { + this(new WeightedStateProvider(blocks), dir); + } + + public PlaceFacingBlockConfig(BlockStateProvider blocks, List dir) { + super(blocks); + directions = dir; + } + + @Override + + public boolean placeBlock( + FeaturePlaceContext 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; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/SequenceFeatureConfig.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/SequenceFeatureConfig.java new file mode 100644 index 00000000..91c8a7a0 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/SequenceFeatureConfig.java @@ -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 CODEC = RecordCodecBuilder.create(instance -> + instance.group( + ExtraCodecs.nonEmptyList(PlacedFeature.CODEC.listOf()) + .fieldOf("features") + .forGetter(a -> a.features) + ).apply(instance, SequenceFeatureConfig::new) + ); + + private final List> features; + + public static SequenceFeatureConfig create(List> features) { + return new SequenceFeatureConfig(features.stream().map(f -> f.getPlacedFeature()).toList()); + } + + public static SequenceFeatureConfig createSequence(List> features) { + return new SequenceFeatureConfig(features.stream().map(f -> f.getPlacedFeature()).toList()); + } + + public SequenceFeatureConfig(List> features) { + this.features = features; + } + + public boolean placeAll(FeaturePlaceContext ctx) { + boolean placed = false; + for (Holder f : features) { + placed |= f.value().place(ctx.level(), ctx.chunkGenerator(), ctx.random(), ctx.origin()); + } + return placed; + + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/TemplateFeatureConfig.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/TemplateFeatureConfig.java new file mode 100644 index 00000000..73b47c8e --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/config/TemplateFeatureConfig.java @@ -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 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 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 structures) { + this.structures = structures; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/ConditionFeature.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/ConditionFeature.java new file mode 100644 index 00000000..8ceb7de2 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/ConditionFeature.java @@ -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 { + public ConditionFeature() { + super(ConditionFeatureConfig.CODEC); + } + + @Override + public boolean place(FeaturePlaceContext 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 stream = cfg.filter.getPositions(c, ctx.random(), pos); + Holder state = (stream.findFirst().isPresent() ? cfg.okFeature : cfg.failFeature.orElse(null)); + if (state != null) { + return state.value().place(level, ctx.chunkGenerator(), random, pos); + } + return false; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/MarkPostProcessingFeature.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/MarkPostProcessingFeature.java new file mode 100644 index 00000000..888a8103 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/MarkPostProcessingFeature.java @@ -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 { + public MarkPostProcessingFeature() { + super(NoneFeatureConfiguration.CODEC); + } + + @Override + public boolean place(FeaturePlaceContext 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; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/PillarFeature.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/PillarFeature.java similarity index 94% rename from src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/PillarFeature.java rename to src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/PillarFeature.java index 8c318022..3cc71224 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/PillarFeature.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/PillarFeature.java @@ -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 net.minecraft.core.BlockPos; diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/PlaceBlockFeature.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/PlaceBlockFeature.java new file mode 100644 index 00000000..257bf0d2 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/PlaceBlockFeature.java @@ -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 extends Feature { + public PlaceBlockFeature(Codec codec) { + super(codec); + } + + @Override + public boolean place(FeaturePlaceContext ctx) { + return ctx.config().place(ctx); + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/SequenceFeature.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/SequenceFeature.java new file mode 100644 index 00000000..c42735c7 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/SequenceFeature.java @@ -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 { + public SequenceFeature() { + super(SequenceFeatureConfig.CODEC); + } + + @Override + public boolean place(FeaturePlaceContext featurePlaceContext) { + return featurePlaceContext.config().placeAll(featurePlaceContext); + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/TemplateFeature.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/TemplateFeature.java new file mode 100644 index 00000000..8fe8798b --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/features/TemplateFeature.java @@ -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 extends Feature { + + public static 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 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 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 ctx) { + StructureWorldNBT structure = randomStructure(ctx.config(), ctx.random()); + return structure.generateIfPlaceable( + ctx.level(), + ctx.origin(), + StructureNBT.getRandomRotation(ctx.random()), + StructureNBT.getRandomMirror(ctx.random()) + ); + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/All.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/All.java new file mode 100644 index 00000000..05e3ba8c --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/All.java @@ -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 CODEC = Codec.unit(All::new); + + @Override + public Stream 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; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Debug.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Debug.java new file mode 100644 index 00000000..be942fd1 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Debug.java @@ -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 CODEC = Codec.unit(Debug::new); + + @Override + public Stream getPositions( + PlacementContext placementContext, + RandomSource randomSource, + BlockPos blockPos + ) { + return Stream.of(blockPos); + } + + @Override + public PlacementModifierType type() { + return PlacementModifiers.DEBUG; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Extend.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Extend.java new file mode 100644 index 00000000..21436043 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Extend.java @@ -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 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 getPositions( + PlacementContext placementContext, + RandomSource random, + BlockPos blockPos + ) { + var builder = Stream.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; + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/FindSolidInDirection.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/FindSolidInDirection.java new file mode 100644 index 00000000..4d3a99b0 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/FindSolidInDirection.java @@ -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 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; + 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, int maxSearchDistance) { + this(direction, maxSearchDistance, direction.size() > 1); + } + + public FindSolidInDirection(List 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 getPositions( + PlacementContext placementContext, + RandomSource randomSource, + BlockPos blockPos + ) { + var builder = Stream.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 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; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/ForAll.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/ForAll.java new file mode 100644 index 00000000..0a511a08 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/ForAll.java @@ -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 CODEC = RecordCodecBuilder.create(instance -> instance + .group( + ExtraCodecs.nonEmptyList(PlacementModifier.CODEC.listOf()) + .fieldOf("modifiers") + .forGetter(a -> a.modifiers) + ) + .apply(instance, ForAll::new)); + + private final List modifiers; + + public ForAll(List modifiers) { + this.modifiers = modifiers; + } + + @Override + public Stream getPositions( + PlacementContext placementContext, + RandomSource randomSource, + BlockPos blockPos + ) { + Stream.Builder 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; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Is.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Is.java new file mode 100644 index 00000000..56f3066f --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Is.java @@ -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 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 offset; + + public Is(BlockPredicate predicate, Optional 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 type() { + return PlacementModifiers.IS; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/IsBasin.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/IsBasin.java new file mode 100644 index 00000000..a8d856a0 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/IsBasin.java @@ -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 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 topPredicate; + + public IsBasin(BlockPredicate predicate) { + this(predicate, Optional.empty()); + } + + public IsBasin(BlockPredicate predicate, Optional 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; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/IsNextTo.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/IsNextTo.java similarity index 97% rename from src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/IsNextTo.java rename to src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/IsNextTo.java index 33f35c0b..fbb7c48f 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/placement/IsNextTo.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/IsNextTo.java @@ -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.codecs.RecordCodecBuilder; diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/NoiseFilter.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/NoiseFilter.java index c5fd6430..cdf6c021 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/NoiseFilter.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/NoiseFilter.java @@ -1,6 +1,5 @@ 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 com.mojang.serialization.Codec; diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Offset.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Offset.java new file mode 100644 index 00000000..69ba3ac5 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Offset.java @@ -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 DIRECTIONS = Maps.newHashMap(); + public static final Codec 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 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())); + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/OnEveryLayer.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/OnEveryLayer.java new file mode 100644 index 00000000..4a2ccb4b --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/OnEveryLayer.java @@ -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 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 minHeight; + private final Optional maxHeight; + + protected OnEveryLayer(Optional minHeight, Optional maxHeight) { + this.minHeight = minHeight; + + this.maxHeight = maxHeight; + } + + public static OnEveryLayer simple() { + return INSTANCE; + } + + public static OnEveryLayer min4() { + return INSTANCE_MIN_4; + } + + @Override + public Stream getPositions( + PlacementContext ctx, + RandomSource random, + BlockPos pos + ) { + + Stream.Builder 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 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; + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/PlacementModifiers.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/PlacementModifiers.java new file mode 100644 index 00000000..62248abc --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/PlacementModifiers.java @@ -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 = register( + "stencil", + Stencil.CODEC + ); + public static final PlacementModifierType IS_NEXT_TO = register( + "is_next_to", + IsNextTo.CODEC + ); + public static final PlacementModifierType NOISE_FILTER = register( + "noise_filter", + NoiseFilter.CODEC + ); + public static final PlacementModifierType DEBUG = register( + "debug", + Debug.CODEC + ); + + public static final PlacementModifierType FOR_ALL = register( + "for_all", + ForAll.CODEC + ); + + public static final PlacementModifierType SOLID_IN_DIR = register( + "solid_in_dir", + FindSolidInDirection.CODEC + ); + + public static final PlacementModifierType ALL = register( + "all", + All.CODEC + ); + + public static final PlacementModifierType IS_BASIN = register( + "is_basin", + IsBasin.CODEC + ); + + public static final PlacementModifierType IS = register( + "is", + Is.CODEC + ); + + public static final PlacementModifierType OFFSET = register( + "offset", + Offset.CODEC + ); + + public static final PlacementModifierType EXTEND = register( + "extend", + Extend.CODEC + ); + + public static final PlacementModifierType ON_EVERY_LAYER = register( + "on_every_layer", + OnEveryLayer.CODEC + ); + + public static final PlacementModifierType UNDER_EVERY_LAYER = register( + "under_every_layer", + UnderEveryLayer.CODEC + ); + + + private static

PlacementModifierType

register(String path, Codec

codec) { + return register(BCLib.makeID(path), codec); + } + + public static

PlacementModifierType

register( + ResourceLocation location, + Codec

codec + ) { + return Registry.register(Registry.PLACEMENT_MODIFIERS, location, () -> codec); + } + + public static void ensureStaticInitialization() { + + } +} + diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Stencil.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Stencil.java new file mode 100644 index 00000000..64470958 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/Stencil.java @@ -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 CODEC; + private static final Boolean[] BN_STENCIL; + private final List stencil; + private static final Stencil DEFAULT; + private static final Stencil DEFAULT4; + private final int selectOneIn; + + private static List convert(Boolean[] s) { + return Arrays.stream(s).toList(); + } + + public Stencil(Boolean[] stencil, int selectOneIn) { + this(convert(stencil), selectOneIn); + } + + public Stencil(List stencil, int selectOneIn) { + this.stencil = stencil; + this.selectOneIn = selectOneIn; + } + + public static Stencil all() { + return DEFAULT; + } + + public static Stencil oneIn4() { + return DEFAULT4; + } + + @Override + public Stream getPositions( + PlacementContext placementContext, + RandomSource randomSource, + BlockPos blockPos + ) { + List 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) + ); + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/UnderEveryLayer.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/UnderEveryLayer.java new file mode 100644 index 00000000..eb4c7d57 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/UnderEveryLayer.java @@ -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 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 minHeight; + private final Optional maxHeight; + + protected UnderEveryLayer(Optional minHeight, Optional maxHeight) { + this.minHeight = minHeight; + + this.maxHeight = maxHeight; + } + + public static UnderEveryLayer simple() { + return INSTANCE; + } + + public static UnderEveryLayer min4() { + return INSTANCE_MIN_4; + } + + @Override + public Stream getPositions( + PlacementContext ctx, + RandomSource random, + BlockPos pos + ) { + + Stream.Builder 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 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; + } +}