From 97a65a3707c28bb28060c488933b873c3c9d05d0 Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 5 Jun 2022 17:31:03 +0200 Subject: [PATCH] Refactoring and CrimsonPinewood --- src/main/java/org/betterx/bclib/BCLib.java | 2 + .../bclib/api/features/BCLFeature.java | 4 + .../bclib/api/features/BCLFeatureBuilder.java | 4 +- .../bclib/api/features/BlockPlaceFeature.java | 25 ----- .../bclib/api/features/FastFeatures.java | 74 ++++++++++++- .../bclib/api/features/PlaceBlockFeature.java | 18 +++ .../config/BlockPlaceFeatureConfig.java | 59 ---------- .../config/PlaceBlockFeatureConfig.java | 76 +++++++++++++ .../config/PlaceFacingBlockConfig.java | 77 +++++++++++++ .../placement/FindSolidInDirection.java | 41 +++++-- .../bclib/api/surface/SurfaceRuleBuilder.java | 66 +++++++---- .../bclib/api/surface/rules/Conditions.java | 60 ++++++++++ .../DoubleBlockSurfaceNoiseCondition.java | 5 + .../surface/rules/NetherNoiseCondition.java | 43 ++++++++ .../api/surface/rules/RandomIntProvider.java | 5 +- .../surface/rules/SurfaceNoiseCondition.java | 2 + .../api/surface/rules/ThresholdCondition.java | 79 ++++++++++++++ .../rules/VolumeThresholdCondition.java | 103 ++++++++++++++++++ .../betterx/bclib/api/tag/NamedBlockTags.java | 5 + .../DoubleBlockSurfaceNoiseCondition.java | 60 ---------- 20 files changed, 626 insertions(+), 182 deletions(-) delete mode 100644 src/main/java/org/betterx/bclib/api/features/BlockPlaceFeature.java create mode 100644 src/main/java/org/betterx/bclib/api/features/PlaceBlockFeature.java delete mode 100644 src/main/java/org/betterx/bclib/api/features/config/BlockPlaceFeatureConfig.java create mode 100644 src/main/java/org/betterx/bclib/api/features/config/PlaceBlockFeatureConfig.java create mode 100644 src/main/java/org/betterx/bclib/api/features/config/PlaceFacingBlockConfig.java create mode 100644 src/main/java/org/betterx/bclib/api/surface/rules/Conditions.java create mode 100644 src/main/java/org/betterx/bclib/api/surface/rules/DoubleBlockSurfaceNoiseCondition.java create mode 100644 src/main/java/org/betterx/bclib/api/surface/rules/NetherNoiseCondition.java create mode 100644 src/main/java/org/betterx/bclib/api/surface/rules/ThresholdCondition.java create mode 100644 src/main/java/org/betterx/bclib/api/surface/rules/VolumeThresholdCondition.java delete mode 100644 src/main/java/org/betterx/bclib/world/surface/DoubleBlockSurfaceNoiseCondition.java diff --git a/src/main/java/org/betterx/bclib/BCLib.java b/src/main/java/org/betterx/bclib/BCLib.java index 8090aaed..cb119b5c 100644 --- a/src/main/java/org/betterx/bclib/BCLib.java +++ b/src/main/java/org/betterx/bclib/BCLib.java @@ -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, diff --git a/src/main/java/org/betterx/bclib/api/features/BCLFeature.java b/src/main/java/org/betterx/bclib/api/features/BCLFeature.java index 7e297bd5..d4ade758 100644 --- a/src/main/java/org/betterx/bclib/api/features/BCLFeature.java +++ b/src/main/java/org/betterx/bclib/api/features/BCLFeature.java @@ -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 PLACE_BLOCK = register( + BCLib.makeID("place_block"), + new PlaceBlockFeature<>(PlaceFacingBlockConfig.CODEC)); public static final Feature SCATTER_ON_SOLID = register( BCLib.makeID("scatter_on_solid"), new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC)); diff --git a/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java b/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java index 6e12f3d7..79e3d4f0 100644 --- a/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java +++ b/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java @@ -297,8 +297,8 @@ public class BCLFeatureBuilder dir, int distance) { - return modifier(new FindSolidInDirection(dir, distance)); + public BCLFeatureBuilder findSolidSurface(List dir, int distance, boolean randomSelect) { + return modifier(new FindSolidInDirection(dir, distance, randomSelect)); } public BCLFeatureBuilder heightmap() { diff --git a/src/main/java/org/betterx/bclib/api/features/BlockPlaceFeature.java b/src/main/java/org/betterx/bclib/api/features/BlockPlaceFeature.java deleted file mode 100644 index c19eb568..00000000 --- a/src/main/java/org/betterx/bclib/api/features/BlockPlaceFeature.java +++ /dev/null @@ -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 extends Feature { - public BlockPlaceFeature(Codec codec) { - super(codec); - } - - @Override - public boolean place(FeaturePlaceContext ctx) { - Optional state = ctx.config().getRandomBlock(ctx.random()); - if (state.isPresent()) - BlocksHelper.setWithoutUpdate(ctx.level(), ctx.origin(), state.get()); - return true; - } -} diff --git a/src/main/java/org/betterx/bclib/api/features/FastFeatures.java b/src/main/java/org/betterx/bclib/api/features/FastFeatures.java index 334aabe4..69c1532f 100644 --- a/src/main/java/org/betterx/bclib/api/features/FastFeatures.java +++ b/src/main/java/org/betterx/bclib/api/features/FastFeatures.java @@ -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 BCLFeature simple(ResourceLocation location, int searchDist, @@ -104,11 +152,33 @@ public class FastFeatures { int ySpread, Feature 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())); } + + } diff --git a/src/main/java/org/betterx/bclib/api/features/PlaceBlockFeature.java b/src/main/java/org/betterx/bclib/api/features/PlaceBlockFeature.java new file mode 100644 index 00000000..fbfa9550 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/features/PlaceBlockFeature.java @@ -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 extends Feature { + public PlaceBlockFeature(Codec codec) { + super(codec); + } + + @Override + public boolean place(FeaturePlaceContext ctx) { + return ctx.config().place(ctx); + } +} diff --git a/src/main/java/org/betterx/bclib/api/features/config/BlockPlaceFeatureConfig.java b/src/main/java/org/betterx/bclib/api/features/config/BlockPlaceFeatureConfig.java deleted file mode 100644 index c37e5e51..00000000 --- a/src/main/java/org/betterx/bclib/api/features/config/BlockPlaceFeatureConfig.java +++ /dev/null @@ -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 CODEC = SimpleWeightedRandomList - .wrappedCodec(BlockState.CODEC) - .comapFlatMap(BlockPlaceFeatureConfig::create, cfg -> cfg.weightedList) - .fieldOf("entries").codec(); - - private final SimpleWeightedRandomList weightedList; - - private static DataResult create(SimpleWeightedRandomList simpleWeightedRandomList) { - if (simpleWeightedRandomList.isEmpty()) { - return DataResult.error("BlockPlaceFeatureConfig with no states"); - } - return DataResult.success(new BlockPlaceFeatureConfig(simpleWeightedRandomList)); - } - - - private static SimpleWeightedRandomList convert(List states) { - var builder = SimpleWeightedRandomList.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 - .builder() - .add(state, 1) - .build()); - } - - public BlockPlaceFeatureConfig(List states) { - this(convert(states)); - } - - public BlockPlaceFeatureConfig(SimpleWeightedRandomList blocks) { - this.weightedList = blocks; - } - - public Optional getRandomBlock(RandomSource random) { - return this.weightedList.getRandomValue(random); - } -} diff --git a/src/main/java/org/betterx/bclib/api/features/config/PlaceBlockFeatureConfig.java b/src/main/java/org/betterx/bclib/api/features/config/PlaceBlockFeatureConfig.java new file mode 100644 index 00000000..37661770 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/features/config/PlaceBlockFeatureConfig.java @@ -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 RecordCodecBuilder> blockStateCodec() { + return SimpleWeightedRandomList + .wrappedCodec(BlockState.CODEC) + .fieldOf("entries") + .forGetter((T o) -> o.weightedList); + } + + protected final SimpleWeightedRandomList weightedList; + + + protected static SimpleWeightedRandomList buildWeightedList(List states) { + var builder = SimpleWeightedRandomList.builder(); + for (BlockState s : states) builder.add(s, 1); + return builder.build(); + } + + protected static SimpleWeightedRandomList buildWeightedList(BlockState state) { + return SimpleWeightedRandomList + .builder() + .add(state, 1) + .build(); + } + + public PlaceBlockFeatureConfig(Block block) { + this(block.defaultBlockState()); + } + + public PlaceBlockFeatureConfig(BlockState state) { + this(buildWeightedList(state)); + } + + + public PlaceBlockFeatureConfig(List states) { + this(buildWeightedList(states)); + } + + public PlaceBlockFeatureConfig(SimpleWeightedRandomList blocks) { + this.weightedList = blocks; + } + + public Optional getRandomBlock(RandomSource random) { + return this.weightedList.getRandomValue(random); + } + + public boolean place(FeaturePlaceContext ctx) { + Optional state = getRandomBlock(ctx.random()); + if (state.isPresent()) { + return placeBlock(ctx, ctx.level(), ctx.origin(), state.get()); + } + return false; + } + + + protected abstract boolean placeBlock(FeaturePlaceContext ctx, + WorldGenLevel level, + BlockPos pos, + BlockState targetState); +} diff --git a/src/main/java/org/betterx/bclib/api/features/config/PlaceFacingBlockConfig.java b/src/main/java/org/betterx/bclib/api/features/config/PlaceFacingBlockConfig.java new file mode 100644 index 00000000..15d76fd9 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/features/config/PlaceFacingBlockConfig.java @@ -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 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 HORIZONTAL = List.of(Direction.NORTH, + Direction.EAST, + Direction.WEST, + Direction.SOUTH); + public static final List VERTICAL = List.of(Direction.UP, Direction.DOWN); + public static final List ALL = List.of(Direction.NORTH, + Direction.EAST, + Direction.SOUTH, + Direction.WEST, + Direction.UP, + Direction.DOWN); + + private final List directions; + + public PlaceFacingBlockConfig(Block block, List dir) { + this(block.defaultBlockState(), dir); + } + + public PlaceFacingBlockConfig(BlockState state, List dir) { + this(buildWeightedList(state), dir); + } + + public PlaceFacingBlockConfig(List states, List dir) { + this(buildWeightedList(states), dir); + } + + public PlaceFacingBlockConfig(SimpleWeightedRandomList blocks, List dir) { + super(blocks); + directions = dir; + } + + @Override + + public boolean placeBlock(FeaturePlaceContext 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; + } +} diff --git a/src/main/java/org/betterx/bclib/api/features/placement/FindSolidInDirection.java b/src/main/java/org/betterx/bclib/api/features/placement/FindSolidInDirection.java index c5fad618..94f7ea32 100644 --- a/src/main/java/org/betterx/bclib/api/features/placement/FindSolidInDirection.java +++ b/src/main/java/org/betterx/bclib/api/features/placement/FindSolidInDirection.java @@ -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; 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, int maxSearchDistance) { + this(direction, maxSearchDistance, direction.size() > 1); + } + + public FindSolidInDirection(List 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 getPositions(PlacementContext placementContext, RandomSource randomSource, BlockPos blockPos) { + var builder = Stream.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 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 diff --git a/src/main/java/org/betterx/bclib/api/surface/SurfaceRuleBuilder.java b/src/main/java/org/betterx/bclib/api/surface/SurfaceRuleBuilder.java index e51d97a8..70b0ab02 100644 --- a/src/main/java/org/betterx/bclib/api/surface/SurfaceRuleBuilder.java +++ b/src/main/java/org/betterx/bclib/api/surface/SurfaceRuleBuilder.java @@ -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; } diff --git a/src/main/java/org/betterx/bclib/api/surface/rules/Conditions.java b/src/main/java/org/betterx/bclib/api/surface/rules/Conditions.java new file mode 100644 index 00000000..1139c59e --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/surface/rules/Conditions.java @@ -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 codec) { + Registry.register(Registry.CONDITION, location, codec); + } + + public static void registerNumeric(ResourceLocation location, Codec 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); + } +} diff --git a/src/main/java/org/betterx/bclib/api/surface/rules/DoubleBlockSurfaceNoiseCondition.java b/src/main/java/org/betterx/bclib/api/surface/rules/DoubleBlockSurfaceNoiseCondition.java new file mode 100644 index 00000000..7213548f --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/surface/rules/DoubleBlockSurfaceNoiseCondition.java @@ -0,0 +1,5 @@ +package org.betterx.bclib.api.surface.rules; + +public class DoubleBlockSurfaceNoiseCondition { + public static final ThresholdCondition CONDITION = Conditions.DOUBLE_BLOCK_SURFACE_NOISE; +} diff --git a/src/main/java/org/betterx/bclib/api/surface/rules/NetherNoiseCondition.java b/src/main/java/org/betterx/bclib/api/surface/rules/NetherNoiseCondition.java new file mode 100644 index 00000000..910f821d --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/surface/rules/NetherNoiseCondition.java @@ -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 CODEC = Codec.BYTE.fieldOf("nether_noise") + .xmap((obj) -> (NetherNoiseCondition) Conditions.NETHER_NOISE, + obj -> (byte) 0) + .codec(); + + + NetherNoiseCondition() { + } + + + @Override + public Codec 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; + } +} diff --git a/src/main/java/org/betterx/bclib/api/surface/rules/RandomIntProvider.java b/src/main/java/org/betterx/bclib/api/surface/rules/RandomIntProvider.java index 47593ae8..cb77002a 100644 --- a/src/main/java/org/betterx/bclib/api/surface/rules/RandomIntProvider.java +++ b/src/main/java/org/betterx/bclib/api/surface/rules/RandomIntProvider.java @@ -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); + } } diff --git a/src/main/java/org/betterx/bclib/api/surface/rules/SurfaceNoiseCondition.java b/src/main/java/org/betterx/bclib/api/surface/rules/SurfaceNoiseCondition.java index 9b02eee3..e8b0088e 100644 --- a/src/main/java/org/betterx/bclib/api/surface/rules/SurfaceNoiseCondition.java +++ b/src/main/java/org/betterx/bclib/api/surface/rules/SurfaceNoiseCondition.java @@ -28,4 +28,6 @@ public abstract class SurfaceNoiseCondition implements NoiseCondition { } public abstract boolean test(SurfaceRulesContextAccessor context); + + } diff --git a/src/main/java/org/betterx/bclib/api/surface/rules/ThresholdCondition.java b/src/main/java/org/betterx/bclib/api/surface/rules/ThresholdCondition.java new file mode 100644 index 00000000..9604ba1b --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/surface/rules/ThresholdCondition.java @@ -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 NOISES = Maps.newHashMap(); + public static final Codec 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 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 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); + } + } +} diff --git a/src/main/java/org/betterx/bclib/api/surface/rules/VolumeThresholdCondition.java b/src/main/java/org/betterx/bclib/api/surface/rules/VolumeThresholdCondition.java new file mode 100644 index 00000000..4e8f3da7 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/surface/rules/VolumeThresholdCondition.java @@ -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 NOISES = Maps.newHashMap(); + public static final Codec 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 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 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); + } + } +} diff --git a/src/main/java/org/betterx/bclib/api/tag/NamedBlockTags.java b/src/main/java/org/betterx/bclib/api/tag/NamedBlockTags.java index 596196de..a42cc700 100644 --- a/src/main/java/org/betterx/bclib/api/tag/NamedBlockTags.java +++ b/src/main/java/org/betterx/bclib/api/tag/NamedBlockTags.java @@ -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 SOUL_SPEED_BLOCKS = BlockTags.SOUL_SPEED_BLOCKS; public static final TagKey BEACON_BASE_BLOCKS = BlockTags.BEACON_BASE_BLOCKS; public static final TagKey STONE_BRICKS = BlockTags.STONE_BRICKS; + + static { + TagAPI.BLOCKS.add(BlockTags.NETHER_CARVER_REPLACEABLES, Blocks.RED_SAND, Blocks.MAGMA_BLOCK); + } } diff --git a/src/main/java/org/betterx/bclib/world/surface/DoubleBlockSurfaceNoiseCondition.java b/src/main/java/org/betterx/bclib/world/surface/DoubleBlockSurfaceNoiseCondition.java deleted file mode 100644 index b12dfbc6..00000000 --- a/src/main/java/org/betterx/bclib/world/surface/DoubleBlockSurfaceNoiseCondition.java +++ /dev/null @@ -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 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 KEY_CODEC = KeyDispatchDataCodec.of( - CODEC); - private final double threshold; - - public DoubleBlockSurfaceNoiseCondition(double threshold) { - this.threshold = threshold; - } - - @Override - public KeyDispatchDataCodec 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); - } -}