UpsideDownForest

This commit is contained in:
Frank 2022-06-07 02:39:12 +02:00
parent 56e63f3ce2
commit 2ac472f716
8 changed files with 252 additions and 20 deletions

View file

@ -747,6 +747,11 @@ public class BiomeAPI {
public static void applyModifications(BiomeSource source, ResourceKey<LevelStem> dimension) {
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();
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(dimension);
for (Holder<Biome> biomeHolder : biomes) {

View file

@ -30,6 +30,14 @@ public class BCLFeature<F extends Feature<FC>, FC extends FeatureConfiguration>
BCLib.makeID("scatter_on_solid"),
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC));
public static final Feature<ScatterFeatureConfig.ExtendTop> SCATTER_EXTEND_TOP = register(
BCLib.makeID("scatter_extend_top"),
new ScatterFeature<>(ScatterFeatureConfig.ExtendTop.CODEC));
public static final Feature<ScatterFeatureConfig.ExtendBottom> SCATTER_EXTEND_BOTTOM = register(
BCLib.makeID("scatter_extend_bottom"),
new ScatterFeature<>(ScatterFeatureConfig.ExtendBottom.CODEC));
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = register(
BCLib.makeID("random_select"),
new WeightedRandomSelectorFeature());

View file

@ -245,6 +245,10 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
return modifier(OnEveryLayer.simple());
}
public BCLFeatureBuilder underEveryLayer() {
return modifier(UnderEveryLayer.simple());
}
public BCLFeatureBuilder spreadHorizontal(IntProvider 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())));
}
public BCLFeatureBuilder isUnder(BlockPredicate... predicates) {
return modifier(new Is(BlockPredicate.anyOf(predicates), Optional.of(Direction.UP.getNormal())));
}
public BCLFeatureBuilder findSolidCeil(int distance) {
return modifier(FindSolidInDirection.up(distance));
}

View file

@ -145,6 +145,7 @@ public class FastFeatures {
)));
}
public static <FC extends FeatureConfiguration> BCLFeature
simple(ResourceLocation location,
int searchDist,
@ -166,6 +167,7 @@ public class FastFeatures {
return patch(location, 96, 7, 3, feature, FeatureConfiguration.NONE);
}
public static BCLFeature
patch(ResourceLocation location,
int attempts,
@ -175,6 +177,7 @@ public class FastFeatures {
return patch(location, attempts, xzSpread, ySpread, feature, FeatureConfiguration.NONE);
}
public static <FC extends FeatureConfiguration> BCLFeature
patch(ResourceLocation location,
int attempts,
@ -209,4 +212,6 @@ public class FastFeatures {
.start(patchLocation, Feature.RANDOM_PATCH)
.buildAndRegister(new RandomPatchConfiguration(attempts, xzSpread, ySpread, single.getPlacedFeature()));
}
}

View file

@ -344,24 +344,28 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration {
}
}
public static Builder<OnSolid> startOnSolid() {
return Builder.start(OnSolid::new);
}
public static class OnSolid extends ScatterFeatureConfig {
public static final Codec<OnSolid> CODEC = buildCodec(OnSolid::new);
public OnSolid(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) {
protected OnSolid(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,
@ -380,11 +384,6 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration {
}
public static Builder<OnSolid> startOnSolid() {
return Builder.start(OnSolid::new);
}
@Override
public boolean isValidBase(BlockState 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);
}
}
}

View file

@ -49,6 +49,10 @@ public class PlacementModifiers {
"on_every_layer",
OnEveryLayer.CODEC);
public static final PlacementModifierType<UnderEveryLayer> UNDER_EVERY_LAYER = register(
"under_every_layer",
UnderEveryLayer.CODEC);
private static <P extends PlacementModifier> PlacementModifierType<P> register(String path, Codec<P> codec) {
return register(BCLib.makeID(path), codec);

View file

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

View file

@ -40,5 +40,8 @@ public class NamedBlockTags {
static {
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);
}
}