Refactoring and CrimsonPinewood
This commit is contained in:
parent
90921451dd
commit
97a65a3707
20 changed files with 626 additions and 182 deletions
|
@ -15,6 +15,7 @@ import org.betterx.bclib.api.WorldDataAPI;
|
|||
import org.betterx.bclib.api.dataexchange.DataExchangeAPI;
|
||||
import org.betterx.bclib.api.dataexchange.handler.autosync.*;
|
||||
import org.betterx.bclib.api.features.placement.PlacementModifiers;
|
||||
import org.betterx.bclib.api.surface.rules.Conditions;
|
||||
import org.betterx.bclib.api.tag.TagAPI;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
import org.betterx.bclib.presets.worldgen.BCLWorldPresets;
|
||||
|
@ -49,6 +50,7 @@ public class BCLib implements ModInitializer {
|
|||
DataExchangeAPI.registerMod(MOD_ID);
|
||||
BCLWorldPresets.registerPresets();
|
||||
AnvilRecipe.register();
|
||||
Conditions.registerAll();
|
||||
|
||||
DataExchangeAPI.registerDescriptors(List.of(
|
||||
HelloClient.DESCRIPTOR,
|
||||
|
|
|
@ -16,6 +16,7 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
|||
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.features.config.PlaceFacingBlockConfig;
|
||||
import org.betterx.bclib.api.features.config.ScatterFeatureConfig;
|
||||
import org.betterx.bclib.api.features.config.TemplateFeatureConfig;
|
||||
|
||||
|
@ -23,6 +24,9 @@ import java.util.Map.Entry;
|
|||
import java.util.Optional;
|
||||
|
||||
public class BCLFeature {
|
||||
public static final Feature<PlaceFacingBlockConfig> PLACE_BLOCK = register(
|
||||
BCLib.makeID("place_block"),
|
||||
new PlaceBlockFeature<>(PlaceFacingBlockConfig.CODEC));
|
||||
public static final Feature<ScatterFeatureConfig.OnSolid> SCATTER_ON_SOLID = register(
|
||||
BCLib.makeID("scatter_on_solid"),
|
||||
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC));
|
||||
|
|
|
@ -297,8 +297,8 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
|
|||
return modifier(new FindSolidInDirection(dir, distance));
|
||||
}
|
||||
|
||||
public BCLFeatureBuilder findSolidSurface(List<Direction> dir, int distance) {
|
||||
return modifier(new FindSolidInDirection(dir, distance));
|
||||
public BCLFeatureBuilder findSolidSurface(List<Direction> dir, int distance, boolean randomSelect) {
|
||||
return modifier(new FindSolidInDirection(dir, distance, randomSelect));
|
||||
}
|
||||
|
||||
public BCLFeatureBuilder heightmap() {
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import org.betterx.bclib.api.features.config.BlockPlaceFeatureConfig;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class BlockPlaceFeature<FC extends BlockPlaceFeatureConfig> extends Feature<FC> {
|
||||
public BlockPlaceFeature(Codec<FC> codec) {
|
||||
super(codec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<FC> ctx) {
|
||||
Optional<BlockState> state = ctx.config().getRandomBlock(ctx.random());
|
||||
if (state.isPresent())
|
||||
BlocksHelper.setWithoutUpdate(ctx.level(), ctx.origin(), state.get());
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.valueproviders.UniformInt;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
||||
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;
|
||||
|
@ -9,7 +12,9 @@ import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConf
|
|||
import net.minecraft.world.level.levelgen.feature.configurations.RandomPatchConfiguration;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.SimpleBlockConfiguration;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.RandomizedIntStateProvider;
|
||||
|
||||
import org.betterx.bclib.api.features.config.PlaceFacingBlockConfig;
|
||||
import org.betterx.bclib.api.features.config.ScatterFeatureConfig;
|
||||
|
||||
public class FastFeatures {
|
||||
|
@ -59,6 +64,24 @@ public class FastFeatures {
|
|||
new SimpleBlockConfiguration(BlockStateProvider.simple(block)));
|
||||
}
|
||||
|
||||
public static BCLFeature patchWitRandomInt(ResourceLocation location, Block block, IntegerProperty prop) {
|
||||
return patchWitRandomInt(location, block, prop, 96, 7, 3);
|
||||
}
|
||||
|
||||
public static BCLFeature
|
||||
patchWitRandomInt(ResourceLocation location,
|
||||
Block block,
|
||||
IntegerProperty prop,
|
||||
int attempts,
|
||||
int xzSpread,
|
||||
int ySpread) {
|
||||
return patch(location,
|
||||
attempts,
|
||||
xzSpread,
|
||||
ySpread,
|
||||
simple(location, ySpread, false, block.defaultBlockState(), prop));
|
||||
}
|
||||
|
||||
public static BCLFeature
|
||||
simple(ResourceLocation location,
|
||||
int searchDist,
|
||||
|
@ -67,6 +90,31 @@ public class FastFeatures {
|
|||
return simple(location, searchDist, rare, feature, NoneFeatureConfiguration.NONE);
|
||||
}
|
||||
|
||||
public static BCLFeature
|
||||
simple(ResourceLocation location,
|
||||
int searchDist,
|
||||
boolean rare,
|
||||
BlockState baseState,
|
||||
IntegerProperty property) {
|
||||
int min = Integer.MAX_VALUE;
|
||||
int max = Integer.MIN_VALUE;
|
||||
|
||||
for (Integer i : property.getPossibleValues()) {
|
||||
if (i < min) min = i;
|
||||
if (i > max) max = i;
|
||||
}
|
||||
|
||||
return simple(location,
|
||||
searchDist,
|
||||
rare,
|
||||
Feature.SIMPLE_BLOCK,
|
||||
new SimpleBlockConfiguration(new RandomizedIntStateProvider(
|
||||
BlockStateProvider.simple(baseState),
|
||||
property,
|
||||
UniformInt.of(min, max)
|
||||
)));
|
||||
}
|
||||
|
||||
public static <FC extends FeatureConfiguration> BCLFeature
|
||||
simple(ResourceLocation location,
|
||||
int searchDist,
|
||||
|
@ -104,11 +152,33 @@ public class FastFeatures {
|
|||
int ySpread,
|
||||
Feature<FC> feature,
|
||||
FC config) {
|
||||
ResourceLocation patchLocation = new ResourceLocation(location.getNamespace(), location.getPath() + "_patch");
|
||||
final BCLFeature SINGLE = simple(location, ySpread, false, feature, config);
|
||||
return patch(location, attempts, xzSpread, ySpread, SINGLE);
|
||||
}
|
||||
|
||||
public static BCLFeature
|
||||
wallPatch(ResourceLocation location,
|
||||
Block block,
|
||||
int attempts,
|
||||
int xzSpread,
|
||||
int ySpread) {
|
||||
final BCLFeature SINGLE = simple(location, ySpread, false, BCLFeature.PLACE_BLOCK,
|
||||
new PlaceFacingBlockConfig(block, PlaceFacingBlockConfig.HORIZONTAL));
|
||||
return patch(location, attempts, xzSpread, ySpread, SINGLE);
|
||||
}
|
||||
|
||||
public static BCLFeature
|
||||
patch(ResourceLocation location,
|
||||
int attempts,
|
||||
int xzSpread,
|
||||
int ySpread,
|
||||
BCLFeature single) {
|
||||
ResourceLocation patchLocation = new ResourceLocation(location.getNamespace(), location.getPath() + "_patch");
|
||||
|
||||
return BCLFeatureBuilder
|
||||
.start(patchLocation, Feature.RANDOM_PATCH)
|
||||
.buildAndRegister(new RandomPatchConfiguration(attempts, xzSpread, ySpread, SINGLE.getPlacedFeature()));
|
||||
.buildAndRegister(new RandomPatchConfiguration(attempts, xzSpread, ySpread, single.getPlacedFeature()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import org.betterx.bclib.api.features.config.PlaceBlockFeatureConfig;
|
||||
|
||||
public class PlaceBlockFeature<FC extends PlaceBlockFeatureConfig> extends Feature<FC> {
|
||||
public PlaceBlockFeature(Codec<FC> codec) {
|
||||
super(codec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<FC> ctx) {
|
||||
return ctx.config().place(ctx);
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package org.betterx.bclib.api.features.config;
|
||||
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.util.random.SimpleWeightedRandomList;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DataResult;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class BlockPlaceFeatureConfig implements FeatureConfiguration {
|
||||
public static final Codec<BlockPlaceFeatureConfig> CODEC = SimpleWeightedRandomList
|
||||
.wrappedCodec(BlockState.CODEC)
|
||||
.comapFlatMap(BlockPlaceFeatureConfig::create, cfg -> cfg.weightedList)
|
||||
.fieldOf("entries").codec();
|
||||
|
||||
private final SimpleWeightedRandomList<BlockState> weightedList;
|
||||
|
||||
private static DataResult<BlockPlaceFeatureConfig> create(SimpleWeightedRandomList<BlockState> simpleWeightedRandomList) {
|
||||
if (simpleWeightedRandomList.isEmpty()) {
|
||||
return DataResult.error("BlockPlaceFeatureConfig with no states");
|
||||
}
|
||||
return DataResult.success(new BlockPlaceFeatureConfig(simpleWeightedRandomList));
|
||||
}
|
||||
|
||||
|
||||
private static SimpleWeightedRandomList<BlockState> convert(List<BlockState> states) {
|
||||
var builder = SimpleWeightedRandomList.<BlockState>builder();
|
||||
for (BlockState s : states) builder.add(s, 1);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public BlockPlaceFeatureConfig(Block block) {
|
||||
this(block.defaultBlockState());
|
||||
}
|
||||
|
||||
public BlockPlaceFeatureConfig(BlockState state) {
|
||||
this(SimpleWeightedRandomList
|
||||
.<BlockState>builder()
|
||||
.add(state, 1)
|
||||
.build());
|
||||
}
|
||||
|
||||
public BlockPlaceFeatureConfig(List<BlockState> states) {
|
||||
this(convert(states));
|
||||
}
|
||||
|
||||
public BlockPlaceFeatureConfig(SimpleWeightedRandomList<BlockState> blocks) {
|
||||
this.weightedList = blocks;
|
||||
}
|
||||
|
||||
public Optional<BlockState> getRandomBlock(RandomSource random) {
|
||||
return this.weightedList.getRandomValue(random);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package org.betterx.bclib.api.features.config;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.util.random.SimpleWeightedRandomList;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class PlaceBlockFeatureConfig implements FeatureConfiguration {
|
||||
|
||||
protected static <T extends PlaceBlockFeatureConfig> RecordCodecBuilder<T, SimpleWeightedRandomList<BlockState>> blockStateCodec() {
|
||||
return SimpleWeightedRandomList
|
||||
.wrappedCodec(BlockState.CODEC)
|
||||
.fieldOf("entries")
|
||||
.forGetter((T o) -> o.weightedList);
|
||||
}
|
||||
|
||||
protected final SimpleWeightedRandomList<BlockState> weightedList;
|
||||
|
||||
|
||||
protected static SimpleWeightedRandomList<BlockState> buildWeightedList(List<BlockState> states) {
|
||||
var builder = SimpleWeightedRandomList.<BlockState>builder();
|
||||
for (BlockState s : states) builder.add(s, 1);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected static SimpleWeightedRandomList<BlockState> buildWeightedList(BlockState state) {
|
||||
return SimpleWeightedRandomList
|
||||
.<BlockState>builder()
|
||||
.add(state, 1)
|
||||
.build();
|
||||
}
|
||||
|
||||
public PlaceBlockFeatureConfig(Block block) {
|
||||
this(block.defaultBlockState());
|
||||
}
|
||||
|
||||
public PlaceBlockFeatureConfig(BlockState state) {
|
||||
this(buildWeightedList(state));
|
||||
}
|
||||
|
||||
|
||||
public PlaceBlockFeatureConfig(List<BlockState> states) {
|
||||
this(buildWeightedList(states));
|
||||
}
|
||||
|
||||
public PlaceBlockFeatureConfig(SimpleWeightedRandomList<BlockState> blocks) {
|
||||
this.weightedList = blocks;
|
||||
}
|
||||
|
||||
public Optional<BlockState> getRandomBlock(RandomSource random) {
|
||||
return this.weightedList.getRandomValue(random);
|
||||
}
|
||||
|
||||
public boolean place(FeaturePlaceContext<? extends PlaceBlockFeatureConfig> ctx) {
|
||||
Optional<BlockState> state = getRandomBlock(ctx.random());
|
||||
if (state.isPresent()) {
|
||||
return placeBlock(ctx, ctx.level(), ctx.origin(), state.get());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected abstract boolean placeBlock(FeaturePlaceContext<? extends PlaceBlockFeatureConfig> ctx,
|
||||
WorldGenLevel level,
|
||||
BlockPos pos,
|
||||
BlockState targetState);
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package org.betterx.bclib.api.features.config;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
import net.minecraft.util.random.SimpleWeightedRandomList;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PlaceFacingBlockConfig extends PlaceBlockFeatureConfig {
|
||||
public static final Codec<PlaceFacingBlockConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
blockStateCodec(),
|
||||
ExtraCodecs.nonEmptyList(Direction.CODEC.listOf())
|
||||
.fieldOf("dir")
|
||||
.orElse(List.of(Direction.NORTH))
|
||||
.forGetter(a -> a.directions)
|
||||
).apply(instance, PlaceFacingBlockConfig::new)
|
||||
);
|
||||
public static final List<Direction> HORIZONTAL = List.of(Direction.NORTH,
|
||||
Direction.EAST,
|
||||
Direction.WEST,
|
||||
Direction.SOUTH);
|
||||
public static final List<Direction> VERTICAL = List.of(Direction.UP, Direction.DOWN);
|
||||
public static final List<Direction> ALL = List.of(Direction.NORTH,
|
||||
Direction.EAST,
|
||||
Direction.SOUTH,
|
||||
Direction.WEST,
|
||||
Direction.UP,
|
||||
Direction.DOWN);
|
||||
|
||||
private final List<Direction> directions;
|
||||
|
||||
public PlaceFacingBlockConfig(Block block, List<Direction> dir) {
|
||||
this(block.defaultBlockState(), dir);
|
||||
}
|
||||
|
||||
public PlaceFacingBlockConfig(BlockState state, List<Direction> dir) {
|
||||
this(buildWeightedList(state), dir);
|
||||
}
|
||||
|
||||
public PlaceFacingBlockConfig(List<BlockState> states, List<Direction> dir) {
|
||||
this(buildWeightedList(states), dir);
|
||||
}
|
||||
|
||||
public PlaceFacingBlockConfig(SimpleWeightedRandomList<BlockState> blocks, List<Direction> dir) {
|
||||
super(blocks);
|
||||
directions = dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public boolean placeBlock(FeaturePlaceContext<? extends PlaceBlockFeatureConfig> ctx,
|
||||
WorldGenLevel level,
|
||||
BlockPos pos,
|
||||
BlockState targetState) {
|
||||
BlockState lookupState;
|
||||
for (Direction dir : directions) {
|
||||
lookupState = targetState.setValue(HorizontalDirectionalBlock.FACING, dir);
|
||||
if (lookupState.canSurvive(level, pos)) {
|
||||
BlocksHelper.setWithoutUpdate(level, pos, lookupState);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.util.valueproviders.IntProvider;
|
||||
import net.minecraft.util.valueproviders.UniformInt;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementContext;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
|
||||
|
@ -23,7 +25,9 @@ public class FindSolidInDirection extends PlacementModifier {
|
|||
.fieldOf("dir")
|
||||
.orElse(List.of(Direction.DOWN))
|
||||
.forGetter(a -> a.direction),
|
||||
Codec.intRange(1, 32).fieldOf("dist").orElse(12).forGetter((p) -> p.maxSearchDistance))
|
||||
Codec.intRange(1, 32).fieldOf("dist").orElse(12).forGetter((p) -> p.maxSearchDistance),
|
||||
Codec.BOOL.fieldOf("random:select").orElse(true).forGetter(p -> p.randomSelect)
|
||||
)
|
||||
.apply(instance,
|
||||
FindSolidInDirection::new));
|
||||
protected static final FindSolidInDirection DOWN = new FindSolidInDirection(Direction.DOWN, 6);
|
||||
|
@ -31,13 +35,23 @@ public class FindSolidInDirection extends PlacementModifier {
|
|||
private final List<Direction> direction;
|
||||
private final int maxSearchDistance;
|
||||
|
||||
private final boolean randomSelect;
|
||||
private final IntProvider provider;
|
||||
|
||||
|
||||
public FindSolidInDirection(Direction direction, int maxSearchDistance) {
|
||||
this(List.of(direction), maxSearchDistance);
|
||||
this(List.of(direction), maxSearchDistance, false);
|
||||
}
|
||||
|
||||
public FindSolidInDirection(List<Direction> direction, int maxSearchDistance) {
|
||||
this(direction, maxSearchDistance, direction.size() > 1);
|
||||
}
|
||||
|
||||
public FindSolidInDirection(List<Direction> direction, int maxSearchDistance, boolean randomSelect) {
|
||||
this.direction = direction;
|
||||
this.maxSearchDistance = maxSearchDistance;
|
||||
this.provider = UniformInt.of(0, direction.size() - 1);
|
||||
this.randomSelect = randomSelect;
|
||||
}
|
||||
|
||||
public static PlacementModifier down() {
|
||||
|
@ -59,24 +73,37 @@ public class FindSolidInDirection extends PlacementModifier {
|
|||
}
|
||||
|
||||
public Direction randomDirection(RandomSource random) {
|
||||
return direction.get(Math.max(0, Math.min(direction.size(), random.nextInt(direction.size()))));
|
||||
return direction.get(provider.sample(random));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<BlockPos> getPositions(PlacementContext placementContext,
|
||||
RandomSource randomSource,
|
||||
BlockPos blockPos) {
|
||||
var builder = Stream.<BlockPos>builder();
|
||||
if (randomSelect) {
|
||||
submitSingle(placementContext, blockPos, builder, randomDirection(randomSource));
|
||||
} else {
|
||||
for (Direction d : direction) {
|
||||
submitSingle(placementContext, blockPos, builder, d);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private void submitSingle(PlacementContext placementContext,
|
||||
BlockPos blockPos,
|
||||
Stream.Builder<BlockPos> builder,
|
||||
Direction d) {
|
||||
BlockPos.MutableBlockPos POS = blockPos.mutable();
|
||||
Direction d = randomDirection(randomSource);
|
||||
if (BlocksHelper.findOnSurroundingSurface(placementContext.getLevel(),
|
||||
POS,
|
||||
d,
|
||||
maxSearchDistance,
|
||||
BlocksHelper::isTerrain)) {
|
||||
return Stream.of(POS);
|
||||
builder.add(POS);
|
||||
}
|
||||
|
||||
return Stream.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,8 +10,9 @@ import net.minecraft.world.level.levelgen.placement.CaveSurface;
|
|||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.betterx.bclib.api.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.api.surface.rules.Conditions;
|
||||
import org.betterx.bclib.api.surface.rules.DoubleBlockSurfaceNoiseCondition;
|
||||
import org.betterx.bclib.api.surface.rules.NoiseCondition;
|
||||
import org.betterx.bclib.world.surface.DoubleBlockSurfaceNoiseCondition;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -96,7 +97,7 @@ public class SurfaceRuleBuilder {
|
|||
*/
|
||||
public SurfaceRuleBuilder filler(BlockState state) {
|
||||
entryInstance = getFromCache("fill_" + state.toString(),
|
||||
() -> new SurfaceRuleEntry(10, SurfaceRules.state(state)));
|
||||
() -> new SurfaceRuleEntry(10, SurfaceRules.state(state)));
|
||||
rules.add(entryInstance);
|
||||
return this;
|
||||
}
|
||||
|
@ -127,14 +128,14 @@ public class SurfaceRuleBuilder {
|
|||
public SurfaceRuleBuilder belowFloor(BlockState state, int height, NoiseCondition noise) {
|
||||
entryInstance = getFromCache("below_floor_" + height + "_" + state.toString() + "_" + noise.getClass()
|
||||
.getSimpleName(),
|
||||
() -> {
|
||||
RuleSource rule = SurfaceRules.state(state);
|
||||
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(height,
|
||||
false,
|
||||
CaveSurface.FLOOR),
|
||||
SurfaceRules.ifTrue(noise, rule));
|
||||
return new SurfaceRuleEntry(3, rule);
|
||||
});
|
||||
() -> {
|
||||
RuleSource rule = SurfaceRules.state(state);
|
||||
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(height,
|
||||
false,
|
||||
CaveSurface.FLOOR),
|
||||
SurfaceRules.ifTrue(noise, rule));
|
||||
return new SurfaceRuleEntry(3, rule);
|
||||
});
|
||||
rules.add(entryInstance);
|
||||
return this;
|
||||
}
|
||||
|
@ -237,7 +238,7 @@ public class SurfaceRuleBuilder {
|
|||
* @return same {@link SurfaceRuleBuilder} instance.
|
||||
*/
|
||||
public SurfaceRuleBuilder chancedFloor(BlockState surfaceBlockA, BlockState surfaceBlockB) {
|
||||
return chancedFloor(surfaceBlockA, surfaceBlockB, DoubleBlockSurfaceNoiseCondition.CONDITION);
|
||||
return chancedFloor(surfaceBlockA, surfaceBlockB, Conditions.DOUBLE_BLOCK_SURFACE_NOISE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -251,18 +252,37 @@ public class SurfaceRuleBuilder {
|
|||
public SurfaceRuleBuilder chancedFloor(BlockState surfaceBlockA, BlockState surfaceBlockB, NoiseCondition noise) {
|
||||
entryInstance = getFromCache("chancedFloor_" + surfaceBlockA + "_" + surfaceBlockB + "_" + noise.getClass()
|
||||
.getSimpleName(),
|
||||
() -> {
|
||||
RuleSource rule =
|
||||
SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR,
|
||||
SurfaceRules.sequence(
|
||||
SurfaceRules.ifTrue(noise,
|
||||
SurfaceRules.state(
|
||||
surfaceBlockA)),
|
||||
SurfaceRules.state(surfaceBlockB)
|
||||
)
|
||||
);
|
||||
return new SurfaceRuleEntry(4, rule);
|
||||
});
|
||||
() -> {
|
||||
RuleSource rule =
|
||||
SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR,
|
||||
SurfaceRules.sequence(
|
||||
SurfaceRules.ifTrue(noise,
|
||||
SurfaceRules.state(
|
||||
surfaceBlockA)),
|
||||
SurfaceRules.state(surfaceBlockB)
|
||||
)
|
||||
);
|
||||
return new SurfaceRuleEntry(4, rule);
|
||||
});
|
||||
rules.add(entryInstance);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SurfaceRuleBuilder chancedFloor(BlockState surfaceBlockA, RuleSource surfaceBlockB, NoiseCondition noise) {
|
||||
entryInstance = getFromCache("chancedFloor_" + surfaceBlockA + "_" + surfaceBlockB + "_" + noise.getClass()
|
||||
.getSimpleName(),
|
||||
() -> {
|
||||
RuleSource rule =
|
||||
SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR,
|
||||
SurfaceRules.sequence(
|
||||
SurfaceRules.ifTrue(noise,
|
||||
SurfaceRules.state(
|
||||
surfaceBlockA)),
|
||||
surfaceBlockB
|
||||
)
|
||||
);
|
||||
return new SurfaceRuleEntry(4, rule);
|
||||
});
|
||||
rules.add(entryInstance);
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package org.betterx.bclib.api.surface.rules;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.valueproviders.UniformFloat;
|
||||
import net.minecraft.world.level.levelgen.SurfaceRules;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.interfaces.NumericProvider;
|
||||
|
||||
public class Conditions {
|
||||
public static final ThresholdCondition DOUBLE_BLOCK_SURFACE_NOISE = new ThresholdCondition(4141,
|
||||
0,
|
||||
UniformFloat.of(-0.4f, 0.4f),
|
||||
0.1,
|
||||
0.1);
|
||||
|
||||
public static final ThresholdCondition FORREST_FLOOR_SURFACE_NOISE_A = new ThresholdCondition(614,
|
||||
0,
|
||||
UniformFloat.of(-0.2f, 0f),
|
||||
0.1,
|
||||
0.1);
|
||||
|
||||
public static final ThresholdCondition FORREST_FLOOR_SURFACE_NOISE_B = new ThresholdCondition(614,
|
||||
0,
|
||||
UniformFloat.of(-0.7f, -0.5f),
|
||||
0.1,
|
||||
0.1);
|
||||
|
||||
public static final ThresholdCondition NETHER_SURFACE_NOISE = new ThresholdCondition(245,
|
||||
0,
|
||||
UniformFloat.of(-0.7f, -0.5f),
|
||||
0.05,
|
||||
0.05);
|
||||
|
||||
public static final VolumeThresholdCondition NETHER_VOLUME_NOISE = new VolumeThresholdCondition(245,
|
||||
0,
|
||||
UniformFloat.of(-0.1f, 0.2f),
|
||||
0.1,
|
||||
0.2,
|
||||
0.1);
|
||||
|
||||
public static final NumericProvider NETHER_NOISE = new NetherNoiseCondition();
|
||||
|
||||
public static void register(ResourceLocation location, Codec<? extends SurfaceRules.ConditionSource> codec) {
|
||||
Registry.register(Registry.CONDITION, location, codec);
|
||||
}
|
||||
|
||||
public static void registerNumeric(ResourceLocation location, Codec<? extends NumericProvider> codec) {
|
||||
Registry.register(NumericProvider.NUMERIC_PROVIDER, location, codec);
|
||||
}
|
||||
|
||||
public static void registerAll() {
|
||||
registerNumeric(BCLib.makeID("rnd_int"), RandomIntProvider.CODEC);
|
||||
registerNumeric(BCLib.makeID("nether_noise"), NetherNoiseCondition.CODEC);
|
||||
register(BCLib.makeID("threshold_condition"), ThresholdCondition.CODEC);
|
||||
register(BCLib.makeID("volume_threshold_condition"), VolumeThresholdCondition.CODEC);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package org.betterx.bclib.api.surface.rules;
|
||||
|
||||
public class DoubleBlockSurfaceNoiseCondition {
|
||||
public static final ThresholdCondition CONDITION = Conditions.DOUBLE_BLOCK_SURFACE_NOISE;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package org.betterx.bclib.api.surface.rules;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import org.betterx.bclib.interfaces.NumericProvider;
|
||||
import org.betterx.bclib.mixin.common.SurfaceRulesContextAccessor;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
|
||||
public class NetherNoiseCondition implements NumericProvider {
|
||||
public static final Codec<NetherNoiseCondition> CODEC = Codec.BYTE.fieldOf("nether_noise")
|
||||
.xmap((obj) -> (NetherNoiseCondition) Conditions.NETHER_NOISE,
|
||||
obj -> (byte) 0)
|
||||
.codec();
|
||||
|
||||
|
||||
NetherNoiseCondition() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Codec<? extends NumericProvider> pcodec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumber(SurfaceRulesContextAccessor context) {
|
||||
final int x = context.getBlockX();
|
||||
final int y = context.getBlockY();
|
||||
final int z = context.getBlockZ();
|
||||
double value = Conditions.NETHER_VOLUME_NOISE.noiseContext.noise.eval(x * Conditions.NETHER_VOLUME_NOISE.scaleX,
|
||||
y * Conditions.NETHER_VOLUME_NOISE.scaleY,
|
||||
z * Conditions.NETHER_VOLUME_NOISE.scaleZ);
|
||||
|
||||
int offset = Conditions.NETHER_VOLUME_NOISE.noiseContext.random.nextInt(20) == 0 ? 3 : 0;
|
||||
|
||||
float cmp = MHelper.randRange(0.4F, 0.5F, Conditions.NETHER_VOLUME_NOISE.noiseContext.random);
|
||||
if (value > cmp || value < -cmp) return 2 + offset;
|
||||
|
||||
if (value > Conditions.NETHER_VOLUME_NOISE.range.sample(Conditions.NETHER_VOLUME_NOISE.noiseContext.random))
|
||||
return 0 + offset;
|
||||
|
||||
return 1 + offset;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
package org.betterx.bclib.api.surface.rules;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.interfaces.NumericProvider;
|
||||
import org.betterx.bclib.mixin.common.SurfaceRulesContextAccessor;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
|
@ -24,6 +21,6 @@ public record RandomIntProvider(int range) implements NumericProvider {
|
|||
}
|
||||
|
||||
static {
|
||||
Registry.register(NumericProvider.NUMERIC_PROVIDER, BCLib.makeID("rnd_int"), RandomIntProvider.CODEC);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,4 +28,6 @@ public abstract class SurfaceNoiseCondition implements NoiseCondition {
|
|||
}
|
||||
|
||||
public abstract boolean test(SurfaceRulesContextAccessor context);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
package org.betterx.bclib.api.surface.rules;
|
||||
|
||||
import net.minecraft.util.KeyDispatchDataCodec;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.util.valueproviders.ConstantFloat;
|
||||
import net.minecraft.util.valueproviders.FloatProvider;
|
||||
import net.minecraft.world.level.levelgen.LegacyRandomSource;
|
||||
import net.minecraft.world.level.levelgen.SurfaceRules;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.mixin.common.SurfaceRulesContextAccessor;
|
||||
import org.betterx.bclib.noise.OpenSimplexNoise;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ThresholdCondition extends SurfaceNoiseCondition {
|
||||
private static final Map<Long, Context> NOISES = Maps.newHashMap();
|
||||
public static final Codec<ThresholdCondition> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
Codec.LONG.fieldOf("seed").forGetter(p -> p.noiseContext.seed),
|
||||
Codec.DOUBLE.fieldOf("threshold").orElse(0.0).forGetter(p -> p.threshold),
|
||||
FloatProvider.CODEC.fieldOf("threshold_offset").orElse(ConstantFloat.of(0)).forGetter(p -> p.range),
|
||||
Codec.DOUBLE.fieldOf("scale_x").orElse(0.1).forGetter(p -> p.scaleX),
|
||||
Codec.DOUBLE.fieldOf("scale_z").orElse(0.1).forGetter(p -> p.scaleZ)
|
||||
)
|
||||
.apply(instance, ThresholdCondition::new));
|
||||
public static final KeyDispatchDataCodec<ThresholdCondition> KEY_CODEC = KeyDispatchDataCodec.of(CODEC);
|
||||
private final Context noiseContext;
|
||||
private final double threshold;
|
||||
private final FloatProvider range;
|
||||
private final double scaleX;
|
||||
private final double scaleZ;
|
||||
|
||||
public ThresholdCondition(long noiseSeed, double threshold, FloatProvider range, double scaleX, double scaleZ) {
|
||||
this.threshold = threshold;
|
||||
this.range = range;
|
||||
this.scaleX = scaleX;
|
||||
this.scaleZ = scaleZ;
|
||||
|
||||
noiseContext = NOISES.computeIfAbsent(noiseSeed, seed -> new Context(seed));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(SurfaceRulesContextAccessor context) {
|
||||
final double x = context.getBlockX() * scaleX;
|
||||
final double z = context.getBlockZ() * scaleZ;
|
||||
if (noiseContext.lastX == x && noiseContext.lastZ == z)
|
||||
return noiseContext.lastValue + range.sample(noiseContext.random) > threshold;
|
||||
double value = noiseContext.noise.eval(x, z);
|
||||
|
||||
noiseContext.lastX = x;
|
||||
noiseContext.lastZ = z;
|
||||
noiseContext.lastValue = value;
|
||||
return value + range.sample(noiseContext.random) > threshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyDispatchDataCodec<? extends SurfaceRules.ConditionSource> codec() {
|
||||
return KEY_CODEC;
|
||||
}
|
||||
|
||||
static class Context {
|
||||
public final OpenSimplexNoise noise;
|
||||
public final RandomSource random;
|
||||
public final long seed;
|
||||
|
||||
public double lastX = Integer.MIN_VALUE;
|
||||
public double lastZ = Integer.MIN_VALUE;
|
||||
public double lastValue = 0;
|
||||
|
||||
Context(long seed) {
|
||||
this.seed = seed;
|
||||
this.noise = new OpenSimplexNoise(seed);
|
||||
this.random = new LegacyRandomSource(seed * 2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package org.betterx.bclib.api.surface.rules;
|
||||
|
||||
import net.minecraft.util.KeyDispatchDataCodec;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.util.valueproviders.ConstantFloat;
|
||||
import net.minecraft.util.valueproviders.FloatProvider;
|
||||
import net.minecraft.world.level.levelgen.LegacyRandomSource;
|
||||
import net.minecraft.world.level.levelgen.SurfaceRules;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.mixin.common.SurfaceRulesContextAccessor;
|
||||
import org.betterx.bclib.noise.OpenSimplexNoise;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class VolumeThresholdCondition extends VolumeNoiseCondition {
|
||||
private static final Map<Long, VolumeThresholdCondition.Context> NOISES = Maps.newHashMap();
|
||||
public static final Codec<VolumeThresholdCondition> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
Codec.LONG.fieldOf("seed").forGetter(p -> p.noiseContext.seed),
|
||||
Codec.DOUBLE.fieldOf("threshold").orElse(0.0).forGetter(p -> p.threshold),
|
||||
FloatProvider.CODEC.fieldOf("threshold_offset").orElse(ConstantFloat.of(0)).forGetter(p -> p.range),
|
||||
Codec.DOUBLE.fieldOf("scale_x").orElse(0.1).forGetter(p -> p.scaleX),
|
||||
Codec.DOUBLE.fieldOf("scale_y").orElse(0.1).forGetter(p -> p.scaleY),
|
||||
Codec.DOUBLE.fieldOf("scale_z").orElse(0.1).forGetter(p -> p.scaleZ)
|
||||
)
|
||||
.apply(instance, VolumeThresholdCondition::new));
|
||||
public static final KeyDispatchDataCodec<VolumeThresholdCondition> KEY_CODEC = KeyDispatchDataCodec.of(CODEC);
|
||||
public final VolumeThresholdCondition.Context noiseContext;
|
||||
public final double threshold;
|
||||
public final FloatProvider range;
|
||||
public final double scaleX;
|
||||
public final double scaleY;
|
||||
public final double scaleZ;
|
||||
|
||||
public VolumeThresholdCondition(long noiseSeed,
|
||||
double threshold,
|
||||
FloatProvider range,
|
||||
double scaleX,
|
||||
double scaleY,
|
||||
double scaleZ) {
|
||||
this.threshold = threshold;
|
||||
this.range = range;
|
||||
this.scaleX = scaleX;
|
||||
this.scaleY = scaleY;
|
||||
this.scaleZ = scaleZ;
|
||||
|
||||
noiseContext = NOISES.computeIfAbsent(noiseSeed, seed -> new Context(seed));
|
||||
}
|
||||
|
||||
public double getValue(SurfaceRulesContextAccessor context) {
|
||||
return getValue(context.getBlockX(), context.getBlockY(), context.getBlockZ());
|
||||
}
|
||||
|
||||
public double getValue(int xx, int yy, int zz) {
|
||||
final double x = xx * scaleX;
|
||||
final double y = yy * scaleY;
|
||||
final double z = zz * scaleZ;
|
||||
|
||||
if (noiseContext.lastX == x
|
||||
&& noiseContext.lastY == y
|
||||
&& noiseContext.lastZ == z)
|
||||
return noiseContext.lastValue + range.sample(noiseContext.random);
|
||||
|
||||
double value = noiseContext.noise.eval(x, y, z);
|
||||
|
||||
noiseContext.lastX = x;
|
||||
noiseContext.lastZ = z;
|
||||
noiseContext.lastY = y;
|
||||
noiseContext.lastValue = value;
|
||||
|
||||
return value + range.sample(noiseContext.random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(SurfaceRulesContextAccessor context) {
|
||||
return getValue(context) > threshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyDispatchDataCodec<? extends SurfaceRules.ConditionSource> codec() {
|
||||
return KEY_CODEC;
|
||||
}
|
||||
|
||||
public static class Context {
|
||||
public final OpenSimplexNoise noise;
|
||||
public final RandomSource random;
|
||||
public final long seed;
|
||||
|
||||
double lastX = Integer.MIN_VALUE;
|
||||
double lastY = Integer.MIN_VALUE;
|
||||
double lastZ = Integer.MIN_VALUE;
|
||||
double lastValue = 0;
|
||||
|
||||
Context(long seed) {
|
||||
this.seed = seed;
|
||||
this.noise = new OpenSimplexNoise(seed);
|
||||
this.random = new LegacyRandomSource(seed * 3 + 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package org.betterx.bclib.api.tag;
|
|||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
|
||||
|
||||
public class NamedBlockTags {
|
||||
|
@ -36,4 +37,8 @@ public class NamedBlockTags {
|
|||
public static final TagKey<Block> SOUL_SPEED_BLOCKS = BlockTags.SOUL_SPEED_BLOCKS;
|
||||
public static final TagKey<Block> BEACON_BASE_BLOCKS = BlockTags.BEACON_BASE_BLOCKS;
|
||||
public static final TagKey<Block> STONE_BRICKS = BlockTags.STONE_BRICKS;
|
||||
|
||||
static {
|
||||
TagAPI.BLOCKS.add(BlockTags.NETHER_CARVER_REPLACEABLES, Blocks.RED_SAND, Blocks.MAGMA_BLOCK);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
package org.betterx.bclib.world.surface;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.util.KeyDispatchDataCodec;
|
||||
import net.minecraft.world.level.levelgen.SurfaceRules;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.surface.rules.SurfaceNoiseCondition;
|
||||
import org.betterx.bclib.mixin.common.SurfaceRulesContextAccessor;
|
||||
import org.betterx.bclib.noise.OpenSimplexNoise;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
|
||||
public class DoubleBlockSurfaceNoiseCondition extends SurfaceNoiseCondition {
|
||||
public static final DoubleBlockSurfaceNoiseCondition CONDITION = new DoubleBlockSurfaceNoiseCondition(0);
|
||||
private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(4141);
|
||||
public static final Codec<DoubleBlockSurfaceNoiseCondition> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
Codec.DOUBLE.fieldOf("threshold").orElse(0.0).forGetter(o -> o.threshold)
|
||||
)
|
||||
.apply(instance, DoubleBlockSurfaceNoiseCondition::new));
|
||||
|
||||
public static final KeyDispatchDataCodec<DoubleBlockSurfaceNoiseCondition> KEY_CODEC = KeyDispatchDataCodec.of(
|
||||
CODEC);
|
||||
private final double threshold;
|
||||
|
||||
public DoubleBlockSurfaceNoiseCondition(double threshold) {
|
||||
this.threshold = threshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyDispatchDataCodec<? extends SurfaceRules.ConditionSource> codec() {
|
||||
return KEY_CODEC;
|
||||
}
|
||||
|
||||
private static int lastX = Integer.MIN_VALUE;
|
||||
private static int lastZ = Integer.MIN_VALUE;
|
||||
private static double lastValue = 0;
|
||||
|
||||
@Override
|
||||
public boolean test(SurfaceRulesContextAccessor context) {
|
||||
final int x = context.getBlockX();
|
||||
final int z = context.getBlockZ();
|
||||
if (lastX == x && lastZ == z) return lastValue > threshold;
|
||||
|
||||
double value = NOISE.eval(x * 0.1, z * 0.1) + MHelper.randRange(-0.4, 0.4, MHelper.RANDOM_SOURCE);
|
||||
|
||||
lastX = x;
|
||||
lastZ = z;
|
||||
lastValue = value;
|
||||
return value > threshold;
|
||||
}
|
||||
|
||||
static {
|
||||
Registry.register(Registry.CONDITION,
|
||||
BCLib.makeID("doubleblock_surface"),
|
||||
DoubleBlockSurfaceNoiseCondition.CODEC);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue