diff --git a/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java b/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java index 0f854076..f045199c 100644 --- a/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java +++ b/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java @@ -135,8 +135,7 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourc private static boolean isValidNetherBiome(Holder biome, ResourceLocation location) { - return biome.unwrapKey().get().location().toString().contains("mushroom_forest") - || biome.unwrapKey().get().location().toString().contains("old_fungiwoods"); + return biome.unwrapKey().get().location().toString().contains("upside_down"); // return NetherBiomes.canGenerateInNether(biome.unwrapKey().get()) || // biome.is(BiomeTags.IS_NETHER) || diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLCommonFeatures.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLCommonFeatures.java index 6d12edd2..a3983e06 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLCommonFeatures.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLCommonFeatures.java @@ -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.structure.templatesystem.BlockMatchTest; +@Deprecated(forRemoval = true) public class BCLCommonFeatures { /** * Will create a basic plant feature. diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeature.java index eb84e4ef..ee6d5be9 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/BCLFeature.java @@ -1,8 +1,8 @@ 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.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.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.PlacementModifier; -import java.util.Map.Entry; +import java.util.Map; import java.util.Optional; /** @@ -35,62 +35,57 @@ import java.util.Optional; */ @Deprecated(forRemoval = true) public class BCLFeature, FC extends FeatureConfiguration> { - public static final Feature PLACE_BLOCK = register( - BCLib.makeID("place_block"), - new PlaceBlockFeature<>(PlaceFacingBlockConfig.CODEC) - ); - public static final Feature SCATTER_ON_SOLID = register( - BCLib.makeID("scatter_on_solid"), - new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC) - ); + /** + * @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#PLACE_BLOCK} + */ + @Deprecated(forRemoval = true) + public static final Feature PLACE_BLOCK = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.PLACE_BLOCK; + /** + * @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#SCATTER_ON_SOLID} + */ + @Deprecated(forRemoval = true) + public static final Feature SCATTER_ON_SOLID = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_ON_SOLID; + /** + * @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#SCATTER_EXTEND_TOP} + */ + @Deprecated(forRemoval = true) + public static final Feature SCATTER_EXTEND_TOP = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_EXTEND_TOP; + /** + * @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#SCATTER_EXTEND_BOTTOM} + */ + @Deprecated(forRemoval = true) + public static final Feature SCATTER_EXTEND_BOTTOM = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.SCATTER_EXTEND_BOTTOM; + /** + * @deprecated Replace by {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#RANDOM_SELECTOR} + */ + @Deprecated(forRemoval = true) + public static final Feature 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 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 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 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 CONDITION = org.betterx.bclib.api.v3.levelgen.features.BCLFeature.CONDITION; - public static final Feature SCATTER_EXTEND_TOP = register( - BCLib.makeID("scatter_extend_top"), - new ScatterFeature<>(ScatterFeatureConfig.ExtendTop.CODEC) - ); - - public static final Feature SCATTER_EXTEND_BOTTOM = register( - BCLib.makeID("scatter_extend_bottom"), - new ScatterFeature<>(ScatterFeatureConfig.ExtendBottom.CODEC) - ); - - public static final Feature RANDOM_SELECTOR = register( - BCLib.makeID("random_select"), - new WeightedRandomSelectorFeature() - ); - public static final Feature TEMPLATE = register( - BCLib.makeID("template"), - new TemplateFeature( - TemplateFeatureConfig.CODEC) - ); - - public static final Feature MARK_POSTPROCESSING = register( - BCLib.makeID( - "mark_postprocessing"), - new MarkPostProcessingFeature() - ); - - public static final Feature SEQUENCE = register( - BCLib.makeID("sequence"), - new SequenceFeature() - ); - - public static final Feature CONDITION = register( - BCLib.makeID("condition"), - new ConditionFeature() - ); - - public static final Feature PILLAR = register( - BCLib.makeID("pillar"), - new PillarFeature() - ); - private final Holder placedFeature; - private final Decoration featureStep; - private final F feature; - private final FC configuration; public final ResourceLocation id; + org.betterx.bclib.api.v3.levelgen.features.BCLFeature proxy; + @Deprecated(forRemoval = true) public BCLFeature( ResourceLocation id, F feature, @@ -101,6 +96,35 @@ public class BCLFeature, FC extends FeatureConfiguration> this(id, feature, featureStep, configuration, buildPlacedFeature(id, feature, configuration, modifiers)); } + private static boolean containsObj(Registry registry, E obj) { + Optional, E>> optional = registry + .entrySet() + .stream() + .filter(entry -> entry.getValue() == obj) + .findAny(); + return optional.isPresent(); + } + + private static , FC extends FeatureConfiguration> org.betterx.bclib.api.v3.levelgen.features.BCLFeature build( + ResourceLocation id, + F feature, + Decoration featureStep, + FC configuration, + Holder placedFeature + ) { + BCLConfigureFeature 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( ResourceLocation id, F feature, @@ -108,18 +132,13 @@ public class BCLFeature, FC extends FeatureConfiguration> FC configuration, Holder placedFeature ) { - this.placedFeature = placedFeature; - this.featureStep = featureStep; - this.feature = feature; - this.configuration = configuration; - this.id = id; + this(build(id, feature, featureStep, configuration, placedFeature)); + } - 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); - } + @Deprecated(forRemoval = true) + public BCLFeature(org.betterx.bclib.api.v3.levelgen.features.BCLFeature proxy) { + this.proxy = proxy; + this.id = proxy.configuredFeature.id; } private static > Holder buildPlacedFeature( @@ -154,20 +173,20 @@ public class BCLFeature, FC extends FeatureConfiguration> } } - private static boolean containsObj(Registry registry, E obj) { - Optional, E>> optional = registry - .entrySet() - .stream() - .filter(entry -> entry.getValue() == obj) - .findAny(); - return optional.isPresent(); - } - + /** + * @param string + * @param feature + * @param + * @param + * @return + * @deprecated Use {@link org.betterx.bclib.api.v3.levelgen.features.BCLFeature#register(ResourceLocation, Feature)} instead + */ + @Deprecated(forRemoval = true) public static > F register( ResourceLocation string, 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, FC extends FeatureConfiguration> * @return {@link Feature}. */ public F getFeature() { - return feature; + return proxy.getFeature(); + } + + public BCLConfigureFeature getConfFeature() { + return proxy.configuredFeature; } /** @@ -185,7 +208,7 @@ public class BCLFeature, FC extends FeatureConfiguration> * @return {@link PlacedFeature}. */ public Holder getPlacedFeature() { - return placedFeature; + return proxy.getPlacedFeature(); } /** @@ -194,11 +217,11 @@ public class BCLFeature, FC extends FeatureConfiguration> * @return {@link Decoration}. */ public Decoration getDecoration() { - return featureStep; + return proxy.getDecoration(); } public FC getConfiguration() { - return configuration; + return proxy.getConfiguration(); } public boolean place(ServerLevel level, BlockPos pos, RandomSource random) { diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/FastFeatures.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/FastFeatures.java index 09c4774b..fe97cb83 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/FastFeatures.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/FastFeatures.java @@ -35,7 +35,9 @@ public class FastFeatures { boolean sparse, 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( @@ -229,7 +231,8 @@ public class FastFeatures { int xzSpread, 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) ); return patch(location, attempts, xzSpread, ySpread, SINGLE); diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/TemplateFeature.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/TemplateFeature.java index 22740389..14d7a25a 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/TemplateFeature.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/features/features/TemplateFeature.java @@ -23,7 +23,7 @@ public class TemplateFeature extends Feature extends Feature NOISE_FILTER = register( + "noise_filter", + NoiseFilter.CODEC + ); public static final PlacementModifierType DEBUG = register( "debug", Debug.CODEC diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/surface/rules/Conditions.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/surface/rules/Conditions.java index 8e9ebc20..63920e1a 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/surface/rules/Conditions.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/surface/rules/Conditions.java @@ -83,5 +83,6 @@ public class Conditions { registerNumeric(BCLib.makeID("nether_noise"), NetherNoiseCondition.CODEC); register(BCLib.makeID("threshold_condition"), ThresholdCondition.CODEC); register(BCLib.makeID("volume_threshold_condition"), VolumeThresholdCondition.CODEC); + register(BCLib.makeID("rough_noise_condition"), RoughNoiseCondition.CODEC); } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/surface/rules/RoughNoiseCondition.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/surface/rules/RoughNoiseCondition.java new file mode 100644 index 00000000..e578bcf4 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/surface/rules/RoughNoiseCondition.java @@ -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 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 KEY_CODEC = KeyDispatchDataCodec.of(CODEC); + + private final ResourceKey noise; + private final double minThreshold; + private final double maxThreshold; + private final FloatProvider roughness; + + public RoughNoiseCondition( + ResourceKey noise, + FloatProvider roughness, + double minThreshold, + double maxThreshold + ) { + this.noise = noise; + this.minThreshold = minThreshold; + + this.maxThreshold = maxThreshold; + this.roughness = roughness; + } + + public RoughNoiseCondition( + ResourceKey noise, + FloatProvider roughness, + double minThreshold + ) { + this(noise, roughness, minThreshold, Double.MAX_VALUE); + } + + public RoughNoiseCondition( + ResourceKey noise, + double minThreshold + ) { + this(noise, UniformFloat.of(-0.2f, 0.4f), minThreshold, Double.MAX_VALUE); + } + + public RoughNoiseCondition( + ResourceKey noise, + double minThreshold, + double maxThreshold + ) { + this(noise, UniformFloat.of(-0.1f, 0.4f), minThreshold, maxThreshold); + } + + @Override + public KeyDispatchDataCodec 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(); + } +} diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLConfigureFeature.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLConfigureFeature.java index 07ca36be..84fa892e 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLConfigureFeature.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLConfigureFeature.java @@ -1,13 +1,22 @@ 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; +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.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.NoneFeatureConfiguration; +import net.minecraft.world.level.levelgen.feature.configurations.RandomPatchConfiguration; import java.util.HashMap; import java.util.Map; +import java.util.Optional; public class BCLConfigureFeature, FC extends FeatureConfiguration> { private static final Map>, BCLConfigureFeature> KNOWN = new HashMap<>(); @@ -46,4 +55,55 @@ public class BCLConfigureFeature, FC extends FeatureConfig .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 feature, + ServerLevel level, + BlockPos pos, + RandomSource random + ) { + return placeUnboundInWorld(feature, FeatureConfiguration.NONE, level, pos, random); + } + + public static boolean placeInWorld( + Feature feature, + FC config, + ServerLevel level, + BlockPos pos, + RandomSource random + ) { + return placeUnboundInWorld(feature, config, level, pos, random); + } } diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeature.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeature.java index 7174dc0e..058d94a6 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeature.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeature.java @@ -1,8 +1,12 @@ 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 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.feature.Feature; 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.placement.PlacedFeature; +import org.jetbrains.annotations.ApiStatus; + public class BCLFeature, FC extends FeatureConfiguration> { - public static final Feature PLACE_BLOCK = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.PLACE_BLOCK; - public static final Feature SCATTER_ON_SOLID = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.SCATTER_ON_SOLID; - public static final Feature SCATTER_EXTEND_TOP = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.SCATTER_EXTEND_TOP; - public static final Feature SCATTER_EXTEND_BOTTOM = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.SCATTER_EXTEND_BOTTOM; - public static final Feature RANDOM_SELECTOR = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.RANDOM_SELECTOR; - public static final Feature TEMPLATE = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.TEMPLATE; - public static final Feature MARK_POSTPROCESSING = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.MARK_POSTPROCESSING; - public static final Feature SEQUENCE = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.SEQUENCE; - public static final Feature CONDITION = org.betterx.bclib.api.v2.levelgen.features.BCLFeature.CONDITION; + public static final Feature PLACE_BLOCK = register( + BCLib.makeID("place_block"), + new PlaceBlockFeature<>(PlaceFacingBlockConfig.CODEC) + ); + public static final Feature SCATTER_ON_SOLID = register( + BCLib.makeID("scatter_on_solid"), + new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC) + ); + + public static final Feature SCATTER_EXTEND_TOP = register( + BCLib.makeID("scatter_extend_top"), + new ScatterFeature<>(ScatterFeatureConfig.ExtendTop.CODEC) + ); + + public static final Feature SCATTER_EXTEND_BOTTOM = register( + BCLib.makeID("scatter_extend_bottom"), + new ScatterFeature<>(ScatterFeatureConfig.ExtendBottom.CODEC) + ); + + public static final Feature RANDOM_SELECTOR = register( + BCLib.makeID("random_select"), + new WeightedRandomSelectorFeature() + ); + public static final Feature TEMPLATE = register( + BCLib.makeID("template"), + new TemplateFeature( + TemplateFeatureConfig.CODEC) + ); + + public static final Feature MARK_POSTPROCESSING = register( + BCLib.makeID( + "mark_postprocessing"), + new MarkPostProcessingFeature() + ); + + public static final Feature SEQUENCE = register( + BCLib.makeID("sequence"), + new SequenceFeature() + ); + + public static final Feature CONDITION = register( + BCLib.makeID("condition"), + new ConditionFeature() + ); + + public static final Feature PILLAR = register( + BCLib.makeID("pillar"), + new PillarFeature() + ); public final BCLConfigureFeature configuredFeature; public final Holder placedFeature; public final GenerationStep.Decoration decoration; - BCLFeature( + @ApiStatus.Internal + @Deprecated(forRemoval = true) + public BCLFeature( BCLConfigureFeature configuredFeature, Holder placed, GenerationStep.Decoration decoration @@ -34,11 +82,42 @@ public class BCLFeature, FC extends FeatureConfiguration> this.decoration = decoration; } + /** + * Get raw feature. + * + * @return {@link Feature}. + */ + public F getFeature() { + return configuredFeature.getFeature(); + } + + /** + * Get configured feature. + * + * @return {@link PlacedFeature}. + */ public Holder getPlacedFeature() { return placedFeature; } + /** + * Get feature decoration step. + * + * @return {@link GenerationStep.Decoration}. + */ public GenerationStep.Decoration getDecoration() { return decoration; } + + public FC getConfiguration() { + return configuredFeature.getConfiguration(); + } + + + public static > F register( + ResourceLocation location, + F feature + ) { + return Registry.register(Registry.FEATURE, location, feature); + } } diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java index 101f26f5..bf754f8a 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BCLFeatureBuilder.java @@ -1,7 +1,6 @@ package org.betterx.bclib.api.v3.levelgen.features; 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.PlaceFacingBlockConfig; import org.betterx.bclib.api.v2.levelgen.features.config.SequenceFeatureConfig; @@ -43,6 +42,7 @@ import java.util.Set; import java.util.function.BiFunction; import org.jetbrains.annotations.NotNull; +@SuppressWarnings("unused") public abstract class BCLFeatureBuilder, FC extends FeatureConfiguration> { private final ResourceLocation featureID; private final F feature; @@ -122,7 +122,7 @@ public abstract class BCLFeatureBuilder, FC extends Featur public static AsMultiPlaceRandomSelect startRandomSelect( ResourceLocation featureID, - BiFunction, Integer, Holder> placementModFunction + AsMultiPlaceRandomSelect.Placer placementModFunction ) { return new AsMultiPlaceRandomSelect( featureID, @@ -146,7 +146,7 @@ public abstract class BCLFeatureBuilder, FC extends Featur ) { return new WithTemplates( featureID, - (TemplateFeature) BCLFeature.TEMPLATE + (TemplateFeature) org.betterx.bclib.api.v3.levelgen.features.BCLFeature.TEMPLATE ); } @@ -383,7 +383,7 @@ public abstract class BCLFeatureBuilder, 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); } @@ -427,12 +427,10 @@ public abstract class BCLFeatureBuilder, FC extends Featur .build(); } - @SafeVarargs public final AsBlockColumn addRandom(int height, BlockState... states) { return this.addRandom(ConstantInt.of(height), states); } - @SafeVarargs public final AsBlockColumn addRandom(IntProvider height, BlockState... states) { var builder = SimpleWeightedRandomList.builder(); for (BlockState state : states) builder.add(state, 1); @@ -659,7 +657,7 @@ public abstract class BCLFeatureBuilder, FC extends Featur super(featureID, feature); } - public WithConfiguration configuration(FC config) { + public WithConfiguration configuration(FC config) { this.configuration = config; return this; } @@ -673,7 +671,7 @@ public abstract class BCLFeatureBuilder, FC extends Featur } public static class FacingBlock extends BCLFeatureBuilder, PlaceFacingBlockConfig> { - private SimpleWeightedRandomList.Builder stateBuilder = SimpleWeightedRandomList.builder(); + private final SimpleWeightedRandomList.Builder stateBuilder = SimpleWeightedRandomList.builder(); BlockState firstState; private int count = 0; private List directions = PlaceFacingBlockConfig.HORIZONTAL; @@ -805,7 +803,7 @@ public abstract class BCLFeatureBuilder, FC extends Featur } public static class AsRandomSelect extends BCLFeatureBuilder { - private List features = new LinkedList<>(); + private final List features = new LinkedList<>(); private Holder defaultFeature; private AsRandomSelect(ResourceLocation featureID, RandomSelectorFeature feature) { @@ -830,14 +828,21 @@ public abstract class BCLFeatureBuilder, FC extends Featur } public static class AsMultiPlaceRandomSelect extends BCLFeatureBuilder { - private List> features = new LinkedList<>(); + public interface Placer { + Holder place( + BCLInlinePlacedBuilder placer, + int id + ); + } - private final BiFunction, Integer, Holder> modFunction; + private final List> features = new LinkedList<>(); + + private final Placer modFunction; private AsMultiPlaceRandomSelect( ResourceLocation featureID, RandomSelectorFeature feature, - BiFunction, Integer, Holder> mod + Placer mod ) { super(featureID, feature); this.modFunction = mod; @@ -916,7 +921,7 @@ public abstract class BCLFeatureBuilder, FC extends Featur var builder = BCLFeatureBuilder .start(BCLib.makeID("temp_select_feature" + (featureCounter++)), p) .inlinePlace(); - return modFunction.apply(builder, id); + return modFunction.place(builder, id); } @Override @@ -924,7 +929,7 @@ public abstract class BCLFeatureBuilder, FC extends Featur if (modFunction == null) { 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 features = this.features.stream() .map(p -> new WeightedPlacedFeature( this.place(p.first, p.third), diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BlockPredicates.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BlockPredicates.java index c659870a..483bc451 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BlockPredicates.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/BlockPredicates.java @@ -15,6 +15,7 @@ public class BlockPredicates { Blocks.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_GROUND = BlockPredicate.matchesTag(CommonBlockTags.TERRAIN); diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/CommonPlacedFeatureBuilder.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/CommonPlacedFeatureBuilder.java index 2de1e38f..3543cf1a 100644 --- a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/CommonPlacedFeatureBuilder.java +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/CommonPlacedFeatureBuilder.java @@ -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.placement.*; +import org.betterx.bclib.api.v3.levelgen.features.placement.NoiseFilter; import org.betterx.worlds.together.tag.v3.CommonBlockTags; import net.minecraft.core.Direction; @@ -11,6 +12,7 @@ import net.minecraft.data.worldgen.placement.PlacementUtils; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.valueproviders.IntProvider; import net.minecraft.util.valueproviders.UniformInt; +import net.minecraft.world.level.levelgen.Noises; 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; @@ -158,6 +160,18 @@ abstract class CommonPlacedFeatureBuilder, FC extends Feat 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 * diff --git a/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/NoiseFilter.java b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/NoiseFilter.java new file mode 100644 index 00000000..c5fd6430 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/levelgen/features/placement/NoiseFilter.java @@ -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 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 noise; + + private final double minNoiseLevel; + private final double maxNoiseLevel; + private final float scaleXZ; + private final float scaleY; + + + public NoiseFilter( + ResourceKey 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; + } +} diff --git a/src/main/java/org/betterx/bclib/blocks/FeatureHangingSaplingBlock.java b/src/main/java/org/betterx/bclib/blocks/FeatureHangingSaplingBlock.java index e698408d..790886be 100644 --- a/src/main/java/org/betterx/bclib/blocks/FeatureHangingSaplingBlock.java +++ b/src/main/java/org/betterx/bclib/blocks/FeatureHangingSaplingBlock.java @@ -1,27 +1,28 @@ package org.betterx.bclib.blocks; -import org.betterx.bclib.api.v2.levelgen.features.BCLFeature; - import net.minecraft.core.BlockPos; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockBehaviour; 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.VoxelShape; import java.util.function.Function; -public abstract class FeatureHangingSaplingBlock extends FeatureSaplingBlock { +public abstract class FeatureHangingSaplingBlock, FC extends FeatureConfiguration> extends FeatureSaplingBlock { + private static final VoxelShape SHAPE = Block.box(4, 2, 4, 12, 16, 12); - public FeatureHangingSaplingBlock(Function featureSupplier) { + public FeatureHangingSaplingBlock(FeatureSupplier featureSupplier) { super(featureSupplier); } public FeatureHangingSaplingBlock( - Function featureSupplier, + FeatureSupplier featureSupplier, int light ) { super(light, featureSupplier); @@ -29,7 +30,28 @@ public abstract class FeatureHangingSaplingBlock extends FeatureSaplingBlock { public FeatureHangingSaplingBlock( BlockBehaviour.Properties properties, - Function featureSupplier + FeatureSupplier featureSupplier + ) { + super(properties, featureSupplier); + } + + @Deprecated(forRemoval = true) + public FeatureHangingSaplingBlock(Function featureSupplier) { + super(featureSupplier); + } + + @Deprecated(forRemoval = true) + public FeatureHangingSaplingBlock( + Function featureSupplier, + int light + ) { + super(light, featureSupplier); + } + + @Deprecated(forRemoval = true) + public FeatureHangingSaplingBlock( + BlockBehaviour.Properties properties, + Function featureSupplier ) { super(properties, featureSupplier); } diff --git a/src/main/java/org/betterx/bclib/blocks/FeatureSaplingBlock.java b/src/main/java/org/betterx/bclib/blocks/FeatureSaplingBlock.java index ce826908..067310c4 100644 --- a/src/main/java/org/betterx/bclib/blocks/FeatureSaplingBlock.java +++ b/src/main/java/org/betterx/bclib/blocks/FeatureSaplingBlock.java @@ -1,6 +1,7 @@ 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.ModelsHelper; 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.state.BlockBehaviour; 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.storage.loot.LootContext; import net.minecraft.world.phys.shapes.CollisionContext; @@ -39,11 +43,17 @@ import java.util.Optional; import java.util.function.Function; import org.jetbrains.annotations.Nullable; -public class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProvider, BlockModelProvider { - private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12); - private final Function feature; +public class FeatureSaplingBlock, FC extends FeatureConfiguration> extends SaplingBlock implements RenderLayerProvider, BlockModelProvider { - public FeatureSaplingBlock(Function featureSupplier) { + @FunctionalInterface + public interface FeatureSupplier, FC extends FeatureConfiguration> { + BCLConfigureFeature get(BlockState state); + } + + private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12); + private final FeatureSupplier feature; + + public FeatureSaplingBlock(FeatureSupplier featureSupplier) { this( FabricBlockSettings.of(Material.PLANT) .collidable(false) @@ -54,7 +64,7 @@ public class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProv ); } - public FeatureSaplingBlock(int light, Function featureSupplier) { + public FeatureSaplingBlock(int light, FeatureSupplier featureSupplier) { this( FabricBlockSettings.of(Material.PLANT) .collidable(false) @@ -68,14 +78,60 @@ public class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProv public FeatureSaplingBlock( BlockBehaviour.Properties properties, - Function featureSupplier + FeatureSupplier featureSupplier ) { super(null, properties); this.feature = featureSupplier; } - protected BCLFeature getFeature(BlockState state) { - return feature.apply(state); + @Deprecated(forRemoval = true) + public FeatureSaplingBlock(Function featureSupplier) { + this( + FabricBlockSettings.of(Material.PLANT) + .collidable(false) + .instabreak() + .sound(SoundType.GRASS) + .randomTicks(), + featureSupplier + ); + } + + @Deprecated(forRemoval = true) + public FeatureSaplingBlock( + int light, + Function 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 featureSupplier + ) { + super(null, properties); + this.feature = (s) -> featureSupplier.apply(s).getConfFeature(); + } + + protected BCLConfigureFeature 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 @@ -103,7 +159,9 @@ public class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProv @Override 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 diff --git a/src/main/java/org/betterx/bclib/integration/ModIntegration.java b/src/main/java/org/betterx/bclib/integration/ModIntegration.java index a1e98ff8..f5a42211 100644 --- a/src/main/java/org/betterx/bclib/integration/ModIntegration.java +++ b/src/main/java/org/betterx/bclib/integration/ModIntegration.java @@ -64,6 +64,7 @@ public abstract class ModIntegration { return FabricLoader.getInstance().isModLoaded(modID); } + @Deprecated(forRemoval = true) public BCLFeature getFeature(String featureID, String placedFeatureID, GenerationStep.Decoration featureStep) { ResourceLocation id = getID(featureID); 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) { return getFeature(name, name, featureStep); } diff --git a/src/main/java/org/betterx/bclib/noise/Noises.java b/src/main/java/org/betterx/bclib/noise/Noises.java new file mode 100644 index 00000000..9022cbf7 --- /dev/null +++ b/src/main/java/org/betterx/bclib/noise/Noises.java @@ -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, NormalNoise> noiseIntances = new HashMap<>(); + public static final ResourceKey ROUGHNESS_NOISE = createKey(BCLib.makeID( + "roughness_noise")); + + public static ResourceKey createKey(ResourceLocation loc) { + return ResourceKey.create(Registry.NOISE_REGISTRY, loc); + } + + public static NormalNoise createNoise( + Registry registry, + RandomSource randomSource, + ResourceKey resourceKey + ) { + Holder holder = registry.getHolderOrThrow(resourceKey); + return NormalNoise.create(randomSource, holder.value()); + } + + public static NormalNoise getOrCreateNoise( + RegistryAccess registryAccess, + RandomSource randomSource, + ResourceKey noise + ) { + final Registry registry = registryAccess.registryOrThrow(Registry.NOISE_REGISTRY); + return noiseIntances.computeIfAbsent(noise, (key) -> createNoise(registry, randomSource, noise)); + } +} diff --git a/src/main/java/org/betterx/worlds/together/tag/v3/CommonBlockTags.java b/src/main/java/org/betterx/worlds/together/tag/v3/CommonBlockTags.java index 6aff8f21..fce9a26b 100644 --- a/src/main/java/org/betterx/worlds/together/tag/v3/CommonBlockTags.java +++ b/src/main/java/org/betterx/worlds/together/tag/v3/CommonBlockTags.java @@ -22,6 +22,7 @@ public class CommonBlockTags { public static final TagKey END_ORES = TagManager.BLOCKS.makeCommonTag("end_ores"); public static final TagKey SAPLINGS = TagManager.BLOCKS.makeCommonTag("saplings"); public static final TagKey SOUL_GROUND = TagManager.BLOCKS.makeCommonTag("soul_ground"); + public static final TagKey SCULK_LIKE = TagManager.BLOCKS.makeCommonTag("sculk_like"); public static final TagKey WOODEN_BARREL = TagManager.BLOCKS.makeCommonTag("wooden_barrels"); public static final TagKey WOODEN_CHEST = TagManager.BLOCKS.makeCommonTag("wooden_chests"); public static final TagKey WORKBENCHES = TagManager.BLOCKS.makeCommonTag("workbench"); @@ -35,6 +36,7 @@ public class CommonBlockTags { public static final TagKey NETHER_TERRAIN = TagManager.BLOCKS.makeCommonTag("nether_terrain"); static void prepareTags() { + TagManager.BLOCKS.add(SCULK_LIKE, Blocks.SCULK); TagManager.BLOCKS.addOtherTags(DRAGON_IMMUNE, BlockTags.DRAGON_IMMUNE); TagManager.BLOCKS.add(END_STONES, Blocks.END_STONE); @@ -84,8 +86,7 @@ public class CommonBlockTags { Blocks.GRAVEL, Blocks.RED_SAND, Blocks.GLOWSTONE, - Blocks.BONE_BLOCK, - Blocks.SCULK + Blocks.BONE_BLOCK ); TagManager.BLOCKS.addOtherTags( NETHER_TERRAIN,