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.DataExchangeAPI;
|
||||||
import org.betterx.bclib.api.dataexchange.handler.autosync.*;
|
import org.betterx.bclib.api.dataexchange.handler.autosync.*;
|
||||||
import org.betterx.bclib.api.features.placement.PlacementModifiers;
|
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.api.tag.TagAPI;
|
||||||
import org.betterx.bclib.config.Configs;
|
import org.betterx.bclib.config.Configs;
|
||||||
import org.betterx.bclib.presets.worldgen.BCLWorldPresets;
|
import org.betterx.bclib.presets.worldgen.BCLWorldPresets;
|
||||||
|
@ -49,6 +50,7 @@ public class BCLib implements ModInitializer {
|
||||||
DataExchangeAPI.registerMod(MOD_ID);
|
DataExchangeAPI.registerMod(MOD_ID);
|
||||||
BCLWorldPresets.registerPresets();
|
BCLWorldPresets.registerPresets();
|
||||||
AnvilRecipe.register();
|
AnvilRecipe.register();
|
||||||
|
Conditions.registerAll();
|
||||||
|
|
||||||
DataExchangeAPI.registerDescriptors(List.of(
|
DataExchangeAPI.registerDescriptors(List.of(
|
||||||
HelloClient.DESCRIPTOR,
|
HelloClient.DESCRIPTOR,
|
||||||
|
|
|
@ -16,6 +16,7 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||||
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
|
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
|
||||||
|
|
||||||
import org.betterx.bclib.BCLib;
|
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.ScatterFeatureConfig;
|
||||||
import org.betterx.bclib.api.features.config.TemplateFeatureConfig;
|
import org.betterx.bclib.api.features.config.TemplateFeatureConfig;
|
||||||
|
|
||||||
|
@ -23,6 +24,9 @@ import java.util.Map.Entry;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class BCLFeature {
|
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(
|
public static final Feature<ScatterFeatureConfig.OnSolid> SCATTER_ON_SOLID = register(
|
||||||
BCLib.makeID("scatter_on_solid"),
|
BCLib.makeID("scatter_on_solid"),
|
||||||
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC));
|
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC));
|
||||||
|
|
|
@ -297,8 +297,8 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
|
||||||
return modifier(new FindSolidInDirection(dir, distance));
|
return modifier(new FindSolidInDirection(dir, distance));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BCLFeatureBuilder findSolidSurface(List<Direction> dir, int distance) {
|
public BCLFeatureBuilder findSolidSurface(List<Direction> dir, int distance, boolean randomSelect) {
|
||||||
return modifier(new FindSolidInDirection(dir, distance));
|
return modifier(new FindSolidInDirection(dir, distance, randomSelect));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BCLFeatureBuilder heightmap() {
|
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;
|
package org.betterx.bclib.api.features;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.util.valueproviders.UniformInt;
|
||||||
import net.minecraft.world.level.block.Block;
|
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.blockpredicates.BlockPredicate;
|
||||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
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.RandomPatchConfiguration;
|
||||||
import net.minecraft.world.level.levelgen.feature.configurations.SimpleBlockConfiguration;
|
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.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;
|
import org.betterx.bclib.api.features.config.ScatterFeatureConfig;
|
||||||
|
|
||||||
public class FastFeatures {
|
public class FastFeatures {
|
||||||
|
@ -59,6 +64,24 @@ public class FastFeatures {
|
||||||
new SimpleBlockConfiguration(BlockStateProvider.simple(block)));
|
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
|
public static BCLFeature
|
||||||
simple(ResourceLocation location,
|
simple(ResourceLocation location,
|
||||||
int searchDist,
|
int searchDist,
|
||||||
|
@ -67,6 +90,31 @@ public class FastFeatures {
|
||||||
return simple(location, searchDist, rare, feature, NoneFeatureConfiguration.NONE);
|
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
|
public static <FC extends FeatureConfiguration> BCLFeature
|
||||||
simple(ResourceLocation location,
|
simple(ResourceLocation location,
|
||||||
int searchDist,
|
int searchDist,
|
||||||
|
@ -104,11 +152,33 @@ public class FastFeatures {
|
||||||
int ySpread,
|
int ySpread,
|
||||||
Feature<FC> feature,
|
Feature<FC> feature,
|
||||||
FC config) {
|
FC config) {
|
||||||
ResourceLocation patchLocation = new ResourceLocation(location.getNamespace(), location.getPath() + "_patch");
|
|
||||||
final BCLFeature SINGLE = simple(location, ySpread, false, feature, config);
|
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
|
return BCLFeatureBuilder
|
||||||
.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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.core.Direction;
|
||||||
import net.minecraft.util.ExtraCodecs;
|
import net.minecraft.util.ExtraCodecs;
|
||||||
import net.minecraft.util.RandomSource;
|
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.PlacementContext;
|
||||||
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
|
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
|
||||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
|
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
|
||||||
|
@ -23,7 +25,9 @@ public class FindSolidInDirection extends PlacementModifier {
|
||||||
.fieldOf("dir")
|
.fieldOf("dir")
|
||||||
.orElse(List.of(Direction.DOWN))
|
.orElse(List.of(Direction.DOWN))
|
||||||
.forGetter(a -> a.direction),
|
.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,
|
.apply(instance,
|
||||||
FindSolidInDirection::new));
|
FindSolidInDirection::new));
|
||||||
protected static final FindSolidInDirection DOWN = new FindSolidInDirection(Direction.DOWN, 6);
|
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 List<Direction> direction;
|
||||||
private final int maxSearchDistance;
|
private final int maxSearchDistance;
|
||||||
|
|
||||||
|
private final boolean randomSelect;
|
||||||
|
private final IntProvider provider;
|
||||||
|
|
||||||
|
|
||||||
public FindSolidInDirection(Direction direction, int maxSearchDistance) {
|
public FindSolidInDirection(Direction direction, int maxSearchDistance) {
|
||||||
this(List.of(direction), maxSearchDistance);
|
this(List.of(direction), maxSearchDistance, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FindSolidInDirection(List<Direction> direction, int maxSearchDistance) {
|
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.direction = direction;
|
||||||
this.maxSearchDistance = maxSearchDistance;
|
this.maxSearchDistance = maxSearchDistance;
|
||||||
|
this.provider = UniformInt.of(0, direction.size() - 1);
|
||||||
|
this.randomSelect = randomSelect;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlacementModifier down() {
|
public static PlacementModifier down() {
|
||||||
|
@ -59,24 +73,37 @@ public class FindSolidInDirection extends PlacementModifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Direction randomDirection(RandomSource random) {
|
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
|
@Override
|
||||||
public Stream<BlockPos> getPositions(PlacementContext placementContext,
|
public Stream<BlockPos> getPositions(PlacementContext placementContext,
|
||||||
RandomSource randomSource,
|
RandomSource randomSource,
|
||||||
BlockPos blockPos) {
|
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();
|
BlockPos.MutableBlockPos POS = blockPos.mutable();
|
||||||
Direction d = randomDirection(randomSource);
|
|
||||||
if (BlocksHelper.findOnSurroundingSurface(placementContext.getLevel(),
|
if (BlocksHelper.findOnSurroundingSurface(placementContext.getLevel(),
|
||||||
POS,
|
POS,
|
||||||
d,
|
d,
|
||||||
maxSearchDistance,
|
maxSearchDistance,
|
||||||
BlocksHelper::isTerrain)) {
|
BlocksHelper::isTerrain)) {
|
||||||
return Stream.of(POS);
|
builder.add(POS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Stream.of();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -10,8 +10,9 @@ import net.minecraft.world.level.levelgen.placement.CaveSurface;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import org.betterx.bclib.api.biomes.BiomeAPI;
|
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.api.surface.rules.NoiseCondition;
|
||||||
import org.betterx.bclib.world.surface.DoubleBlockSurfaceNoiseCondition;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -96,7 +97,7 @@ public class SurfaceRuleBuilder {
|
||||||
*/
|
*/
|
||||||
public SurfaceRuleBuilder filler(BlockState state) {
|
public SurfaceRuleBuilder filler(BlockState state) {
|
||||||
entryInstance = getFromCache("fill_" + state.toString(),
|
entryInstance = getFromCache("fill_" + state.toString(),
|
||||||
() -> new SurfaceRuleEntry(10, SurfaceRules.state(state)));
|
() -> new SurfaceRuleEntry(10, SurfaceRules.state(state)));
|
||||||
rules.add(entryInstance);
|
rules.add(entryInstance);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -127,14 +128,14 @@ public class SurfaceRuleBuilder {
|
||||||
public SurfaceRuleBuilder belowFloor(BlockState state, int height, NoiseCondition noise) {
|
public SurfaceRuleBuilder belowFloor(BlockState state, int height, NoiseCondition noise) {
|
||||||
entryInstance = getFromCache("below_floor_" + height + "_" + state.toString() + "_" + noise.getClass()
|
entryInstance = getFromCache("below_floor_" + height + "_" + state.toString() + "_" + noise.getClass()
|
||||||
.getSimpleName(),
|
.getSimpleName(),
|
||||||
() -> {
|
() -> {
|
||||||
RuleSource rule = SurfaceRules.state(state);
|
RuleSource rule = SurfaceRules.state(state);
|
||||||
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(height,
|
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(height,
|
||||||
false,
|
false,
|
||||||
CaveSurface.FLOOR),
|
CaveSurface.FLOOR),
|
||||||
SurfaceRules.ifTrue(noise, rule));
|
SurfaceRules.ifTrue(noise, rule));
|
||||||
return new SurfaceRuleEntry(3, rule);
|
return new SurfaceRuleEntry(3, rule);
|
||||||
});
|
});
|
||||||
rules.add(entryInstance);
|
rules.add(entryInstance);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -237,7 +238,7 @@ public class SurfaceRuleBuilder {
|
||||||
* @return same {@link SurfaceRuleBuilder} instance.
|
* @return same {@link SurfaceRuleBuilder} instance.
|
||||||
*/
|
*/
|
||||||
public SurfaceRuleBuilder chancedFloor(BlockState surfaceBlockA, BlockState surfaceBlockB) {
|
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) {
|
public SurfaceRuleBuilder chancedFloor(BlockState surfaceBlockA, BlockState surfaceBlockB, NoiseCondition noise) {
|
||||||
entryInstance = getFromCache("chancedFloor_" + surfaceBlockA + "_" + surfaceBlockB + "_" + noise.getClass()
|
entryInstance = getFromCache("chancedFloor_" + surfaceBlockA + "_" + surfaceBlockB + "_" + noise.getClass()
|
||||||
.getSimpleName(),
|
.getSimpleName(),
|
||||||
() -> {
|
() -> {
|
||||||
RuleSource rule =
|
RuleSource rule =
|
||||||
SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR,
|
SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR,
|
||||||
SurfaceRules.sequence(
|
SurfaceRules.sequence(
|
||||||
SurfaceRules.ifTrue(noise,
|
SurfaceRules.ifTrue(noise,
|
||||||
SurfaceRules.state(
|
SurfaceRules.state(
|
||||||
surfaceBlockA)),
|
surfaceBlockA)),
|
||||||
SurfaceRules.state(surfaceBlockB)
|
SurfaceRules.state(surfaceBlockB)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return new SurfaceRuleEntry(4, rule);
|
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);
|
rules.add(entryInstance);
|
||||||
return this;
|
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;
|
package org.betterx.bclib.api.surface.rules;
|
||||||
|
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import org.betterx.bclib.BCLib;
|
|
||||||
import org.betterx.bclib.interfaces.NumericProvider;
|
import org.betterx.bclib.interfaces.NumericProvider;
|
||||||
import org.betterx.bclib.mixin.common.SurfaceRulesContextAccessor;
|
import org.betterx.bclib.mixin.common.SurfaceRulesContextAccessor;
|
||||||
import org.betterx.bclib.util.MHelper;
|
import org.betterx.bclib.util.MHelper;
|
||||||
|
@ -24,6 +21,6 @@ public record RandomIntProvider(int range) implements NumericProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
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);
|
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.BlockTags;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
|
||||||
|
|
||||||
public class NamedBlockTags {
|
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> SOUL_SPEED_BLOCKS = BlockTags.SOUL_SPEED_BLOCKS;
|
||||||
public static final TagKey<Block> BEACON_BASE_BLOCKS = BlockTags.BEACON_BASE_BLOCKS;
|
public static final TagKey<Block> BEACON_BASE_BLOCKS = BlockTags.BEACON_BASE_BLOCKS;
|
||||||
public static final TagKey<Block> STONE_BRICKS = BlockTags.STONE_BRICKS;
|
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