UpsideDownForest
This commit is contained in:
parent
56e63f3ce2
commit
2ac472f716
8 changed files with 252 additions and 20 deletions
|
@ -747,6 +747,11 @@ public class BiomeAPI {
|
||||||
|
|
||||||
public static void applyModifications(BiomeSource source, ResourceKey<LevelStem> dimension) {
|
public static void applyModifications(BiomeSource source, ResourceKey<LevelStem> dimension) {
|
||||||
BCLib.LOGGER.info("Apply Modifications for " + dimension.location() + " BiomeSource " + source);
|
BCLib.LOGGER.info("Apply Modifications for " + dimension.location() + " BiomeSource " + source);
|
||||||
|
/*if (dimension.location().equals(LevelStem.NETHER)){
|
||||||
|
if (source instanceof BCLBiomeSource s) {
|
||||||
|
NetherBiomes.useLegacyGeneration = s.biomeSourceVersion==BCLBiomeSource.BIOME_SOURCE_VERSION_SQUARE;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
final Set<Holder<Biome>> biomes = source.possibleBiomes();
|
final Set<Holder<Biome>> biomes = source.possibleBiomes();
|
||||||
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(dimension);
|
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(dimension);
|
||||||
for (Holder<Biome> biomeHolder : biomes) {
|
for (Holder<Biome> biomeHolder : biomes) {
|
||||||
|
|
|
@ -30,6 +30,14 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
|
||||||
BCLib.makeID("scatter_on_solid"),
|
BCLib.makeID("scatter_on_solid"),
|
||||||
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC));
|
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC));
|
||||||
|
|
||||||
|
public static final Feature<ScatterFeatureConfig.ExtendTop> SCATTER_EXTEND_TOP = register(
|
||||||
|
BCLib.makeID("scatter_extend_top"),
|
||||||
|
new ScatterFeature<>(ScatterFeatureConfig.ExtendTop.CODEC));
|
||||||
|
|
||||||
|
public static final Feature<ScatterFeatureConfig.ExtendBottom> SCATTER_EXTEND_BOTTOM = register(
|
||||||
|
BCLib.makeID("scatter_extend_bottom"),
|
||||||
|
new ScatterFeature<>(ScatterFeatureConfig.ExtendBottom.CODEC));
|
||||||
|
|
||||||
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = register(
|
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = register(
|
||||||
BCLib.makeID("random_select"),
|
BCLib.makeID("random_select"),
|
||||||
new WeightedRandomSelectorFeature());
|
new WeightedRandomSelectorFeature());
|
||||||
|
|
|
@ -245,6 +245,10 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
|
||||||
return modifier(OnEveryLayer.simple());
|
return modifier(OnEveryLayer.simple());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BCLFeatureBuilder underEveryLayer() {
|
||||||
|
return modifier(UnderEveryLayer.simple());
|
||||||
|
}
|
||||||
|
|
||||||
public BCLFeatureBuilder spreadHorizontal(IntProvider p) {
|
public BCLFeatureBuilder spreadHorizontal(IntProvider p) {
|
||||||
return modifier(RandomOffsetPlacement.horizontal(p));
|
return modifier(RandomOffsetPlacement.horizontal(p));
|
||||||
}
|
}
|
||||||
|
@ -300,6 +304,10 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
|
||||||
return modifier(new Is(BlockPredicate.anyOf(predicates), Optional.of(Direction.DOWN.getNormal())));
|
return modifier(new Is(BlockPredicate.anyOf(predicates), Optional.of(Direction.DOWN.getNormal())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BCLFeatureBuilder isUnder(BlockPredicate... predicates) {
|
||||||
|
return modifier(new Is(BlockPredicate.anyOf(predicates), Optional.of(Direction.UP.getNormal())));
|
||||||
|
}
|
||||||
|
|
||||||
public BCLFeatureBuilder findSolidCeil(int distance) {
|
public BCLFeatureBuilder findSolidCeil(int distance) {
|
||||||
return modifier(FindSolidInDirection.up(distance));
|
return modifier(FindSolidInDirection.up(distance));
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,6 +145,7 @@ public class FastFeatures {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static <FC extends FeatureConfiguration> BCLFeature
|
public static <FC extends FeatureConfiguration> BCLFeature
|
||||||
simple(ResourceLocation location,
|
simple(ResourceLocation location,
|
||||||
int searchDist,
|
int searchDist,
|
||||||
|
@ -166,6 +167,7 @@ public class FastFeatures {
|
||||||
return patch(location, 96, 7, 3, feature, FeatureConfiguration.NONE);
|
return patch(location, 96, 7, 3, feature, FeatureConfiguration.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static BCLFeature
|
public static BCLFeature
|
||||||
patch(ResourceLocation location,
|
patch(ResourceLocation location,
|
||||||
int attempts,
|
int attempts,
|
||||||
|
@ -175,6 +177,7 @@ public class FastFeatures {
|
||||||
return patch(location, attempts, xzSpread, ySpread, feature, FeatureConfiguration.NONE);
|
return patch(location, attempts, xzSpread, ySpread, feature, FeatureConfiguration.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static <FC extends FeatureConfiguration> BCLFeature
|
public static <FC extends FeatureConfiguration> BCLFeature
|
||||||
patch(ResourceLocation location,
|
patch(ResourceLocation location,
|
||||||
int attempts,
|
int attempts,
|
||||||
|
@ -209,4 +212,6 @@ public class FastFeatures {
|
||||||
.start(patchLocation, Feature.RANDOM_PATCH)
|
.start(patchLocation, Feature.RANDOM_PATCH)
|
||||||
.buildAndRegister(new RandomPatchConfiguration(attempts, xzSpread, ySpread, single.getPlacedFeature()));
|
.buildAndRegister(new RandomPatchConfiguration(attempts, xzSpread, ySpread, single.getPlacedFeature()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -344,10 +344,14 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Builder<OnSolid> startOnSolid() {
|
||||||
|
return Builder.start(OnSolid::new);
|
||||||
|
}
|
||||||
|
|
||||||
public static class OnSolid extends ScatterFeatureConfig {
|
public static class OnSolid extends ScatterFeatureConfig {
|
||||||
public static final Codec<OnSolid> CODEC = buildCodec(OnSolid::new);
|
public static final Codec<OnSolid> CODEC = buildCodec(OnSolid::new);
|
||||||
|
|
||||||
public OnSolid(BlockStateProvider clusterBlock,
|
protected OnSolid(BlockStateProvider clusterBlock,
|
||||||
Optional<BlockStateProvider> tipBlock,
|
Optional<BlockStateProvider> tipBlock,
|
||||||
Optional<BlockStateProvider> bottomBlock,
|
Optional<BlockStateProvider> bottomBlock,
|
||||||
Optional<BlockState> baseState,
|
Optional<BlockState> baseState,
|
||||||
|
@ -380,11 +384,6 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Builder<OnSolid> startOnSolid() {
|
|
||||||
return Builder.start(OnSolid::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidBase(BlockState state) {
|
public boolean isValidBase(BlockState state) {
|
||||||
return BlocksHelper.isTerrain(state)
|
return BlocksHelper.isTerrain(state)
|
||||||
|
@ -400,4 +399,113 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Builder<ExtendTop> startExtendTop() {
|
||||||
|
return Builder.start(ExtendTop::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ExtendTop extends ScatterFeatureConfig {
|
||||||
|
public static final Codec<ExtendTop> CODEC = buildCodec(ExtendTop::new);
|
||||||
|
|
||||||
|
protected ExtendTop(BlockStateProvider clusterBlock,
|
||||||
|
Optional<BlockStateProvider> tipBlock,
|
||||||
|
Optional<BlockStateProvider> bottomBlock,
|
||||||
|
Optional<BlockState> baseState,
|
||||||
|
float baseReplaceChance,
|
||||||
|
float chanceOfDirectionalSpread,
|
||||||
|
float chanceOfSpreadRadius2,
|
||||||
|
float chanceOfSpreadRadius3,
|
||||||
|
int minHeight,
|
||||||
|
int maxHeight,
|
||||||
|
float maxSpread,
|
||||||
|
float sizeVariation,
|
||||||
|
float floorChance,
|
||||||
|
boolean growWhileFree,
|
||||||
|
IntProvider spreadCount) {
|
||||||
|
super(clusterBlock,
|
||||||
|
tipBlock,
|
||||||
|
bottomBlock,
|
||||||
|
baseState,
|
||||||
|
baseReplaceChance,
|
||||||
|
chanceOfDirectionalSpread,
|
||||||
|
chanceOfSpreadRadius2,
|
||||||
|
chanceOfSpreadRadius3,
|
||||||
|
minHeight,
|
||||||
|
maxHeight,
|
||||||
|
maxSpread,
|
||||||
|
sizeVariation,
|
||||||
|
floorChance,
|
||||||
|
growWhileFree,
|
||||||
|
spreadCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidBase(BlockState state) {
|
||||||
|
return BlocksHelper.isTerrain(state)
|
||||||
|
|| baseState.map(s -> state.is(s.getBlock())).orElse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState createBlock(int height, int maxHeight, RandomSource random, BlockPos pos) {
|
||||||
|
if (height == 0) return this.bottomBlock.getState(random, pos);
|
||||||
|
if (height == 1) return this.clusterBlock.getState(random, pos);
|
||||||
|
return this.tipBlock.getState(random, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder<ExtendBottom> startExtendBottom() {
|
||||||
|
return Builder.start(ExtendBottom::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ExtendBottom extends ScatterFeatureConfig {
|
||||||
|
public static final Codec<ExtendBottom> CODEC = buildCodec(ExtendBottom::new);
|
||||||
|
|
||||||
|
protected ExtendBottom(BlockStateProvider clusterBlock,
|
||||||
|
Optional<BlockStateProvider> tipBlock,
|
||||||
|
Optional<BlockStateProvider> bottomBlock,
|
||||||
|
Optional<BlockState> baseState,
|
||||||
|
float baseReplaceChance,
|
||||||
|
float chanceOfDirectionalSpread,
|
||||||
|
float chanceOfSpreadRadius2,
|
||||||
|
float chanceOfSpreadRadius3,
|
||||||
|
int minHeight,
|
||||||
|
int maxHeight,
|
||||||
|
float maxSpread,
|
||||||
|
float sizeVariation,
|
||||||
|
float floorChance,
|
||||||
|
boolean growWhileFree,
|
||||||
|
IntProvider spreadCount) {
|
||||||
|
super(clusterBlock,
|
||||||
|
tipBlock,
|
||||||
|
bottomBlock,
|
||||||
|
baseState,
|
||||||
|
baseReplaceChance,
|
||||||
|
chanceOfDirectionalSpread,
|
||||||
|
chanceOfSpreadRadius2,
|
||||||
|
chanceOfSpreadRadius3,
|
||||||
|
minHeight,
|
||||||
|
maxHeight,
|
||||||
|
maxSpread,
|
||||||
|
sizeVariation,
|
||||||
|
floorChance,
|
||||||
|
growWhileFree,
|
||||||
|
spreadCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidBase(BlockState state) {
|
||||||
|
return BlocksHelper.isTerrain(state)
|
||||||
|
|| baseState.map(s -> state.is(s.getBlock())).orElse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState createBlock(int height, int maxHeight, RandomSource random, BlockPos pos) {
|
||||||
|
if (height == maxHeight) return this.tipBlock.getState(random, pos);
|
||||||
|
if (height == maxHeight - 1) return this.clusterBlock.getState(random, pos);
|
||||||
|
return this.bottomBlock.getState(random, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,10 @@ public class PlacementModifiers {
|
||||||
"on_every_layer",
|
"on_every_layer",
|
||||||
OnEveryLayer.CODEC);
|
OnEveryLayer.CODEC);
|
||||||
|
|
||||||
|
public static final PlacementModifierType<UnderEveryLayer> UNDER_EVERY_LAYER = register(
|
||||||
|
"under_every_layer",
|
||||||
|
UnderEveryLayer.CODEC);
|
||||||
|
|
||||||
|
|
||||||
private static <P extends PlacementModifier> PlacementModifierType<P> register(String path, Codec<P> codec) {
|
private static <P extends PlacementModifier> PlacementModifierType<P> register(String path, Codec<P> codec) {
|
||||||
return register(BCLib.makeID(path), codec);
|
return register(BCLib.makeID(path), codec);
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
package org.betterx.bclib.api.features.placement;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
|
import net.minecraft.world.level.levelgen.placement.PlacementContext;
|
||||||
|
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
|
||||||
|
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
import org.betterx.bclib.util.BlocksHelper;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class UnderEveryLayer
|
||||||
|
extends PlacementModifier {
|
||||||
|
private static UnderEveryLayer INSTANCE = new UnderEveryLayer(Optional.empty(), Optional.empty());
|
||||||
|
private static UnderEveryLayer INSTANCE_MIN_4 = new UnderEveryLayer(Optional.of(4), Optional.empty());
|
||||||
|
public static final Codec<UnderEveryLayer> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||||
|
.group(
|
||||||
|
Codec.INT.optionalFieldOf("min").forGetter(o -> o.minHeight),
|
||||||
|
Codec.INT.optionalFieldOf("max").forGetter(o -> o.maxHeight)
|
||||||
|
).apply(instance, UnderEveryLayer::new));
|
||||||
|
|
||||||
|
|
||||||
|
private final Optional<Integer> minHeight;
|
||||||
|
private final Optional<Integer> maxHeight;
|
||||||
|
|
||||||
|
private UnderEveryLayer(Optional<Integer> minHeight, Optional<Integer> maxHeight) {
|
||||||
|
this.minHeight = minHeight;
|
||||||
|
|
||||||
|
this.maxHeight = maxHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnderEveryLayer simple() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnderEveryLayer min4() {
|
||||||
|
return INSTANCE_MIN_4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<BlockPos> getPositions(PlacementContext ctx,
|
||||||
|
RandomSource random,
|
||||||
|
BlockPos pos) {
|
||||||
|
|
||||||
|
Stream.Builder<BlockPos> builder = Stream.builder();
|
||||||
|
|
||||||
|
final int z = pos.getZ();
|
||||||
|
final int x = pos.getX();
|
||||||
|
final int levelHeight = ctx.getHeight(Heightmap.Types.MOTION_BLOCKING, x, z);
|
||||||
|
final int minLevelHeight = ctx.getMinBuildHeight();
|
||||||
|
int y = maxHeight.map(h -> Math.min(levelHeight, h)).orElse(levelHeight);
|
||||||
|
final int minHeight = this.minHeight.map(h -> Math.max(minLevelHeight, h)).orElse(minLevelHeight);
|
||||||
|
|
||||||
|
int layerY;
|
||||||
|
do {
|
||||||
|
layerY = findUnderGroundYPosition(ctx, x, y, z, minHeight);
|
||||||
|
if (layerY != Integer.MAX_VALUE) {
|
||||||
|
builder.add(new BlockPos(x, layerY, z));
|
||||||
|
y = layerY - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (layerY != Integer.MAX_VALUE);
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlacementModifierType<UnderEveryLayer> type() {
|
||||||
|
return PlacementModifiers.UNDER_EVERY_LAYER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int findUnderGroundYPosition(PlacementContext ctx, int x, int startY, int z, int minHeight) {
|
||||||
|
BlockPos.MutableBlockPos mPos = new BlockPos.MutableBlockPos(x, startY, z);
|
||||||
|
BlockState nowState = ctx.getBlockState(mPos);
|
||||||
|
for (int y = startY; y >= minHeight + 1; --y) {
|
||||||
|
mPos.setY(y - 1);
|
||||||
|
BlockState belowState = ctx.getBlockState(mPos);
|
||||||
|
if (BlocksHelper.isTerrain(nowState) && BlocksHelper.isFreeOrFluid(belowState) && !nowState.is(Blocks.BEDROCK)) {
|
||||||
|
return mPos.getY();
|
||||||
|
}
|
||||||
|
nowState = belowState;
|
||||||
|
}
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,5 +40,8 @@ public class NamedBlockTags {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
TagAPI.BLOCKS.add(BlockTags.NETHER_CARVER_REPLACEABLES, Blocks.RED_SAND, Blocks.MAGMA_BLOCK);
|
TagAPI.BLOCKS.add(BlockTags.NETHER_CARVER_REPLACEABLES, Blocks.RED_SAND, Blocks.MAGMA_BLOCK);
|
||||||
|
TagAPI.BLOCKS.addOtherTags(BlockTags.NETHER_CARVER_REPLACEABLES,
|
||||||
|
CommonBlockTags.NETHER_STONES,
|
||||||
|
CommonBlockTags.NETHERRACK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue