Features for Crimson Glowing Woods
This commit is contained in:
parent
4f4ac722b1
commit
90921451dd
5 changed files with 47 additions and 14 deletions
|
@ -27,7 +27,7 @@ public class BCLFeature {
|
||||||
BCLib.makeID("scatter_on_solid"),
|
BCLib.makeID("scatter_on_solid"),
|
||||||
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC));
|
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC));
|
||||||
|
|
||||||
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECT = register(
|
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = register(
|
||||||
BCLib.makeID("random_select"),
|
BCLib.makeID("random_select"),
|
||||||
new WeightedRandomSelectorFeature());
|
new WeightedRandomSelectorFeature());
|
||||||
public static final Feature<TemplateFeatureConfig> TEMPLATE = register(BCLib.makeID("template"),
|
public static final Feature<TemplateFeatureConfig> TEMPLATE = register(BCLib.makeID("template"),
|
||||||
|
|
|
@ -26,14 +26,13 @@ public class WeightedRandomSelectorFeature extends Feature<RandomFeatureConfigur
|
||||||
if (!cfg.features.isEmpty()) {
|
if (!cfg.features.isEmpty()) {
|
||||||
final float totalWeight = cfg.features.stream().map(w -> w.chance).reduce(0.0f, (p, c) -> p + c);
|
final float totalWeight = cfg.features.stream().map(w -> w.chance).reduce(0.0f, (p, c) -> p + c);
|
||||||
float bar = random.nextFloat() * totalWeight;
|
float bar = random.nextFloat() * totalWeight;
|
||||||
|
|
||||||
for (WeightedPlacedFeature f : cfg.features) {
|
for (WeightedPlacedFeature f : cfg.features) {
|
||||||
selected = f.feature.value();
|
selected = f.feature.value();
|
||||||
bar -= f.chance;
|
bar -= f.chance;
|
||||||
if (bar < 0) break;
|
if (bar < 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return selected.place(level, generator, random, pos);
|
return selected.place(level, generator, random, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package org.betterx.bclib.api.features.placement;
|
package org.betterx.bclib.api.features.placement;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.Vec3i;
|
||||||
import net.minecraft.util.RandomSource;
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.level.WorldGenLevel;
|
import net.minecraft.world.level.WorldGenLevel;
|
||||||
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
|
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
|
||||||
|
@ -11,29 +13,40 @@ import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class Is extends PlacementFilter {
|
public class Is extends PlacementFilter {
|
||||||
public static final Codec<Is> CODEC = RecordCodecBuilder.create((instance) -> instance
|
public static final Codec<Is> CODEC = RecordCodecBuilder.create((instance) -> instance
|
||||||
.group(
|
.group(
|
||||||
BlockPredicate.CODEC
|
BlockPredicate.CODEC
|
||||||
.fieldOf("predicate")
|
.fieldOf("predicate")
|
||||||
.forGetter(cfg -> cfg.predicate)
|
.forGetter(cfg -> cfg.predicate),
|
||||||
|
Vec3i.CODEC
|
||||||
|
.optionalFieldOf("offset")
|
||||||
|
.forGetter(cfg -> cfg.offset)
|
||||||
)
|
)
|
||||||
.apply(instance, Is::new));
|
.apply(instance, Is::new));
|
||||||
|
|
||||||
private final BlockPredicate predicate;
|
private final BlockPredicate predicate;
|
||||||
|
private final Optional<Vec3i> offset;
|
||||||
|
|
||||||
public Is(BlockPredicate predicate) {
|
public Is(BlockPredicate predicate, Optional<Vec3i> offset) {
|
||||||
this.predicate = predicate;
|
this.predicate = predicate;
|
||||||
|
this.offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Is simple(BlockPredicate predicate) {
|
public static Is simple(BlockPredicate predicate) {
|
||||||
return new Is(predicate);
|
return new Is(predicate, Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Is below(BlockPredicate predicate) {
|
||||||
|
return new Is(predicate, Optional.of(Direction.DOWN.getNormal()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
|
protected boolean shouldPlace(PlacementContext ctx, RandomSource random, BlockPos pos) {
|
||||||
WorldGenLevel level = ctx.getLevel();
|
WorldGenLevel level = ctx.getLevel();
|
||||||
return predicate.test(level, pos);
|
return predicate.test(level, offset.map(v -> pos.offset(v.getX(), v.getY(), v.getZ())).orElse(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -10,24 +10,40 @@ import net.minecraft.world.level.levelgen.placement.PlacementModifier;
|
||||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
|
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
import org.betterx.bclib.util.BlocksHelper;
|
import org.betterx.bclib.util.BlocksHelper;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class OnEveryLayer
|
public class OnEveryLayer
|
||||||
extends PlacementModifier {
|
extends PlacementModifier {
|
||||||
private static OnEveryLayer INSTANCE = new OnEveryLayer();
|
private static OnEveryLayer INSTANCE = new OnEveryLayer(Optional.empty(), Optional.empty());
|
||||||
public static final Codec<OnEveryLayer> CODEC = Codec.unit(() -> INSTANCE);
|
private static OnEveryLayer INSTANCE_MIN_4 = new OnEveryLayer(Optional.of(4), Optional.empty());
|
||||||
|
public static final Codec<OnEveryLayer> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||||
|
.group(
|
||||||
|
Codec.INT.optionalFieldOf("min").forGetter(o -> o.minHeight),
|
||||||
|
Codec.INT.optionalFieldOf("max").forGetter(o -> o.maxHeight)
|
||||||
|
).apply(instance, OnEveryLayer::new));
|
||||||
|
|
||||||
|
|
||||||
private OnEveryLayer() {
|
private final Optional<Integer> minHeight;
|
||||||
|
private final Optional<Integer> maxHeight;
|
||||||
|
|
||||||
|
private OnEveryLayer(Optional<Integer> minHeight, Optional<Integer> maxHeight) {
|
||||||
|
this.minHeight = minHeight;
|
||||||
|
|
||||||
|
this.maxHeight = maxHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OnEveryLayer simple() {
|
public static OnEveryLayer simple() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OnEveryLayer min4() {
|
||||||
|
return INSTANCE_MIN_4;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stream<BlockPos> getPositions(PlacementContext ctx,
|
public Stream<BlockPos> getPositions(PlacementContext ctx,
|
||||||
RandomSource random,
|
RandomSource random,
|
||||||
|
@ -37,10 +53,14 @@ public class OnEveryLayer
|
||||||
|
|
||||||
final int z = pos.getZ();
|
final int z = pos.getZ();
|
||||||
final int x = pos.getX();
|
final int x = pos.getX();
|
||||||
int y = ctx.getHeight(Heightmap.Types.MOTION_BLOCKING, x, z);
|
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;
|
int layerY;
|
||||||
do {
|
do {
|
||||||
layerY = OnEveryLayer.findOnGroundYPosition(ctx, x, y, z);
|
layerY = OnEveryLayer.findOnGroundYPosition(ctx, x, y, z, minHeight);
|
||||||
if (layerY != Integer.MAX_VALUE) {
|
if (layerY != Integer.MAX_VALUE) {
|
||||||
builder.add(new BlockPos(x, layerY, z));
|
builder.add(new BlockPos(x, layerY, z));
|
||||||
y = layerY - 1;
|
y = layerY - 1;
|
||||||
|
@ -55,10 +75,10 @@ public class OnEveryLayer
|
||||||
return PlacementModifiers.ON_EVERY_LAYER;
|
return PlacementModifiers.ON_EVERY_LAYER;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int findOnGroundYPosition(PlacementContext ctx, int x, int startY, int z) {
|
private static int findOnGroundYPosition(PlacementContext ctx, int x, int startY, int z, int minHeight) {
|
||||||
BlockPos.MutableBlockPos mPos = new BlockPos.MutableBlockPos(x, startY, z);
|
BlockPos.MutableBlockPos mPos = new BlockPos.MutableBlockPos(x, startY, z);
|
||||||
BlockState nowState = ctx.getBlockState(mPos);
|
BlockState nowState = ctx.getBlockState(mPos);
|
||||||
for (int y = startY; y >= ctx.getMinBuildHeight() + 1; --y) {
|
for (int y = startY; y >= minHeight + 1; --y) {
|
||||||
mPos.setY(y - 1);
|
mPos.setY(y - 1);
|
||||||
BlockState belowState = ctx.getBlockState(mPos);
|
BlockState belowState = ctx.getBlockState(mPos);
|
||||||
if (BlocksHelper.isTerrain(belowState) && BlocksHelper.isFreeOrFluid(nowState) && !belowState.is(Blocks.BEDROCK)) {
|
if (BlocksHelper.isTerrain(belowState) && BlocksHelper.isFreeOrFluid(nowState) && !belowState.is(Blocks.BEDROCK)) {
|
||||||
|
|
|
@ -58,6 +58,7 @@ public class CommonBlockTags {
|
||||||
TagAPI.BLOCKS.addOtherTags(TERRAIN,
|
TagAPI.BLOCKS.addOtherTags(TERRAIN,
|
||||||
BlockTags.DRIPSTONE_REPLACEABLE,
|
BlockTags.DRIPSTONE_REPLACEABLE,
|
||||||
BlockTags.BASE_STONE_OVERWORLD,
|
BlockTags.BASE_STONE_OVERWORLD,
|
||||||
|
BlockTags.NYLIUM,
|
||||||
NETHER_STONES,
|
NETHER_STONES,
|
||||||
NETHER_ORES,
|
NETHER_ORES,
|
||||||
SOUL_GROUND,
|
SOUL_GROUND,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue