Marked Deprecated API

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

View file

@ -9,10 +9,10 @@ import org.betterx.bclib.api.v2.levelgen.LevelGenEvents;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.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();

View file

@ -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> 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> biome, ResourceLocation location) {

View file

@ -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<F extends Feature<FC>, FC extends FeatureConfiguration>
*/
@Deprecated(forRemoval = true)
public static final Feature<PlaceFacingBlockConfig> PLACE_BLOCK = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.PLACE_BLOCK;
/**
* @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#SCATTER_ON_SOLID}
*/
@Deprecated(forRemoval = true)
public static final Feature<ScatterFeatureConfig.OnSolid> 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<ScatterFeatureConfig.OnSolid> SCATTER_ON_SOLID = register(
BCLib.makeID("scatter_on_solid"),
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC)
);
@Deprecated(forRemoval = true)
public static final Feature<ScatterFeatureConfig.ExtendTop> 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<ScatterFeatureConfig.ExtendTop> SCATTER_EXTEND_TOP = register(
BCLib.makeID("scatter_extend_top"),
new ScatterFeature<>(ScatterFeatureConfig.ExtendTop.CODEC)
);
@Deprecated(forRemoval = true)
public static final Feature<ScatterFeatureConfig.ExtendBottom> 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<ScatterFeatureConfig.ExtendBottom> SCATTER_EXTEND_BOTTOM = register(
BCLib.makeID("scatter_extend_bottom"),
new ScatterFeature<>(ScatterFeatureConfig.ExtendBottom.CODEC)
);
@Deprecated(forRemoval = true)
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.RANDOM_SELECTOR;
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = register(
BCLib.makeID("random_select"),
new WeightedRandomSelectorFeature()
);
/**
* @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#TEMPLATE}
*/

View file

@ -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;

View file

@ -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<ScatterFeature<ScatterFeatureConfig.OnSolid>, 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<NoneFeatureConfiguration> 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<NoneFeatureConfiguration> 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 <FC extends FeatureConfiguration> BCLFeature<Feature<FC>, FC>
simple(
ResourceLocation location,
int searchDist,
boolean rare,
Feature<FC> 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<NoneFeatureConfiguration> feature) {
return patch(location, 96, 7, 3, feature, FeatureConfiguration.NONE);
}
public static BCLFeature
patch(
ResourceLocation location,
int attempts,
int xzSpread,
int ySpread,
Feature<NoneFeatureConfiguration> feature
) {
return patch(location, attempts, xzSpread, ySpread, feature, FeatureConfiguration.NONE);
}
public static <FC extends FeatureConfiguration> BCLFeature
patch(
ResourceLocation location,
int attempts,
int xzSpread,
int ySpread,
Feature<FC> 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<ScatterFeature<ScatterFeatureConfig.OnSolid>, 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<NoneFeatureConfiguration> 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<NoneFeatureConfiguration> 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 <FC extends FeatureConfiguration> BCLFeature<Feature<FC>, FC>
// simple(
// ResourceLocation location,
// int searchDist,
// boolean rare,
// Feature<FC> 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<NoneFeatureConfiguration> 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<NoneFeatureConfiguration> feature
// ) {
// return patch(location, attempts, xzSpread, ySpread, feature, FeatureConfiguration.NONE);
// }
//
// @Deprecated(forRemoval = true)
// public static <FC extends FeatureConfiguration> BCLFeature
// patch(
// ResourceLocation location,
// int attempts,
// int xzSpread,
// int ySpread,
// Feature<FC> 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()));
// }
//
}

View file

@ -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<FC extends FeatureConfiguration> {
boolean grow(
ServerLevelAccessor level,
BlockPos pos,
RandomSource random,
FC configuration
);
/**
* @param <FC>
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.UserGrowableFeature} instead
*/
@Deprecated(forRemoval = true)
public interface UserGrowableFeature<FC extends FeatureConfiguration> extends org.betterx.bclib.api.v3.levelgen.features.UserGrowableFeature<FC> {
}

View file

@ -1,21 +1,34 @@
package org.betterx.bclib.api.v2.levelgen.features.blockpredicates;
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<IsFullShape> FULL_SHAPE = register(
BCLib.makeID("full_shape"),
IsFullShape.CODEC
);
/**
* @deprecated Please use {@link BlockPredicates#FULL_SHAPE} instead
*/
@Deprecated(forRemoval = true)
public static final BlockPredicateType<IsFullShape> FULL_SHAPE = BlockPredicates.FULL_SHAPE;
/**
* @param location
* @param codec
* @param <P>
* @return
* @deprecated Please use {@link BlockPredicates#register(ResourceLocation, Codec)} instead
*/
@Deprecated(forRemoval = true)
public static <P extends BlockPredicate> BlockPredicateType<P> register(ResourceLocation location, Codec<P> codec) {
return Registry.register(Registry.BLOCK_PREDICATE_TYPES, location, () -> codec);
return BlockPredicates.register(location, codec);
}
public static void ensureStaticInitialization() {

View file

@ -2,10 +2,7 @@ package org.betterx.bclib.api.v2.levelgen.features.config;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
import 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<ConditionFeatureConfig> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
PlacementModifier.CODEC.fieldOf("filter").forGetter(p -> p.filter),
PlacedFeature.CODEC.fieldOf("filter_pass").forGetter(p -> p.okFeature),
PlacedFeature.CODEC.optionalFieldOf("filter_fail").forGetter(p -> p.failFeature)
).apply(instance, ConditionFeatureConfig::new)
);
public final PlacementModifier filter;
public final Holder<PlacedFeature> okFeature;
public final Optional<Holder<PlacedFeature>> failFeature;
public ConditionFeatureConfig(
@NotNull PlacementFilter filter,
@NotNull BCLFeature okFeature
) {
this(filter, okFeature.getPlacedFeature(), Optional.empty());
/**
* @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<PlacedFeature> okFeature
) {
this(filter, okFeature, Optional.empty());
public ConditionFeatureConfig(@NotNull PlacementFilter filter, @NotNull Holder<PlacedFeature> okFeature) {
super(filter, okFeature);
}
public ConditionFeatureConfig(
@ -55,7 +37,7 @@ public class ConditionFeatureConfig implements FeatureConfiguration {
@NotNull Holder<PlacedFeature> okFeature,
@NotNull Holder<PlacedFeature> failFeature
) {
this(filter, okFeature, Optional.of(failFeature));
super(filter, okFeature, failFeature);
}
protected ConditionFeatureConfig(
@ -63,8 +45,6 @@ public class ConditionFeatureConfig implements FeatureConfiguration {
@NotNull Holder<PlacedFeature> okFeature,
@NotNull Optional<Holder<PlacedFeature>> failFeature
) {
this.filter = filter;
this.okFeature = okFeature;
this.failFeature = failFeature;
super(filter, okFeature, failFeature);
}
}

View file

@ -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 <T extends PlaceBlockFeatureConfig> RecordCodecBuilder<T, BlockStateProvider> blockStateCodec() {
return BlockStateProvider.CODEC
.fieldOf("entries")
.forGetter((T o) -> o.stateProvider);
}
protected final BlockStateProvider stateProvider;
protected static SimpleWeightedRandomList<BlockState> buildWeightedList(List<BlockState> states) {
var builder = SimpleWeightedRandomList.<BlockState>builder();
for (BlockState s : states) builder.add(s, 1);
return builder.build();
}
protected static SimpleWeightedRandomList<BlockState> buildWeightedList(BlockState state) {
return SimpleWeightedRandomList
.<BlockState>builder()
.add(state, 1)
.build();
}
@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<BlockState> states) {
this(buildWeightedList(states));
super(states);
}
public PlaceBlockFeatureConfig(SimpleWeightedRandomList<BlockState> 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<? extends PlaceBlockFeatureConfig> ctx) {
BlockState state = getRandomBlock(ctx.random(), ctx.origin());
return placeBlock(ctx, ctx.level(), ctx.origin(), state);
}
protected abstract boolean placeBlock(
FeaturePlaceContext<? extends PlaceBlockFeatureConfig> ctx,
WorldGenLevel level,
BlockPos pos,
BlockState targetState
);
}

View file

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

View file

@ -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<SequenceFeatureConfig> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
ExtraCodecs.nonEmptyList(PlacedFeature.CODEC.listOf())
.fieldOf("features")
.forGetter(a -> a.features)
).apply(instance, SequenceFeatureConfig::new)
);
private final List<Holder<PlacedFeature>> features;
public static SequenceFeatureConfig create(List<BCLFeature<?, ?>> features) {
return new SequenceFeatureConfig(features.stream().map(f -> f.getPlacedFeature()).toList());
}
public static SequenceFeatureConfig createSequence(List<org.betterx.bclib.api.v3.levelgen.features.BCLFeature<?, ?>> features) {
return new SequenceFeatureConfig(features.stream().map(f -> f.getPlacedFeature()).toList());
}
/**
* @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<Holder<PlacedFeature>> features) {
this.features = features;
}
public boolean placeAll(FeaturePlaceContext<SequenceFeatureConfig> ctx) {
boolean placed = false;
for (Holder<PlacedFeature> f : features) {
placed |= f.value().place(ctx.level(), ctx.chunkGenerator(), ctx.random(), ctx.origin());
}
return placed;
super(features);
}
}

View file

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

View file

@ -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<ConditionFeatureConfig> {
public ConditionFeature() {
super(ConditionFeatureConfig.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<ConditionFeatureConfig> ctx) {
final ConditionFeatureConfig cfg = ctx.config();
final WorldGenLevel level = ctx.level();
final RandomSource random = ctx.random();
final BlockPos pos = ctx.origin();
final PlacementContext c = new PlacementContext(level, ctx.chunkGenerator(), Optional.empty());
Stream<BlockPos> stream = cfg.filter.getPositions(c, ctx.random(), pos);
Holder<PlacedFeature> state = (stream.findFirst().isPresent() ? cfg.okFeature : cfg.failFeature.orElse(null));
if (state != null) {
return state.value().place(level, ctx.chunkGenerator(), random, pos);
}
return false;
}
/**
* @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 {
}

View file

@ -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<NoneFeatureConfiguration> {
public MarkPostProcessingFeature() {
super(NoneFeatureConfiguration.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> ctx) {
BlockPos pos = ctx.origin();
ctx.level().getChunk(pos.getX() >> 4, pos.getZ() >> 4)
.markPosForPostprocessing(new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15));
return true;
}
/**
* @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 {
}

View file

@ -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<FC extends PlaceBlockFeatureConfig> extends Feature<FC> {
/**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.features.PlaceBlockFeature} instead.
*/
@Deprecated(forRemoval = true)
public class PlaceBlockFeature<FC extends PlaceBlockFeatureConfig> extends org.betterx.bclib.api.v3.levelgen.features.features.PlaceBlockFeature<FC> {
public PlaceBlockFeature(Codec<FC> codec) {
super(codec);
}
@Override
public boolean place(FeaturePlaceContext<FC> ctx) {
return ctx.config().place(ctx);
}
}

View file

@ -1,7 +1,7 @@
package org.betterx.bclib.api.v2.levelgen.features.features;
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<FC extends ScatterFeatureConfig>
extends Feature<FC> implements UserGrowableFeature<FC> {

View file

@ -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<SequenceFeatureConfig> {
public SequenceFeature() {
super(SequenceFeatureConfig.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<SequenceFeatureConfig> featurePlaceContext) {
return featurePlaceContext.config().placeAll(featurePlaceContext);
}
}

View file

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

View file

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

View file

@ -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<RandomFeatureConfiguration> {
public WeightedRandomSelectorFeature() {
super(RandomFeatureConfiguration.CODEC);

View file

@ -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<All> CODEC = Codec.unit(All::new);
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
return IntStream.range(0, 16 * 16 - 1).mapToObj(i -> blockPos.offset(i & 0xF, 0, i >> 4));
}
public static PlacementModifier simple() {
return INSTANCE;
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.ALL;
}
}

View file

@ -1,29 +1,9 @@
package org.betterx.bclib.api.v2.levelgen.features.placement;
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<Debug> CODEC = Codec.unit(Debug::new);
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
return Stream.of(blockPos);
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.DEBUG;
}
}

View file

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

View file

@ -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<FindSolidInDirection> CODEC = RecordCodecBuilder
.create((instance) -> instance.group(
ExtraCodecs.nonEmptyList(Direction.CODEC.listOf())
.fieldOf("dir")
.orElse(List.of(Direction.DOWN))
.forGetter(a -> a.direction),
Codec.intRange(1, 32).fieldOf("dist").orElse(12).forGetter((p) -> p.maxSearchDistance),
Codec.BOOL.fieldOf("random:select").orElse(true).forGetter(p -> p.randomSelect)
)
.apply(
instance,
FindSolidInDirection::new
));
protected static final FindSolidInDirection DOWN = new FindSolidInDirection(Direction.DOWN, 6);
protected static final FindSolidInDirection UP = new FindSolidInDirection(Direction.UP, 6);
private final List<Direction> direction;
private final int maxSearchDistance;
private final boolean randomSelect;
private final IntProvider provider;
/**
* @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> direction, int maxSearchDistance) {
this(direction, maxSearchDistance, direction.size() > 1);
super(direction, maxSearchDistance);
}
public FindSolidInDirection(List<Direction> direction, int maxSearchDistance, boolean randomSelect) {
this.direction = direction;
this.maxSearchDistance = maxSearchDistance;
this.provider = UniformInt.of(0, direction.size() - 1);
this.randomSelect = randomSelect;
}
public static PlacementModifier down() {
return DOWN;
}
public static PlacementModifier up() {
return UP;
}
public static PlacementModifier down(int dist) {
if (dist == DOWN.maxSearchDistance) return DOWN;
return new FindSolidInDirection(Direction.DOWN, dist);
}
public static PlacementModifier up(int dist) {
if (dist == UP.maxSearchDistance) return UP;
return new FindSolidInDirection(Direction.UP, dist);
}
public Direction randomDirection(RandomSource random) {
return direction.get(provider.sample(random));
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
var builder = Stream.<BlockPos>builder();
if (randomSelect) {
submitSingle(placementContext, blockPos, builder, randomDirection(randomSource));
} else {
for (Direction d : direction) {
submitSingle(placementContext, blockPos, builder, d);
}
}
return builder.build();
}
private void submitSingle(
PlacementContext placementContext,
BlockPos blockPos,
Stream.Builder<BlockPos> builder,
Direction d
) {
int searchDist;
BlockPos.MutableBlockPos POS = blockPos.mutable();
if (d == Direction.EAST) { //+x
searchDist = Math.min(maxSearchDistance, 15 - SectionPos.sectionRelative(blockPos.getX()));
} else if (d == Direction.WEST) { //-x
searchDist = Math.min(maxSearchDistance, SectionPos.sectionRelative(blockPos.getX()));
} else if (d == Direction.SOUTH) { //+z
searchDist = Math.min(maxSearchDistance, 15 - SectionPos.sectionRelative(blockPos.getZ()));
} else if (d == Direction.NORTH) { //-z
searchDist = Math.min(maxSearchDistance, SectionPos.sectionRelative(blockPos.getZ()));
} else {
searchDist = maxSearchDistance;
}
if (BlocksHelper.findOnSurroundingSurface(
placementContext.getLevel(),
POS,
d,
searchDist,
BlocksHelper::isTerrain
)) {
builder.add(POS);
}
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.SOLID_IN_DIR;
super(direction, maxSearchDistance, randomSelect);
}
}

View file

@ -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<ForAll> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
ExtraCodecs.nonEmptyList(PlacementModifier.CODEC.listOf())
.fieldOf("modifiers")
.forGetter(a -> a.modifiers)
)
.apply(instance, ForAll::new));
private final List<PlacementModifier> modifiers;
/**
* @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<PlacementModifier> modifiers) {
this.modifiers = modifiers;
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
Stream.Builder<BlockPos> stream = Stream.builder();
for (PlacementModifier p : modifiers) {
p.getPositions(placementContext, randomSource, blockPos).forEach(pp -> stream.add(pp));
}
return stream.build();
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.FOR_ALL;
super(modifiers);
}
}

View file

@ -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<Is> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
BlockPredicate.CODEC
.fieldOf("predicate")
.forGetter(cfg -> cfg.predicate),
Vec3i.CODEC
.optionalFieldOf("offset")
.forGetter(cfg -> cfg.offset)
)
.apply(instance, Is::new));
private final BlockPredicate predicate;
private final Optional<Vec3i> offset;
/**
* @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<Vec3i> offset) {
this.predicate = predicate;
this.offset = offset;
}
public static Is simple(BlockPredicate predicate) {
return new Is(predicate, Optional.empty());
}
public static Is below(BlockPredicate predicate) {
return new Is(predicate, Optional.of(Direction.DOWN.getNormal()));
}
public static Is above(BlockPredicate predicate) {
return new Is(predicate, Optional.of(Direction.UP.getNormal()));
}
@Override
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
WorldGenLevel level = ctx.getLevel();
return predicate.test(level, offset.map(v -> pos.offset(v.getX(), v.getY(), v.getZ())).orElse(pos));
}
@Override
public PlacementModifierType<Is> type() {
return PlacementModifiers.IS;
super(predicate, offset);
}
}

View file

@ -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<IsBasin> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
BlockPredicate.CODEC
.fieldOf("predicate")
.forGetter(cfg -> cfg.predicate),
BlockPredicate.CODEC
.optionalFieldOf("top_predicate")
.orElse(Optional.empty())
.forGetter(cfg -> cfg.topPredicate)
)
.apply(instance, IsBasin::new));
private final BlockPredicate predicate;
private final Optional<BlockPredicate> topPredicate;
/**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.IsBasin} instead.
*/
@Deprecated(forRemoval = true)
public class IsBasin extends org.betterx.bclib.api.v3.levelgen.features.placement.IsBasin {
public IsBasin(BlockPredicate predicate) {
this(predicate, Optional.empty());
super(predicate);
}
public IsBasin(BlockPredicate predicate, Optional<BlockPredicate> topPredicate) {
this.predicate = predicate;
this.topPredicate = topPredicate;
}
public static PlacementFilter simple(BlockPredicate predicate) {
return new IsBasin(predicate);
}
public static IsBasin openTop(BlockPredicate predicate) {
return new IsBasin(predicate, Optional.of(BlockPredicate.ONLY_IN_AIR_PREDICATE));
}
@Override
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
WorldGenLevel level = ctx.getLevel();
if (topPredicate.isPresent() && !topPredicate.get().test(level, pos.above())) return false;
return predicate.test(level, pos.below())
&& predicate.test(level, pos.west())
&& predicate.test(level, pos.east())
&& predicate.test(level, pos.north())
&& predicate.test(level, pos.south());
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.IS_BASIN;
super(predicate, topPredicate);
}
}

View file

@ -12,6 +12,7 @@ import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
/**
* Tests if there is air at two locations above the tested block position
*/
@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);

View file

@ -12,6 +12,7 @@ import net.minecraft.world.level.levelgen.placement.PlacementFilter;
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import net.minecraft.world.level.levelgen.placement.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);

View file

@ -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<Direction, Offset> DIRECTIONS = Maps.newHashMap();
public static final Codec<Offset> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
Vec3i.CODEC
.fieldOf("blocks")
.forGetter(cfg -> cfg.offset)
)
.apply(instance, Offset::new));
private final Vec3i offset;
/**
* @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<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
return Stream.of(blockPos.offset(offset));
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.OFFSET;
}
static {
for (Direction d : Direction.values())
DIRECTIONS.put(d, new Offset(d.getNormal()));
super(offset);
}
}

View file

@ -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<OnEveryLayer> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
Codec.INT.optionalFieldOf("min").forGetter(o -> o.minHeight),
Codec.INT.optionalFieldOf("max").forGetter(o -> o.maxHeight)
).apply(instance, OnEveryLayer::new));
/**
* @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<Integer> minHeight;
private final Optional<Integer> maxHeight;
private OnEveryLayer(Optional<Integer> minHeight, Optional<Integer> maxHeight) {
this.minHeight = minHeight;
this.maxHeight = maxHeight;
}
public static OnEveryLayer simple() {
return INSTANCE;
}
public static OnEveryLayer min4() {
return INSTANCE_MIN_4;
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext ctx,
RandomSource random,
BlockPos pos
) {
Stream.Builder<BlockPos> builder = Stream.builder();
final int z = pos.getZ();
final int x = pos.getX();
final int levelHeight = ctx.getHeight(Heightmap.Types.MOTION_BLOCKING, x, z);
final int minLevelHeight = ctx.getMinBuildHeight();
int y = maxHeight.map(h -> Math.min(levelHeight, h)).orElse(levelHeight);
final int minHeight = this.minHeight.map(h -> Math.max(minLevelHeight, h)).orElse(minLevelHeight);
int layerY;
do {
layerY = OnEveryLayer.findOnGroundYPosition(ctx, x, y, z, minHeight);
if (layerY != Integer.MAX_VALUE) {
builder.add(new BlockPos(x, layerY, z));
y = layerY - 1;
}
} while (layerY != Integer.MAX_VALUE);
return builder.build();
}
@Override
public PlacementModifierType<OnEveryLayer> type() {
return PlacementModifiers.ON_EVERY_LAYER;
}
private static int findOnGroundYPosition(PlacementContext ctx, int x, int startY, int z, int minHeight) {
BlockPos.MutableBlockPos mPos = new BlockPos.MutableBlockPos(x, startY, z);
BlockState nowState = ctx.getBlockState(mPos);
for (int y = startY; y >= minHeight + 1; --y) {
mPos.setY(y - 1);
BlockState belowState = ctx.getBlockState(mPos);
if (BlocksHelper.isTerrain(belowState) && BlocksHelper.isFreeOrFluid(nowState) && !belowState.is(Blocks.BEDROCK)) {
return mPos.getY() + 1;
}
nowState = belowState;
}
return Integer.MAX_VALUE;
protected OnEveryLayer(Optional<Integer> minHeight, Optional<Integer> maxHeight) {
super(minHeight, maxHeight);
}
}

View file

@ -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<NoiseFilter> NOISE_FILTER = register(
"noise_filter",
NoiseFilter.CODEC
);
public static final PlacementModifierType<Debug> 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<NoiseFilter> 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> DEBUG = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.DEBUG;
@Deprecated(forRemoval = true)
public static final PlacementModifierType<IsEmptyAboveSampledFilter> IS_EMPTY_ABOVE_SAMPLED_FILTER = register(
"is_empty_above_sampled_filter",
IsEmptyAboveSampledFilter.CODEC
@ -28,73 +45,87 @@ public class PlacementModifiers {
MinEmptyFilter.CODEC
);
public static final PlacementModifierType<ForAll> 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<ForAll> FOR_ALL = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.FOR_ALL;
public static final PlacementModifierType<FindSolidInDirection> SOLID_IN_DIR = register(
"solid_in_dir",
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<FindSolidInDirection> SOLID_IN_DIR = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.SOLID_IN_DIR;
public static final PlacementModifierType<Stencil> 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> STENCIL = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.STENCIL;
public static final PlacementModifierType<All> 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> ALL = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.ALL;
public static final PlacementModifierType<IsBasin> 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<IsBasin> IS_BASIN = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.IS_BASIN;
public static final PlacementModifierType<IsNextTo> IS_NEXT_TO = register(
"is_next_to",
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> IS = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.IS;
public static final PlacementModifierType<Is> 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> OFFSET = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.OFFSET;
public static final PlacementModifierType<Offset> 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> EXTEND = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.EXTEND;
public static final PlacementModifierType<Extend> EXTEND = register(
"extend",
Extend.CODEC
);
public static final PlacementModifierType<OnEveryLayer> ON_EVERY_LAYER = register(
"on_every_layer",
OnEveryLayer.CODEC
);
public static final PlacementModifierType<UnderEveryLayer> UNDER_EVERY_LAYER = register(
"under_every_layer",
UnderEveryLayer.CODEC
);
/**
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#ON_EVERY_LAYER} instead
*/
@Deprecated(forRemoval = true)
public static final PlacementModifierType<OnEveryLayer> 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<UnderEveryLayer> UNDER_EVERY_LAYER = org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.UNDER_EVERY_LAYER;
private static <P extends PlacementModifier> PlacementModifierType<P> register(String path, Codec<P> codec) {
return register(BCLib.makeID(path), codec);
}
/**
* @param location
* @param codec
* @param <P>
* @return
* @deprecated Please use {@link org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers#register(ResourceLocation, Codec)} instead
*/
@Deprecated(forRemoval = true)
public static <P extends PlacementModifier> PlacementModifierType<P> register(
ResourceLocation location,
Codec<P> codec
) {
return Registry.register(Registry.PLACEMENT_MODIFIERS, location, () -> codec);
return org.betterx.bclib.api.v3.levelgen.features.placement.PlacementModifiers.register(location, codec);
}
@Deprecated(forRemoval = true)
public static void ensureStaticInitialization() {
}

View file

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

View file

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

View file

@ -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;

View file

@ -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<F extends Feature<FC>, FC extends FeatureConfiguration>
BCLib.makeID("place_block"),
new PlaceBlockFeature<>(PlaceFacingBlockConfig.CODEC)
);
public static final Feature<ScatterFeatureConfig.OnSolid> SCATTER_ON_SOLID = register(
BCLib.makeID("scatter_on_solid"),
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC)
);
public static final Feature<ScatterFeatureConfig.ExtendTop> SCATTER_EXTEND_TOP = register(
BCLib.makeID("scatter_extend_top"),
new ScatterFeature<>(ScatterFeatureConfig.ExtendTop.CODEC)
);
public static final Feature<ScatterFeatureConfig.ExtendBottom> SCATTER_EXTEND_BOTTOM = register(
BCLib.makeID("scatter_extend_bottom"),
new ScatterFeature<>(ScatterFeatureConfig.ExtendBottom.CODEC)
);
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = register(
BCLib.makeID("random_select"),
new WeightedRandomSelectorFeature()
);
public static final Feature<TemplateFeatureConfig> TEMPLATE = register(
BCLib.makeID("template"),
new TemplateFeature(

View file

@ -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;

View file

@ -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<F extends Feature<FC>, 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<F extends Feature<FC>, 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<F extends Feature<FC>, 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<F extends Feature<FC>, 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

View file

@ -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<FC extends FeatureConfiguration> extends org.betterx.bclib.api.v2.levelgen.features.UserGrowableFeature<FC> {
public interface UserGrowableFeature<FC extends FeatureConfiguration> {
boolean grow(
ServerLevelAccessor level,
BlockPos pos,
RandomSource random,
FC configuration
);
}

View file

@ -1,10 +1,15 @@
package org.betterx.bclib.api.v3.levelgen.features;
package org.betterx.bclib.api.v3.levelgen.features.blockpredicates;
import org.betterx.bclib.BCLib;
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import 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<IsFullShape> FULL_SHAPE = register(
BCLib.makeID("full_shape"),
IsFullShape.CODEC
);
public static <P extends BlockPredicate> BlockPredicateType<P> register(ResourceLocation location, Codec<P> codec) {
return Registry.register(Registry.BLOCK_PREDICATE_TYPES, location, () -> codec);
}
public static void ensureStaticInitialization() {
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,47 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.placement.PlacementContext;
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
import java.util.List;
import java.util.stream.Stream;
public class ForAll extends PlacementModifier {
public static final Codec<ForAll> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
ExtraCodecs.nonEmptyList(PlacementModifier.CODEC.listOf())
.fieldOf("modifiers")
.forGetter(a -> a.modifiers)
)
.apply(instance, ForAll::new));
private final List<PlacementModifier> modifiers;
public ForAll(List<PlacementModifier> modifiers) {
this.modifiers = modifiers;
}
@Override
public Stream<BlockPos> getPositions(
PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos
) {
Stream.Builder<BlockPos> stream = Stream.builder();
for (PlacementModifier p : modifiers) {
p.getPositions(placementContext, randomSource, blockPos).forEach(pp -> stream.add(pp));
}
return stream.build();
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.FOR_ALL;
}
}

View file

@ -0,0 +1,59 @@
package org.betterx.bclib.api.v3.levelgen.features.placement;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.placement.PlacementContext;
import net.minecraft.world.level.levelgen.placement.PlacementFilter;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
import java.util.Optional;
public class Is extends PlacementFilter {
public static final Codec<Is> CODEC = RecordCodecBuilder.create((instance) -> instance
.group(
BlockPredicate.CODEC
.fieldOf("predicate")
.forGetter(cfg -> cfg.predicate),
Vec3i.CODEC
.optionalFieldOf("offset")
.forGetter(cfg -> cfg.offset)
)
.apply(instance, Is::new));
private final BlockPredicate predicate;
private final Optional<Vec3i> offset;
public Is(BlockPredicate predicate, Optional<Vec3i> offset) {
this.predicate = predicate;
this.offset = offset;
}
public static Is simple(BlockPredicate predicate) {
return new Is(predicate, Optional.empty());
}
public static Is below(BlockPredicate predicate) {
return new Is(predicate, Optional.of(Direction.DOWN.getNormal()));
}
public static Is above(BlockPredicate predicate) {
return new Is(predicate, Optional.of(Direction.UP.getNormal()));
}
@Override
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
WorldGenLevel level = ctx.getLevel();
return predicate.test(level, offset.map(v -> pos.offset(v.getX(), v.getY(), v.getZ())).orElse(pos));
}
@Override
public PlacementModifierType<Is> type() {
return PlacementModifiers.IS;
}
}

View file

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

View file

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

View file

@ -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;

View file

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

View file

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

View file

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

View file

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

View file

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