More Feature Refactoring

This commit is contained in:
Frank 2022-06-28 23:19:03 +02:00
parent c1d5ca7b9b
commit 5d85595c5a
19 changed files with 621 additions and 128 deletions

View file

@ -135,8 +135,7 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourc
private static boolean isValidNetherBiome(Holder<Biome> biome, ResourceLocation location) { private static boolean isValidNetherBiome(Holder<Biome> biome, ResourceLocation location) {
return biome.unwrapKey().get().location().toString().contains("mushroom_forest") return biome.unwrapKey().get().location().toString().contains("upside_down");
|| biome.unwrapKey().get().location().toString().contains("old_fungiwoods");
// return NetherBiomes.canGenerateInNether(biome.unwrapKey().get()) || // return NetherBiomes.canGenerateInNether(biome.unwrapKey().get()) ||
// biome.is(BiomeTags.IS_NETHER) || // biome.is(BiomeTags.IS_NETHER) ||

View file

@ -9,6 +9,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguratio
import net.minecraft.world.level.levelgen.placement.PlacementModifier; import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockMatchTest; import net.minecraft.world.level.levelgen.structure.templatesystem.BlockMatchTest;
@Deprecated(forRemoval = true)
public class BCLCommonFeatures { public class BCLCommonFeatures {
/** /**
* Will create a basic plant feature. * Will create a basic plant feature.

View file

@ -1,8 +1,8 @@
package org.betterx.bclib.api.v2.levelgen.features; package org.betterx.bclib.api.v2.levelgen.features;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.levelgen.features.config.*; 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.BCLConfigureFeature;
import org.betterx.bclib.api.v3.levelgen.features.BCLFeatureBuilder;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
@ -25,7 +25,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.RandomPatchConf
import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.PlacementModifier; import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import java.util.Map.Entry; import java.util.Map;
import java.util.Optional; import java.util.Optional;
/** /**
@ -35,62 +35,57 @@ import java.util.Optional;
*/ */
@Deprecated(forRemoval = true) @Deprecated(forRemoval = true)
public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration> { public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration> {
public static final Feature<PlaceFacingBlockConfig> PLACE_BLOCK = register( /**
BCLib.makeID("place_block"), * @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#PLACE_BLOCK}
new PlaceBlockFeature<>(PlaceFacingBlockConfig.CODEC) */
); @Deprecated(forRemoval = true)
public static final Feature<ScatterFeatureConfig.OnSolid> SCATTER_ON_SOLID = register( public static final Feature<PlaceFacingBlockConfig> PLACE_BLOCK = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.PLACE_BLOCK;
BCLib.makeID("scatter_on_solid"), /**
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC) * @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}
*/
@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}
*/
@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}
*/
@Deprecated(forRemoval = true)
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.RANDOM_SELECTOR;
/**
* @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#TEMPLATE}
*/
@Deprecated(forRemoval = true)
public static final Feature<TemplateFeatureConfig> TEMPLATE = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.TEMPLATE;
/**
* @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#MARK_POSTPROCESSING}
*/
@Deprecated(forRemoval = true)
public static final Feature<NoneFeatureConfiguration> MARK_POSTPROCESSING = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.MARK_POSTPROCESSING;
/**
* @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#SEQUENCE}
*/
@Deprecated(forRemoval = true)
public static final Feature<SequenceFeatureConfig> SEQUENCE = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SEQUENCE;
/**
* @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#CONDITION}
*/
@Deprecated(forRemoval = true)
public static final Feature<ConditionFeatureConfig> CONDITION = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.CONDITION;
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(
TemplateFeatureConfig.CODEC)
);
public static final Feature<NoneFeatureConfiguration> MARK_POSTPROCESSING = register(
BCLib.makeID(
"mark_postprocessing"),
new MarkPostProcessingFeature()
);
public static final Feature<SequenceFeatureConfig> SEQUENCE = register(
BCLib.makeID("sequence"),
new SequenceFeature()
);
public static final Feature<ConditionFeatureConfig> CONDITION = register(
BCLib.makeID("condition"),
new ConditionFeature()
);
public static final Feature<PillarFeatureConfig> PILLAR = register(
BCLib.makeID("pillar"),
new PillarFeature()
);
private final Holder<PlacedFeature> placedFeature;
private final Decoration featureStep;
private final F feature;
private final FC configuration;
public final ResourceLocation id; public final ResourceLocation id;
org.betterx.bclib.api.v3.levelgen.features.BCLFeature<F, FC> proxy;
@Deprecated(forRemoval = true)
public BCLFeature( public BCLFeature(
ResourceLocation id, ResourceLocation id,
F feature, F feature,
@ -101,6 +96,35 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
this(id, feature, featureStep, configuration, buildPlacedFeature(id, feature, configuration, modifiers)); this(id, feature, featureStep, configuration, buildPlacedFeature(id, feature, configuration, modifiers));
} }
private static <E> boolean containsObj(Registry<E> registry, E obj) {
Optional<Map.Entry<ResourceKey<E>, E>> optional = registry
.entrySet()
.stream()
.filter(entry -> entry.getValue() == obj)
.findAny();
return optional.isPresent();
}
private static <F extends Feature<FC>, FC extends FeatureConfiguration> org.betterx.bclib.api.v3.levelgen.features.BCLFeature<F, FC> build(
ResourceLocation id,
F feature,
Decoration featureStep,
FC configuration,
Holder<PlacedFeature> placedFeature
) {
BCLConfigureFeature<F, FC> cfg = BCLFeatureBuilder.start(id, feature)
.configuration(configuration)
.build();
if (!BuiltinRegistries.PLACED_FEATURE.containsKey(id)) {
Registry.register(BuiltinRegistries.PLACED_FEATURE, id, placedFeature.value());
}
if (!Registry.FEATURE.containsKey(id) && !containsObj(Registry.FEATURE, feature)) {
Registry.register(Registry.FEATURE, id, feature);
}
return new org.betterx.bclib.api.v3.levelgen.features.BCLFeature<>(cfg, placedFeature, featureStep);
}
@Deprecated(forRemoval = true)
public BCLFeature( public BCLFeature(
ResourceLocation id, ResourceLocation id,
F feature, F feature,
@ -108,18 +132,13 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
FC configuration, FC configuration,
Holder<PlacedFeature> placedFeature Holder<PlacedFeature> placedFeature
) { ) {
this.placedFeature = placedFeature; this(build(id, feature, featureStep, configuration, placedFeature));
this.featureStep = featureStep; }
this.feature = feature;
this.configuration = configuration;
this.id = id;
if (!BuiltinRegistries.PLACED_FEATURE.containsKey(id)) { @Deprecated(forRemoval = true)
Registry.register(BuiltinRegistries.PLACED_FEATURE, id, placedFeature.value()); public BCLFeature(org.betterx.bclib.api.v3.levelgen.features.BCLFeature proxy) {
} this.proxy = proxy;
if (!Registry.FEATURE.containsKey(id) && !containsObj(Registry.FEATURE, feature)) { this.id = proxy.configuredFeature.id;
Registry.register(Registry.FEATURE, id, feature);
}
} }
private static <FC extends FeatureConfiguration, F extends Feature<FC>> Holder<PlacedFeature> buildPlacedFeature( private static <FC extends FeatureConfiguration, F extends Feature<FC>> Holder<PlacedFeature> buildPlacedFeature(
@ -154,20 +173,20 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
} }
} }
private static <E> boolean containsObj(Registry<E> registry, E obj) { /**
Optional<Entry<ResourceKey<E>, E>> optional = registry * @param string
.entrySet() * @param feature
.stream() * @param <C>
.filter(entry -> entry.getValue() == obj) * @param <F>
.findAny(); * @return
return optional.isPresent(); * @deprecated Use {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#register(ResourceLocation, Feature)} instead
} */
@Deprecated(forRemoval = true)
public static <C extends FeatureConfiguration, F extends Feature<C>> F register( public static <C extends FeatureConfiguration, F extends Feature<C>> F register(
ResourceLocation string, ResourceLocation string,
F feature F feature
) { ) {
return Registry.register(Registry.FEATURE, string, feature); return org.betterx.bclib.api.v3.levelgen.features.BCLFeature.register(string, feature);
} }
/** /**
@ -176,7 +195,11 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
* @return {@link Feature}. * @return {@link Feature}.
*/ */
public F getFeature() { public F getFeature() {
return feature; return proxy.getFeature();
}
public BCLConfigureFeature<F, FC> getConfFeature() {
return proxy.configuredFeature;
} }
/** /**
@ -185,7 +208,7 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
* @return {@link PlacedFeature}. * @return {@link PlacedFeature}.
*/ */
public Holder<PlacedFeature> getPlacedFeature() { public Holder<PlacedFeature> getPlacedFeature() {
return placedFeature; return proxy.getPlacedFeature();
} }
/** /**
@ -194,11 +217,11 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
* @return {@link Decoration}. * @return {@link Decoration}.
*/ */
public Decoration getDecoration() { public Decoration getDecoration() {
return featureStep; return proxy.getDecoration();
} }
public FC getConfiguration() { public FC getConfiguration() {
return configuration; return proxy.getConfiguration();
} }
public boolean place(ServerLevel level, BlockPos pos, RandomSource random) { public boolean place(ServerLevel level, BlockPos pos, RandomSource random) {

View file

@ -35,7 +35,9 @@ public class FastFeatures {
boolean sparse, boolean sparse,
ScatterFeatureConfig.Builder builder ScatterFeatureConfig.Builder builder
) { ) {
return scatter(location, onFloor, sparse, builder, BCLFeature.SCATTER_ON_SOLID); return scatter(location, onFloor, sparse, builder,
org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_ON_SOLID
);
} }
public static BCLFeature scatter( public static BCLFeature scatter(
@ -229,7 +231,8 @@ public class FastFeatures {
int xzSpread, int xzSpread,
int ySpread int ySpread
) { ) {
final BCLFeature SINGLE = simple(location, ySpread, false, BCLFeature.PLACE_BLOCK, final BCLFeature SINGLE = simple(location, ySpread, false,
org.betterx.bclib.api.v3.levelgen.features.BCLFeature.PLACE_BLOCK,
new PlaceFacingBlockConfig(block, PlaceFacingBlockConfig.HORIZONTAL) new PlaceFacingBlockConfig(block, PlaceFacingBlockConfig.HORIZONTAL)
); );
return patch(location, attempts, xzSpread, ySpread, SINGLE); return patch(location, attempts, xzSpread, ySpread, SINGLE);

View file

@ -23,7 +23,7 @@ public class TemplateFeature<FC extends TemplateFeatureConfig> extends Feature<F
return BCLFeatureBuilder return BCLFeatureBuilder
.start(location, BCLFeature.TEMPLATE) .start(location, org.betterx.bclib.api.v3.levelgen.features.BCLFeature.TEMPLATE)
.decoration(GenerationStep.Decoration.SURFACE_STRUCTURES) .decoration(GenerationStep.Decoration.SURFACE_STRUCTURES)
.onceEvery(onceEveryChunk) //discard neighboring chunks .onceEvery(onceEveryChunk) //discard neighboring chunks
.count(16) //try 16 placements in chunk .count(16) //try 16 placements in chunk
@ -42,7 +42,7 @@ public class TemplateFeature<FC extends TemplateFeatureConfig> extends Feature<F
int count int count
) { ) {
return BCLFeatureBuilder return BCLFeatureBuilder
.start(location, BCLFeature.TEMPLATE) .start(location, org.betterx.bclib.api.v3.levelgen.features.BCLFeature.TEMPLATE)
.decoration(GenerationStep.Decoration.SURFACE_STRUCTURES) .decoration(GenerationStep.Decoration.SURFACE_STRUCTURES)
.count(count) .count(count)
.squarePlacement() .squarePlacement()

View file

@ -1,6 +1,7 @@
package org.betterx.bclib.api.v2.levelgen.features.placement; package org.betterx.bclib.api.v2.levelgen.features.placement;
import org.betterx.bclib.BCLib; import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v3.levelgen.features.placement.NoiseFilter;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
@ -9,6 +10,10 @@ import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType; import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
public class PlacementModifiers { public class PlacementModifiers {
public static final PlacementModifierType<NoiseFilter> NOISE_FILTER = register(
"noise_filter",
NoiseFilter.CODEC
);
public static final PlacementModifierType<Debug> DEBUG = register( public static final PlacementModifierType<Debug> DEBUG = register(
"debug", "debug",
Debug.CODEC Debug.CODEC

View file

@ -83,5 +83,6 @@ public class Conditions {
registerNumeric(BCLib.makeID("nether_noise"), NetherNoiseCondition.CODEC); registerNumeric(BCLib.makeID("nether_noise"), NetherNoiseCondition.CODEC);
register(BCLib.makeID("threshold_condition"), ThresholdCondition.CODEC); register(BCLib.makeID("threshold_condition"), ThresholdCondition.CODEC);
register(BCLib.makeID("volume_threshold_condition"), VolumeThresholdCondition.CODEC); register(BCLib.makeID("volume_threshold_condition"), VolumeThresholdCondition.CODEC);
register(BCLib.makeID("rough_noise_condition"), RoughNoiseCondition.CODEC);
} }
} }

View file

@ -0,0 +1,116 @@
package org.betterx.bclib.api.v2.levelgen.surface.rules;
import org.betterx.bclib.mixin.common.SurfaceRulesContextAccessor;
import org.betterx.bclib.noise.Noises;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.util.KeyDispatchDataCodec;
import net.minecraft.util.RandomSource;
import net.minecraft.util.valueproviders.FloatProvider;
import net.minecraft.util.valueproviders.UniformFloat;
import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.synth.NormalNoise;
public class RoughNoiseCondition implements SurfaceRules.ConditionSource {
public static final Codec<RoughNoiseCondition> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
ResourceKey.codec(Registry.NOISE_REGISTRY).fieldOf("noise").forGetter(o -> o.noise),
Codec.DOUBLE.fieldOf("min_threshold").forGetter(o -> o.minThreshold),
Codec.DOUBLE.fieldOf("max_threshold").forGetter(o -> o.maxThreshold),
FloatProvider.CODEC.fieldOf("roughness").forGetter(o -> o.roughness)
)
.apply(
instance,
(noise1, minThreshold1, maxThreshold1, roughness1) -> new RoughNoiseCondition(
noise1,
roughness1,
minThreshold1,
maxThreshold1
)
));
public static final KeyDispatchDataCodec<RoughNoiseCondition> KEY_CODEC = KeyDispatchDataCodec.of(CODEC);
private final ResourceKey<NormalNoise.NoiseParameters> noise;
private final double minThreshold;
private final double maxThreshold;
private final FloatProvider roughness;
public RoughNoiseCondition(
ResourceKey<NormalNoise.NoiseParameters> noise,
FloatProvider roughness,
double minThreshold,
double maxThreshold
) {
this.noise = noise;
this.minThreshold = minThreshold;
this.maxThreshold = maxThreshold;
this.roughness = roughness;
}
public RoughNoiseCondition(
ResourceKey<NormalNoise.NoiseParameters> noise,
FloatProvider roughness,
double minThreshold
) {
this(noise, roughness, minThreshold, Double.MAX_VALUE);
}
public RoughNoiseCondition(
ResourceKey<NormalNoise.NoiseParameters> noise,
double minThreshold
) {
this(noise, UniformFloat.of(-0.2f, 0.4f), minThreshold, Double.MAX_VALUE);
}
public RoughNoiseCondition(
ResourceKey<NormalNoise.NoiseParameters> noise,
double minThreshold,
double maxThreshold
) {
this(noise, UniformFloat.of(-0.1f, 0.4f), minThreshold, maxThreshold);
}
@Override
public KeyDispatchDataCodec<? extends SurfaceRules.ConditionSource> codec() {
return KEY_CODEC;
}
@Override
public SurfaceRules.Condition apply(final SurfaceRules.Context context2) {
final SurfaceRulesContextAccessor ctx = SurfaceRulesContextAccessor.class.cast(context2);
final NormalNoise normalNoise = ctx.getRandomState().getOrCreateNoise(this.noise);
final RandomSource roughnessSource = ctx.getRandomState()
.getOrCreateRandomFactory(Noises.ROUGHNESS_NOISE.location())
.fromHashOf(Noises.ROUGHNESS_NOISE.location());
class NoiseThresholdCondition extends SurfaceRules.LazyCondition {
NoiseThresholdCondition() {
super(context2);
}
@Override
protected long getContextLastUpdate() {
final SurfaceRulesContextAccessor ctx = SurfaceRulesContextAccessor.class.cast(this.context);
return ctx.getLastUpdateY() + ctx.getLastUpdateXZ();
}
protected boolean compute() {
double d = normalNoise
.getValue(
ctx.getBlockX(),
ctx.getBlockZ(),
ctx.getBlockZ()
) + roughness.sample(roughnessSource);
return d >= minThreshold && d <= maxThreshold;
}
}
return new NoiseThresholdCondition();
}
}

View file

@ -1,13 +1,22 @@
package org.betterx.bclib.api.v3.levelgen.features; package org.betterx.bclib.api.v3.levelgen.features;
import org.betterx.bclib.api.v2.levelgen.features.UserGrowableFeature;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.RandomPatchConfiguration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
public class BCLConfigureFeature<F extends Feature<FC>, FC extends FeatureConfiguration> { public class BCLConfigureFeature<F extends Feature<FC>, FC extends FeatureConfiguration> {
private static final Map<Holder<ConfiguredFeature<?, ?>>, BCLConfigureFeature<?, ?>> KNOWN = new HashMap<>(); private static final Map<Holder<ConfiguredFeature<?, ?>>, BCLConfigureFeature<?, ?>> KNOWN = new HashMap<>();
@ -46,4 +55,55 @@ public class BCLConfigureFeature<F extends Feature<FC>, FC extends FeatureConfig
.location(), registeredFeature, false) .location(), registeredFeature, false)
); );
} }
public boolean placeInWorld(ServerLevel level, BlockPos pos, RandomSource random) {
return placeInWorld(getFeature(), getConfiguration(), level, pos, random);
}
private static boolean placeUnboundInWorld(
Feature<?> feature,
FeatureConfiguration config,
ServerLevel level,
BlockPos pos,
RandomSource random
) {
if (config instanceof RandomPatchConfiguration rnd) {
var configured = rnd.feature().value().feature().value();
feature = configured.feature();
config = configured.config();
}
if (feature instanceof UserGrowableFeature growable) {
return growable.grow(level, pos, random, config);
}
FeaturePlaceContext context = new FeaturePlaceContext(
Optional.empty(),
level,
level.getChunkSource().getGenerator(),
random,
pos,
config
);
return feature.place(context);
}
public static boolean placeInWorld(
Feature<NoneFeatureConfiguration> feature,
ServerLevel level,
BlockPos pos,
RandomSource random
) {
return placeUnboundInWorld(feature, FeatureConfiguration.NONE, level, pos, random);
}
public static <FC extends FeatureConfiguration> boolean placeInWorld(
Feature<FC> feature,
FC config,
ServerLevel level,
BlockPos pos,
RandomSource random
) {
return placeUnboundInWorld(feature, config, level, pos, random);
}
} }

View file

@ -1,8 +1,12 @@
package org.betterx.bclib.api.v3.levelgen.features; package org.betterx.bclib.api.v3.levelgen.features;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.levelgen.features.config.*; import org.betterx.bclib.api.v2.levelgen.features.config.*;
import org.betterx.bclib.api.v2.levelgen.features.features.*;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.GenerationStep; import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
@ -10,21 +14,65 @@ import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConf
import net.minecraft.world.level.levelgen.feature.configurations.RandomFeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.RandomFeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import org.jetbrains.annotations.ApiStatus;
public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration> { public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration> {
public static final Feature<PlaceFacingBlockConfig> PLACE_BLOCK = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.PLACE_BLOCK; public static final Feature<PlaceFacingBlockConfig> PLACE_BLOCK = register(
public static final Feature<ScatterFeatureConfig.OnSolid> SCATTER_ON_SOLID = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.SCATTER_ON_SOLID; BCLib.makeID("place_block"),
public static final Feature<ScatterFeatureConfig.ExtendTop> SCATTER_EXTEND_TOP = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.SCATTER_EXTEND_TOP; new PlaceBlockFeature<>(PlaceFacingBlockConfig.CODEC)
public static final Feature<ScatterFeatureConfig.ExtendBottom> SCATTER_EXTEND_BOTTOM = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.SCATTER_EXTEND_BOTTOM; );
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.RANDOM_SELECTOR; public static final Feature<ScatterFeatureConfig.OnSolid> SCATTER_ON_SOLID = register(
public static final Feature<TemplateFeatureConfig> TEMPLATE = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.TEMPLATE; BCLib.makeID("scatter_on_solid"),
public static final Feature<NoneFeatureConfiguration> MARK_POSTPROCESSING = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.MARK_POSTPROCESSING; new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC)
public static final Feature<SequenceFeatureConfig> SEQUENCE = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.SEQUENCE; );
public static final Feature<ConditionFeatureConfig> CONDITION = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.CONDITION;
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(
TemplateFeatureConfig.CODEC)
);
public static final Feature<NoneFeatureConfiguration> MARK_POSTPROCESSING = register(
BCLib.makeID(
"mark_postprocessing"),
new MarkPostProcessingFeature()
);
public static final Feature<SequenceFeatureConfig> SEQUENCE = register(
BCLib.makeID("sequence"),
new SequenceFeature()
);
public static final Feature<ConditionFeatureConfig> CONDITION = register(
BCLib.makeID("condition"),
new ConditionFeature()
);
public static final Feature<PillarFeatureConfig> PILLAR = register(
BCLib.makeID("pillar"),
new PillarFeature()
);
public final BCLConfigureFeature<F, FC> configuredFeature; public final BCLConfigureFeature<F, FC> configuredFeature;
public final Holder<PlacedFeature> placedFeature; public final Holder<PlacedFeature> placedFeature;
public final GenerationStep.Decoration decoration; public final GenerationStep.Decoration decoration;
BCLFeature( @ApiStatus.Internal
@Deprecated(forRemoval = true)
public BCLFeature(
BCLConfigureFeature<F, FC> configuredFeature, BCLConfigureFeature<F, FC> configuredFeature,
Holder<PlacedFeature> placed, Holder<PlacedFeature> placed,
GenerationStep.Decoration decoration GenerationStep.Decoration decoration
@ -34,11 +82,42 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
this.decoration = decoration; this.decoration = decoration;
} }
/**
* Get raw feature.
*
* @return {@link Feature}.
*/
public F getFeature() {
return configuredFeature.getFeature();
}
/**
* Get configured feature.
*
* @return {@link PlacedFeature}.
*/
public Holder<PlacedFeature> getPlacedFeature() { public Holder<PlacedFeature> getPlacedFeature() {
return placedFeature; return placedFeature;
} }
/**
* Get feature decoration step.
*
* @return {@link GenerationStep.Decoration}.
*/
public GenerationStep.Decoration getDecoration() { public GenerationStep.Decoration getDecoration() {
return decoration; return decoration;
} }
public FC getConfiguration() {
return configuredFeature.getConfiguration();
}
public static <C extends FeatureConfiguration, F extends Feature<C>> F register(
ResourceLocation location,
F feature
) {
return Registry.register(Registry.FEATURE, location, feature);
}
} }

View file

@ -1,7 +1,6 @@
package org.betterx.bclib.api.v3.levelgen.features; package org.betterx.bclib.api.v3.levelgen.features;
import org.betterx.bclib.BCLib; import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
import org.betterx.bclib.api.v2.levelgen.features.config.PillarFeatureConfig; 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.PlaceFacingBlockConfig;
import org.betterx.bclib.api.v2.levelgen.features.config.SequenceFeatureConfig; import org.betterx.bclib.api.v2.levelgen.features.config.SequenceFeatureConfig;
@ -43,6 +42,7 @@ import java.util.Set;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends FeatureConfiguration> { public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends FeatureConfiguration> {
private final ResourceLocation featureID; private final ResourceLocation featureID;
private final F feature; private final F feature;
@ -122,7 +122,7 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
public static AsMultiPlaceRandomSelect startRandomSelect( public static AsMultiPlaceRandomSelect startRandomSelect(
ResourceLocation featureID, ResourceLocation featureID,
BiFunction<BCLInlinePlacedBuilder<SimpleBlockFeature, SimpleBlockConfiguration>, Integer, Holder<PlacedFeature>> placementModFunction AsMultiPlaceRandomSelect.Placer placementModFunction
) { ) {
return new AsMultiPlaceRandomSelect( return new AsMultiPlaceRandomSelect(
featureID, featureID,
@ -146,7 +146,7 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
) { ) {
return new WithTemplates( return new WithTemplates(
featureID, featureID,
(TemplateFeature<TemplateFeatureConfig>) BCLFeature.TEMPLATE (TemplateFeature<TemplateFeatureConfig>) org.betterx.bclib.api.v3.levelgen.features.BCLFeature.TEMPLATE
); );
} }
@ -383,7 +383,7 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
} }
public AsSequence add(org.betterx.bclib.api.v3.levelgen.features.BCLFeature p) { public AsSequence add(org.betterx.bclib.api.v3.levelgen.features.BCLFeature<?, ?> p) {
return add(p.placedFeature); return add(p.placedFeature);
} }
@ -427,12 +427,10 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
.build(); .build();
} }
@SafeVarargs
public final AsBlockColumn<FF> addRandom(int height, BlockState... states) { public final AsBlockColumn<FF> addRandom(int height, BlockState... states) {
return this.addRandom(ConstantInt.of(height), states); return this.addRandom(ConstantInt.of(height), states);
} }
@SafeVarargs
public final AsBlockColumn<FF> addRandom(IntProvider height, BlockState... states) { public final AsBlockColumn<FF> addRandom(IntProvider height, BlockState... states) {
var builder = SimpleWeightedRandomList.<BlockState>builder(); var builder = SimpleWeightedRandomList.<BlockState>builder();
for (BlockState state : states) builder.add(state, 1); for (BlockState state : states) builder.add(state, 1);
@ -659,7 +657,7 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
super(featureID, feature); super(featureID, feature);
} }
public WithConfiguration configuration(FC config) { public WithConfiguration<F, FC> configuration(FC config) {
this.configuration = config; this.configuration = config;
return this; return this;
} }
@ -673,7 +671,7 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
} }
public static class FacingBlock extends BCLFeatureBuilder<PlaceBlockFeature<PlaceFacingBlockConfig>, PlaceFacingBlockConfig> { public static class FacingBlock extends BCLFeatureBuilder<PlaceBlockFeature<PlaceFacingBlockConfig>, PlaceFacingBlockConfig> {
private SimpleWeightedRandomList.Builder<BlockState> stateBuilder = SimpleWeightedRandomList.builder(); private final SimpleWeightedRandomList.Builder<BlockState> stateBuilder = SimpleWeightedRandomList.builder();
BlockState firstState; BlockState firstState;
private int count = 0; private int count = 0;
private List<Direction> directions = PlaceFacingBlockConfig.HORIZONTAL; private List<Direction> directions = PlaceFacingBlockConfig.HORIZONTAL;
@ -805,7 +803,7 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
} }
public static class AsRandomSelect extends BCLFeatureBuilder<RandomSelectorFeature, RandomFeatureConfiguration> { public static class AsRandomSelect extends BCLFeatureBuilder<RandomSelectorFeature, RandomFeatureConfiguration> {
private List<WeightedPlacedFeature> features = new LinkedList<>(); private final List<WeightedPlacedFeature> features = new LinkedList<>();
private Holder<PlacedFeature> defaultFeature; private Holder<PlacedFeature> defaultFeature;
private AsRandomSelect(ResourceLocation featureID, RandomSelectorFeature feature) { private AsRandomSelect(ResourceLocation featureID, RandomSelectorFeature feature) {
@ -830,14 +828,21 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
} }
public static class AsMultiPlaceRandomSelect extends BCLFeatureBuilder<RandomSelectorFeature, RandomFeatureConfiguration> { public static class AsMultiPlaceRandomSelect extends BCLFeatureBuilder<RandomSelectorFeature, RandomFeatureConfiguration> {
private List<Triple<BlockStateProvider, Float, Integer>> features = new LinkedList<>(); public interface Placer {
Holder<PlacedFeature> place(
BCLInlinePlacedBuilder<SimpleBlockFeature, SimpleBlockConfiguration> placer,
int id
);
}
private final BiFunction<BCLInlinePlacedBuilder<SimpleBlockFeature, SimpleBlockConfiguration>, Integer, Holder<PlacedFeature>> modFunction; private final List<Triple<BlockStateProvider, Float, Integer>> features = new LinkedList<>();
private final Placer modFunction;
private AsMultiPlaceRandomSelect( private AsMultiPlaceRandomSelect(
ResourceLocation featureID, ResourceLocation featureID,
RandomSelectorFeature feature, RandomSelectorFeature feature,
BiFunction<BCLInlinePlacedBuilder<SimpleBlockFeature, SimpleBlockConfiguration>, Integer, Holder<PlacedFeature>> mod Placer mod
) { ) {
super(featureID, feature); super(featureID, feature);
this.modFunction = mod; this.modFunction = mod;
@ -916,7 +921,7 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
var builder = BCLFeatureBuilder var builder = BCLFeatureBuilder
.start(BCLib.makeID("temp_select_feature" + (featureCounter++)), p) .start(BCLib.makeID("temp_select_feature" + (featureCounter++)), p)
.inlinePlace(); .inlinePlace();
return modFunction.apply(builder, id); return modFunction.place(builder, id);
} }
@Override @Override
@ -924,7 +929,7 @@ public abstract class BCLFeatureBuilder<F extends Feature<FC>, FC extends Featur
if (modFunction == null) { if (modFunction == null) {
throw new IllegalStateException("AsMultiPlaceRandomSelect needs a placement.modification Function"); throw new IllegalStateException("AsMultiPlaceRandomSelect needs a placement.modification Function");
} }
float sum = this.features.stream().map(p -> p.second).reduce(0.0f, (p, v) -> p + v); float sum = this.features.stream().map(p -> p.second).reduce(0.0f, Float::sum);
List<WeightedPlacedFeature> features = this.features.stream() List<WeightedPlacedFeature> features = this.features.stream()
.map(p -> new WeightedPlacedFeature( .map(p -> new WeightedPlacedFeature(
this.place(p.first, p.third), this.place(p.first, p.third),

View file

@ -15,6 +15,7 @@ public class BlockPredicates {
Blocks.SAND, Blocks.SAND,
Blocks.RED_SAND Blocks.RED_SAND
); );
public static final BlockPredicate ONLY_SOUL_GROUND = BlockPredicate.matchesTag(CommonBlockTags.SOUL_GROUND);
public static final BlockPredicate ONLY_NETHER_GROUND = BlockPredicate.matchesTag(CommonBlockTags.NETHER_TERRAIN); public static final BlockPredicate ONLY_NETHER_GROUND = BlockPredicate.matchesTag(CommonBlockTags.NETHER_TERRAIN);
public static final BlockPredicate ONLY_GROUND = BlockPredicate.matchesTag(CommonBlockTags.TERRAIN); public static final BlockPredicate ONLY_GROUND = BlockPredicate.matchesTag(CommonBlockTags.TERRAIN);

View file

@ -2,6 +2,7 @@ package org.betterx.bclib.api.v3.levelgen.features;
import org.betterx.bclib.api.v2.levelgen.features.config.PlaceFacingBlockConfig; import org.betterx.bclib.api.v2.levelgen.features.config.PlaceFacingBlockConfig;
import org.betterx.bclib.api.v2.levelgen.features.placement.*; import org.betterx.bclib.api.v2.levelgen.features.placement.*;
import org.betterx.bclib.api.v3.levelgen.features.placement.NoiseFilter;
import org.betterx.worlds.together.tag.v3.CommonBlockTags; import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@ -11,6 +12,7 @@ import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.valueproviders.IntProvider; import net.minecraft.util.valueproviders.IntProvider;
import net.minecraft.util.valueproviders.UniformInt; import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.level.levelgen.Noises;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate; import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
@ -158,6 +160,18 @@ abstract class CommonPlacedFeatureBuilder<F extends Feature<FC>, FC extends Feat
return modifier(BiomeFilter.biome()); return modifier(BiomeFilter.biome());
} }
public T noiseIn(double min, double max, float scaleXZ, float scaleY) {
return modifier(new NoiseFilter(Noises.GRAVEL, min, max, scaleXZ, scaleY));
}
public T noiseAbove(double value, float scaleXZ, float scaleY) {
return modifier(new NoiseFilter(Noises.GRAVEL, value, Double.MAX_VALUE, scaleXZ, scaleY));
}
public T noiseBelow(double value, float scaleXZ, float scaleY) {
return modifier(new NoiseFilter(Noises.GRAVEL, -Double.MAX_VALUE, value, scaleXZ, scaleY));
}
/** /**
* Randomize the xz-Coordinates * Randomize the xz-Coordinates
* *

View file

@ -0,0 +1,61 @@
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;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.util.RandomSource;
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 net.minecraft.world.level.levelgen.synth.NormalNoise;
public class NoiseFilter extends PlacementFilter {
public static final Codec<NoiseFilter> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
ResourceKey.codec(Registry.NOISE_REGISTRY).fieldOf("noise").forGetter(o -> o.noise),
Codec.DOUBLE.fieldOf("min_noise_level").forGetter(o -> o.minNoiseLevel),
Codec.DOUBLE.fieldOf("max_noise_level").orElse(Double.MAX_VALUE).forGetter(o -> o.maxNoiseLevel),
Codec.FLOAT.fieldOf("scale_xz").orElse(1f).forGetter(o -> o.scaleXZ),
Codec.FLOAT.fieldOf("scale_y").orElse(1f).forGetter(o -> o.scaleY)
)
.apply(instance, NoiseFilter::new));
private final ResourceKey<NormalNoise.NoiseParameters> noise;
private final double minNoiseLevel;
private final double maxNoiseLevel;
private final float scaleXZ;
private final float scaleY;
public NoiseFilter(
ResourceKey<NormalNoise.NoiseParameters> noise,
double minNoiseLevel,
double maxNoiseLevel,
float scaleXZ,
float scaleY
) {
this.noise = noise;
this.minNoiseLevel = minNoiseLevel;
this.maxNoiseLevel = maxNoiseLevel;
this.scaleXZ = scaleXZ;
this.scaleY = scaleY;
}
@Override
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
final NormalNoise normalNoise = Noises.getOrCreateNoise(ctx.getLevel().registryAccess(), random, this.noise);
final double v = normalNoise.getValue(pos.getX() * scaleXZ, pos.getY() * scaleY, pos.getZ() * scaleXZ);
return v > minNoiseLevel && v < maxNoiseLevel;
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.NOISE_FILTER;
}
}

View file

@ -1,27 +1,28 @@
package org.betterx.bclib.blocks; package org.betterx.bclib.blocks;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import java.util.function.Function; import java.util.function.Function;
public abstract class FeatureHangingSaplingBlock extends FeatureSaplingBlock { public abstract class FeatureHangingSaplingBlock<F extends Feature<FC>, FC extends FeatureConfiguration> extends FeatureSaplingBlock {
private static final VoxelShape SHAPE = Block.box(4, 2, 4, 12, 16, 12); private static final VoxelShape SHAPE = Block.box(4, 2, 4, 12, 16, 12);
public FeatureHangingSaplingBlock(Function<BlockState, BCLFeature> featureSupplier) { public FeatureHangingSaplingBlock(FeatureSupplier<F, FC> featureSupplier) {
super(featureSupplier); super(featureSupplier);
} }
public FeatureHangingSaplingBlock( public FeatureHangingSaplingBlock(
Function<BlockState, BCLFeature> featureSupplier, FeatureSupplier<F, FC> featureSupplier,
int light int light
) { ) {
super(light, featureSupplier); super(light, featureSupplier);
@ -29,7 +30,28 @@ public abstract class FeatureHangingSaplingBlock extends FeatureSaplingBlock {
public FeatureHangingSaplingBlock( public FeatureHangingSaplingBlock(
BlockBehaviour.Properties properties, BlockBehaviour.Properties properties,
Function<BlockState, BCLFeature> featureSupplier FeatureSupplier<F, FC> featureSupplier
) {
super(properties, featureSupplier);
}
@Deprecated(forRemoval = true)
public FeatureHangingSaplingBlock(Function<BlockState, org.betterx.bclib.api.v2.levelgen.features.BCLFeature> featureSupplier) {
super(featureSupplier);
}
@Deprecated(forRemoval = true)
public FeatureHangingSaplingBlock(
Function<BlockState, org.betterx.bclib.api.v2.levelgen.features.BCLFeature> featureSupplier,
int light
) {
super(light, featureSupplier);
}
@Deprecated(forRemoval = true)
public FeatureHangingSaplingBlock(
BlockBehaviour.Properties properties,
Function<BlockState, org.betterx.bclib.api.v2.levelgen.features.BCLFeature> featureSupplier
) { ) {
super(properties, featureSupplier); super(properties, featureSupplier);
} }

View file

@ -1,6 +1,7 @@
package org.betterx.bclib.blocks; package org.betterx.bclib.blocks;
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature; import org.betterx.bclib.api.v3.levelgen.features.BCLConfigureFeature;
import org.betterx.bclib.api.v3.levelgen.features.BCLFeature;
import org.betterx.bclib.client.models.BasePatterns; import org.betterx.bclib.client.models.BasePatterns;
import org.betterx.bclib.client.models.ModelsHelper; import org.betterx.bclib.client.models.ModelsHelper;
import org.betterx.bclib.client.models.PatternsHelper; import org.betterx.bclib.client.models.PatternsHelper;
@ -24,6 +25,9 @@ import net.minecraft.world.level.block.SaplingBlock;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
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.material.Material; import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
@ -39,11 +43,17 @@ import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProvider, BlockModelProvider { public class FeatureSaplingBlock<F extends Feature<FC>, FC extends FeatureConfiguration> extends SaplingBlock implements RenderLayerProvider, BlockModelProvider {
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12);
private final Function<BlockState, BCLFeature> feature;
public FeatureSaplingBlock(Function<BlockState, BCLFeature> featureSupplier) { @FunctionalInterface
public interface FeatureSupplier<F extends Feature<FC>, FC extends FeatureConfiguration> {
BCLConfigureFeature<F, FC> get(BlockState state);
}
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12);
private final FeatureSupplier<F, FC> feature;
public FeatureSaplingBlock(FeatureSupplier<F, FC> featureSupplier) {
this( this(
FabricBlockSettings.of(Material.PLANT) FabricBlockSettings.of(Material.PLANT)
.collidable(false) .collidable(false)
@ -54,7 +64,7 @@ public class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProv
); );
} }
public FeatureSaplingBlock(int light, Function<BlockState, BCLFeature> featureSupplier) { public FeatureSaplingBlock(int light, FeatureSupplier<F, FC> featureSupplier) {
this( this(
FabricBlockSettings.of(Material.PLANT) FabricBlockSettings.of(Material.PLANT)
.collidable(false) .collidable(false)
@ -68,14 +78,60 @@ public class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProv
public FeatureSaplingBlock( public FeatureSaplingBlock(
BlockBehaviour.Properties properties, BlockBehaviour.Properties properties,
Function<BlockState, BCLFeature> featureSupplier FeatureSupplier<F, FC> featureSupplier
) { ) {
super(null, properties); super(null, properties);
this.feature = featureSupplier; this.feature = featureSupplier;
} }
protected BCLFeature getFeature(BlockState state) { @Deprecated(forRemoval = true)
return feature.apply(state); public FeatureSaplingBlock(Function<BlockState, org.betterx.bclib.api.v2.levelgen.features.BCLFeature> featureSupplier) {
this(
FabricBlockSettings.of(Material.PLANT)
.collidable(false)
.instabreak()
.sound(SoundType.GRASS)
.randomTicks(),
featureSupplier
);
}
@Deprecated(forRemoval = true)
public FeatureSaplingBlock(
int light,
Function<BlockState, org.betterx.bclib.api.v2.levelgen.features.BCLFeature> featureSupplier
) {
this(
FabricBlockSettings.of(Material.PLANT)
.collidable(false)
.luminance(light)
.instabreak()
.sound(SoundType.GRASS)
.randomTicks(),
featureSupplier
);
}
@Deprecated(forRemoval = true)
public FeatureSaplingBlock(
BlockBehaviour.Properties properties,
Function<BlockState, org.betterx.bclib.api.v2.levelgen.features.BCLFeature> featureSupplier
) {
super(null, properties);
this.feature = (s) -> featureSupplier.apply(s).getConfFeature();
}
protected BCLConfigureFeature<F, FC> getConfiguredFeature(BlockState state) {
return feature != null ? feature.get(state) : null;
}
@Deprecated(forRemoval = true)
protected org.betterx.bclib.api.v2.levelgen.features.BCLFeature getFeature(BlockState state) {
return new org.betterx.bclib.api.v2.levelgen.features.BCLFeature(new BCLFeature<>(
getConfiguredFeature(state),
null,
GenerationStep.Decoration.TOP_LAYER_MODIFICATION
));
} }
@Override @Override
@ -103,7 +159,9 @@ public class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProv
@Override @Override
public void advanceTree(ServerLevel world, BlockPos pos, BlockState blockState, RandomSource random) { public void advanceTree(ServerLevel world, BlockPos pos, BlockState blockState, RandomSource random) {
getFeature(blockState).place(world, pos, random); var conf = getConfiguredFeature(blockState);
if (conf == null) getFeature(blockState).place(world, pos, random);
else conf.placeInWorld(world, pos, random);
} }
@Override @Override

View file

@ -64,6 +64,7 @@ public abstract class ModIntegration {
return FabricLoader.getInstance().isModLoaded(modID); return FabricLoader.getInstance().isModLoaded(modID);
} }
@Deprecated(forRemoval = true)
public BCLFeature getFeature(String featureID, String placedFeatureID, GenerationStep.Decoration featureStep) { public BCLFeature getFeature(String featureID, String placedFeatureID, GenerationStep.Decoration featureStep) {
ResourceLocation id = getID(featureID); ResourceLocation id = getID(featureID);
Feature<?> feature = Registry.FEATURE.get(id); Feature<?> feature = Registry.FEATURE.get(id);
@ -78,6 +79,7 @@ public abstract class ModIntegration {
); );
} }
@Deprecated(forRemoval = true)
public BCLFeature getFeature(String name, GenerationStep.Decoration featureStep) { public BCLFeature getFeature(String name, GenerationStep.Decoration featureStep) {
return getFeature(name, name, featureStep); return getFeature(name, name, featureStep);
} }

View file

@ -0,0 +1,42 @@
package org.betterx.bclib.noise;
import org.betterx.bclib.BCLib;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.synth.NormalNoise;
import java.util.HashMap;
import java.util.Map;
public class Noises {
private static final Map<ResourceKey<NormalNoise.NoiseParameters>, NormalNoise> noiseIntances = new HashMap<>();
public static final ResourceKey<NormalNoise.NoiseParameters> ROUGHNESS_NOISE = createKey(BCLib.makeID(
"roughness_noise"));
public static ResourceKey<NormalNoise.NoiseParameters> createKey(ResourceLocation loc) {
return ResourceKey.create(Registry.NOISE_REGISTRY, loc);
}
public static NormalNoise createNoise(
Registry<NormalNoise.NoiseParameters> registry,
RandomSource randomSource,
ResourceKey<NormalNoise.NoiseParameters> resourceKey
) {
Holder<NormalNoise.NoiseParameters> holder = registry.getHolderOrThrow(resourceKey);
return NormalNoise.create(randomSource, holder.value());
}
public static NormalNoise getOrCreateNoise(
RegistryAccess registryAccess,
RandomSource randomSource,
ResourceKey<NormalNoise.NoiseParameters> noise
) {
final Registry<NormalNoise.NoiseParameters> registry = registryAccess.registryOrThrow(Registry.NOISE_REGISTRY);
return noiseIntances.computeIfAbsent(noise, (key) -> createNoise(registry, randomSource, noise));
}
}

View file

@ -22,6 +22,7 @@ public class CommonBlockTags {
public static final TagKey<Block> END_ORES = TagManager.BLOCKS.makeCommonTag("end_ores"); public static final TagKey<Block> END_ORES = TagManager.BLOCKS.makeCommonTag("end_ores");
public static final TagKey<Block> SAPLINGS = TagManager.BLOCKS.makeCommonTag("saplings"); public static final TagKey<Block> SAPLINGS = TagManager.BLOCKS.makeCommonTag("saplings");
public static final TagKey<Block> SOUL_GROUND = TagManager.BLOCKS.makeCommonTag("soul_ground"); public static final TagKey<Block> SOUL_GROUND = TagManager.BLOCKS.makeCommonTag("soul_ground");
public static final TagKey<Block> SCULK_LIKE = TagManager.BLOCKS.makeCommonTag("sculk_like");
public static final TagKey<Block> WOODEN_BARREL = TagManager.BLOCKS.makeCommonTag("wooden_barrels"); public static final TagKey<Block> WOODEN_BARREL = TagManager.BLOCKS.makeCommonTag("wooden_barrels");
public static final TagKey<Block> WOODEN_CHEST = TagManager.BLOCKS.makeCommonTag("wooden_chests"); public static final TagKey<Block> WOODEN_CHEST = TagManager.BLOCKS.makeCommonTag("wooden_chests");
public static final TagKey<Block> WORKBENCHES = TagManager.BLOCKS.makeCommonTag("workbench"); public static final TagKey<Block> WORKBENCHES = TagManager.BLOCKS.makeCommonTag("workbench");
@ -35,6 +36,7 @@ public class CommonBlockTags {
public static final TagKey<Block> NETHER_TERRAIN = TagManager.BLOCKS.makeCommonTag("nether_terrain"); public static final TagKey<Block> NETHER_TERRAIN = TagManager.BLOCKS.makeCommonTag("nether_terrain");
static void prepareTags() { static void prepareTags() {
TagManager.BLOCKS.add(SCULK_LIKE, Blocks.SCULK);
TagManager.BLOCKS.addOtherTags(DRAGON_IMMUNE, BlockTags.DRAGON_IMMUNE); TagManager.BLOCKS.addOtherTags(DRAGON_IMMUNE, BlockTags.DRAGON_IMMUNE);
TagManager.BLOCKS.add(END_STONES, Blocks.END_STONE); TagManager.BLOCKS.add(END_STONES, Blocks.END_STONE);
@ -84,8 +86,7 @@ public class CommonBlockTags {
Blocks.GRAVEL, Blocks.GRAVEL,
Blocks.RED_SAND, Blocks.RED_SAND,
Blocks.GLOWSTONE, Blocks.GLOWSTONE,
Blocks.BONE_BLOCK, Blocks.BONE_BLOCK
Blocks.SCULK
); );
TagManager.BLOCKS.addOtherTags( TagManager.BLOCKS.addOtherTags(
NETHER_TERRAIN, NETHER_TERRAIN,