From 3a61c4cb86661a8b9fc5e26f85ab09515b8655ec Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 3 Jun 2022 10:12:12 +0200 Subject: [PATCH 1/3] Code that allows to dump registries to json --- .../org/betterx/bclib/client/BCLibClient.java | 183 ++++++++++++++++++ .../org/betterx/bclib/server/BCLibServer.java | 1 + 2 files changed, 184 insertions(+) diff --git a/src/main/java/org/betterx/bclib/client/BCLibClient.java b/src/main/java/org/betterx/bclib/client/BCLibClient.java index 3cbdb6c3..10f68bef 100644 --- a/src/main/java/org/betterx/bclib/client/BCLibClient.java +++ b/src/main/java/org/betterx/bclib/client/BCLibClient.java @@ -2,18 +2,44 @@ package org.betterx.bclib.client; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.core.Holder; +import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.KeyDispatchDataCodec; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; +import net.minecraft.world.level.material.Fluid; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.model.*; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.serialization.Codec; +import com.mojang.serialization.JsonOps; +import com.mojang.serialization.codecs.KeyDispatchCodec; +import org.betterx.bclib.BCLib; import org.betterx.bclib.api.ModIntegrationAPI; import org.betterx.bclib.api.PostInitAPI; import org.betterx.bclib.api.dataexchange.DataExchangeAPI; +import org.betterx.bclib.blocks.BaseStairsBlock; import org.betterx.bclib.client.models.CustomModelBakery; import org.betterx.bclib.client.presets.WorldPresetsUI; import org.betterx.bclib.registry.BaseBlockEntityRenders; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import org.jetbrains.annotations.Nullable; public class BCLibClient implements ClientModInitializer, ModelResourceProvider, ModelVariantProvider { @@ -30,6 +56,7 @@ public class BCLibClient implements ClientModInitializer, ModelResourceProvider, ModelLoadingRegistry.INSTANCE.registerVariantProvider(rm -> this); WorldPresetsUI.setupClientside(); + //dumpDatapack(); } @Override @@ -45,4 +72,160 @@ public class BCLibClient implements ClientModInitializer, ModelResourceProvider, ? modelBakery.getItemModel(modelId) : modelBakery.getBlockModel(modelId); } + + public static void dumpDatapack() { + final RegistryAccess registryAccess = RegistryAccess.builtinCopy(); + final RegistryOps registryOps = RegistryOps.create(JsonOps.INSTANCE, registryAccess); + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder = gsonBuilder.setPrettyPrinting(); //Sets pretty formatting + Gson gson = gsonBuilder.create(); + registryAccess.registries().forEach(r -> dumpDatapack(r, registryOps, gson)); + } + + public static void dumpDatapack(RegistryAccess.RegistryEntry registry, + RegistryOps registryOps, + Gson gson) { + File base = new File(System.getProperty("user.dir"), "bclib_datapack_dump"); + BCLib.LOGGER.info(registry.key().toString()); + + registry + .value() + .entrySet() + .stream() + .map(e -> e.getKey()).map(key -> registry.value().getHolder(key).get()) + .forEach(holder -> { + File f1 = new File(base, holder.unwrapKey().get().location().getNamespace()); + f1 = new File(f1, registry.key().location().getPath()); + f1.mkdirs(); + f1 = new File(f1, holder.unwrapKey().get().location().getPath() + ".json"); + + Codec[] codec = {null}; + + BCLib.LOGGER.info(" - " + f1); + Object obj = holder; + + while (obj instanceof Holder) { + obj = ((Holder) obj).value(); + } + + if (obj instanceof Structure s) { + codec[0] = s.type().codec(); + } else if (obj instanceof StructureProcessorList s) { + codec[0] = StructureProcessorType.LIST_OBJECT_CODEC; + } else if (obj instanceof GameEvent) { + return; + } else if (obj instanceof Fluid) { + return; + } else if (obj instanceof MobEffect) { + return; + } else if (obj instanceof BaseStairsBlock) { + return; + } + + if (codec[0] == null) { + for (Method m : obj.getClass().getMethods()) { + if (!Modifier.isStatic(m.getModifiers())) { + m.setAccessible(true); + if (m.getParameterTypes().length == 0) { + if (Codec.class.isAssignableFrom(m.getReturnType())) { + try { + codec[0] = (Codec) m.invoke(obj); + BCLib.LOGGER.info(" Got Codec from " + m); + } catch (Exception e) { + BCLib.LOGGER.error(" !!! Unable to get Codec from " + m); + } + } else if (KeyDispatchCodec.class.isAssignableFrom(m.getReturnType())) { + try { + codec[0] = ((KeyDispatchCodec) m.invoke(obj)).codec(); + BCLib.LOGGER.info(" Got Codec from " + m); + } catch (Exception e) { + BCLib.LOGGER.error(" !!! Unable to get Codec from " + m); + } + } else if (KeyDispatchDataCodec.class.isAssignableFrom(m.getReturnType())) { + try { + codec[0] = ((KeyDispatchDataCodec) m.invoke(obj)).codec(); + BCLib.LOGGER.info(" Got Codec from " + m); + } catch (Exception e) { + BCLib.LOGGER.error(" !!! Unable to get Codec from " + m); + } + } + } + } + } + } + + if (codec[0] == null) { + //Try to find DIRECT_CODEC field + for (Field f : obj.getClass().getDeclaredFields()) { + if (Modifier.isStatic(f.getModifiers())) { + if ("DIRECT_CODEC".equals(f.getName())) { + f.setAccessible(true); + try { + codec[0] = (Codec) f.get(null); + BCLib.LOGGER.info(" Got Codec from " + f); + } catch (Exception e) { + BCLib.LOGGER.error(" !!! Unable to get Codec from " + f); + } + } + } + } + } + + //Try to find CODEC field + if (codec[0] == null) { + for (Field f : obj.getClass().getDeclaredFields()) { + if (Modifier.isStatic(f.getModifiers())) { + if ("CODEC".equals(f.getName())) { + try { + f.setAccessible(true); + codec[0] = (Codec) f.get(null); + BCLib.LOGGER.info(" Got Codec from " + f); + } catch (Exception e) { + BCLib.LOGGER.error(" !!! Unable to get Codec from " + f); + } + } + } + } + } + + //Try to find any Codec field + if (codec[0] == null) { + for (Field f : obj.getClass().getDeclaredFields()) { + if (Modifier.isStatic(f.getModifiers())) { + if (Codec.class.isAssignableFrom(f.getType())) { + f.setAccessible(true); + try { + codec[0] = (Codec) f.get(null); + BCLib.LOGGER.info(" Got Codec from " + f); + } catch (Exception e) { + BCLib.LOGGER.error(" !!! Unable to get Codec from " + f); + } + } + } + } + } + + + if (codec[0] != null) { + try { + var o = codec[0] + .encodeStart(registryOps, holder.value()) + .result() + .orElse(new JsonObject()); + + String content = gson.toJson(o); + try { + Files.writeString(f1.toPath(), content, StandardCharsets.UTF_8); + } catch (IOException e) { + BCLib.LOGGER.error(" ->> Unable to WRITE: " + e.getMessage()); + } + } catch (Exception e) { + BCLib.LOGGER.error(" ->> Unable to encode: " + e.getMessage()); + } + } else { + BCLib.LOGGER.error(" !!! Could not determine Codec"); + } + }); + ; + } } diff --git a/src/main/java/org/betterx/bclib/server/BCLibServer.java b/src/main/java/org/betterx/bclib/server/BCLibServer.java index e194fa0f..0b35ab76 100644 --- a/src/main/java/org/betterx/bclib/server/BCLibServer.java +++ b/src/main/java/org/betterx/bclib/server/BCLibServer.java @@ -14,4 +14,5 @@ public class BCLibServer implements DedicatedServerModInitializer { PostInitAPI.postInit(false); } + } From f82d8b6178803d99eaa6a4e000edff612dd91aeb Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 3 Jun 2022 11:31:56 +0200 Subject: [PATCH 2/3] Added Warp Cap Feature --- .../bclib/api/features/BCLFeatureBuilder.java | 4 ++ .../bclib/api/features/ScatterFeature.java | 53 +++++++++---------- .../placement/FindSolidInDirection.java | 42 +++++++++------ .../org/betterx/bclib/util/BlocksHelper.java | 25 +++++++++ 4 files changed, 82 insertions(+), 42 deletions(-) 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 2d276dbd..618457cf 100644 --- a/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java +++ b/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java @@ -275,6 +275,10 @@ public class BCLFeatureBuilder dir, int distance) { + return modifier(new FindSolidInDirection(dir, distance)); + } + public BCLFeatureBuilder heightmap() { return modifier(PlacementUtils.HEIGHTMAP); } diff --git a/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java b/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java index 02dc813a..b681ea23 100644 --- a/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java +++ b/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java @@ -41,21 +41,21 @@ public class ScatterFeature Feature inlineFeature) { List> set = new ArrayList<>(2); if (cfg.floorChance > 0) set.add(PlacementUtils.inlinePlaced(inlineFeature, - cfg, - EnvironmentScanPlacement.scanningFor(Direction.DOWN, - BlockPredicate.solid(), - BlockPredicate.ONLY_IN_AIR_PREDICATE, - 12), - RandomOffsetPlacement.vertical(ConstantInt.of(1)))); + cfg, + EnvironmentScanPlacement.scanningFor(Direction.DOWN, + BlockPredicate.solid(), + BlockPredicate.ONLY_IN_AIR_PREDICATE, + 12), + RandomOffsetPlacement.vertical(ConstantInt.of(1)))); if (cfg.floorChance < 1) { set.add(PlacementUtils.inlinePlaced(inlineFeature, - cfg, - EnvironmentScanPlacement.scanningFor(Direction.UP, - BlockPredicate.solid(), - BlockPredicate.ONLY_IN_AIR_PREDICATE, - 12), - RandomOffsetPlacement.vertical(ConstantInt.of(-1)))); + cfg, + EnvironmentScanPlacement.scanningFor(Direction.UP, + BlockPredicate.solid(), + BlockPredicate.ONLY_IN_AIR_PREDICATE, + 12), + RandomOffsetPlacement.vertical(ConstantInt.of(-1)))); } SimpleRandomFeatureConfiguration configuration = new SimpleRandomFeatureConfiguration(HolderSet.direct(set)); @@ -87,7 +87,8 @@ public class ScatterFeature if (direction.isEmpty()) { return false; } - BlockPos basePos = origin.relative(direction.get().getOpposite()); + BlockPos basePos = origin.relative(direction.get(), -1); + int i = (int) (random.nextFloat() * (1 + config.maxHeight - config.minHeight) + config.minHeight); growCenterPillar(level, origin, basePos, direction.get(), i, config, random); @@ -105,10 +106,8 @@ public class ScatterFeature if (config.isValidBase(level.getBlockState(basePos))) { final Direction surfaceDirection = direction.getOpposite(); BlockPos.MutableBlockPos POS = new BlockPos.MutableBlockPos(); - basePos = basePos.relative(direction, 1); buildPillarWithBase(level, origin, basePos, direction, centerHeight, config, random); - - + final double distNormalizer = (config.maxSpread * Math.sqrt(2)); final int tryCount = config.spreadCount.sample(random); for (int i = 0; i < tryCount; i++) { @@ -120,10 +119,10 @@ public class ScatterFeature int myHeight; if (config.growWhileFree) { myHeight = BlocksHelper.blockCount(level, - POS, - direction, - config.maxHeight, - state -> state.getMaterial().isReplaceable()); + POS, + direction, + config.maxHeight, + state -> state.getMaterial().isReplaceable()); } else { myHeight = centerHeight; } @@ -136,15 +135,15 @@ public class ScatterFeature myHeight = (int) Math.min(Math.max( config.minHeight, config.minHeight + sizeFactor * (myHeight - config.minHeight) - ), config.maxHeight); + ), config.maxHeight); buildPillarWithBase(level, - POS, - POS.relative(direction.getOpposite()), - direction, - myHeight, - config, - random); + POS, + POS.relative(direction.getOpposite()), + direction, + myHeight, + config, + random); } } } 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 f634886d..d73ebb96 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 @@ -2,6 +2,7 @@ package org.betterx.bclib.api.features.placement; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.util.ExtraCodecs; import net.minecraft.util.RandomSource; import net.minecraft.world.level.levelgen.placement.PlacementContext; import net.minecraft.world.level.levelgen.placement.PlacementModifier; @@ -12,20 +13,30 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import org.betterx.bclib.api.tag.CommonBlockTags; import org.betterx.bclib.util.BlocksHelper; +import java.util.List; import java.util.stream.Stream; public class FindSolidInDirection extends PlacementModifier { + public static final Codec CODEC = RecordCodecBuilder + .create((instance) -> instance.group( + ExtraCodecs.nonEmptyList(Direction.CODEC.listOf()) + .fieldOf("dir") + .orElse(List.of(Direction.DOWN)) + .forGetter(a -> a.direction), + Codec.intRange(1, 32).fieldOf("dist").orElse(12).forGetter((p) -> p.maxSearchDistance)) + .apply(instance, + FindSolidInDirection::new)); protected static final FindSolidInDirection DOWN = new FindSolidInDirection(Direction.DOWN, 6); protected static final FindSolidInDirection UP = new FindSolidInDirection(Direction.UP, 6); - public static final Codec CODEC = RecordCodecBuilder.create((instance) -> instance - .group( - Direction.CODEC.fieldOf("dir").orElse(Direction.DOWN).forGetter((p) -> p.direction), - Codec.intRange(1, 32).fieldOf("dist").orElse(12).forGetter((p) -> p.maxSearchDistance) - ) - .apply(instance, FindSolidInDirection::new)); + private final List direction; + private final int maxSearchDistance; public FindSolidInDirection(Direction direction, int maxSearchDistance) { + this(List.of(direction), maxSearchDistance); + } + + public FindSolidInDirection(List direction, int maxSearchDistance) { this.direction = direction; this.maxSearchDistance = maxSearchDistance; } @@ -48,25 +59,26 @@ public class FindSolidInDirection extends PlacementModifier { return new FindSolidInDirection(Direction.UP, dist); } + public Direction randomDirection(RandomSource random) { + return direction.get(Math.max(0, Math.min(direction.size(), random.nextInt(direction.size())))); + } @Override public Stream getPositions(PlacementContext placementContext, RandomSource randomSource, BlockPos blockPos) { BlockPos.MutableBlockPos POS = blockPos.mutable(); - if (BlocksHelper.findSurroundingSurface(placementContext.getLevel(), - POS, - direction, - maxSearchDistance, - state -> state.is(CommonBlockTags.TERRAIN)) - ) return Stream.of(POS); + Direction d = randomDirection(randomSource); + if (BlocksHelper.findOnSurroundingSurface(placementContext.getLevel(), + POS, + d, + maxSearchDistance, + state -> state.is(CommonBlockTags.TERRAIN))) + return Stream.of(POS); return Stream.of(); } - private final Direction direction; - private final int maxSearchDistance; - @Override public PlacementModifierType type() { return PlacementModifiers.SOLID_IN_DIR; diff --git a/src/main/java/org/betterx/bclib/util/BlocksHelper.java b/src/main/java/org/betterx/bclib/util/BlocksHelper.java index e0ee04cc..ec94ba34 100644 --- a/src/main/java/org/betterx/bclib/util/BlocksHelper.java +++ b/src/main/java/org/betterx/bclib/util/BlocksHelper.java @@ -229,6 +229,31 @@ public class BlocksHelper { return false; } + public static boolean findOnSurroundingSurface(LevelAccessor level, + MutableBlockPos startPos, + Direction dir, + int length, + Predicate surface) { + for (int len = 0; len < length; len++) { + if (surface.test(level.getBlockState(startPos))) { + if (len == 0) { //we started inside of the surface + for (int lenUp = 0; lenUp < length; lenUp++) { + startPos.move(dir, -1); + if (!surface.test(level.getBlockState(startPos))) { + return true; + } + } + return false; + } + startPos.move(dir, -1); + return true; + } + + startPos.move(dir, 1); + } + return false; + } + public static boolean findSurroundingSurface(LevelAccessor level, MutableBlockPos startPos, Direction dir, From e7486c8aa4da678b53411efc414962feb87cee28 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 3 Jun 2022 12:37:34 +0200 Subject: [PATCH 3/3] More Feature Updates --- .../bclib/api/features/BCLFeature.java | 15 +- .../bclib/api/features/BCLFeatureBuilder.java | 16 ++ .../bclib/api/features/BlockPlaceFeature.java | 25 --- .../bclib/api/features/ScatterFeature.java | 4 +- .../config/BlockPlaceFeatureConfig.java | 59 ----- .../features/config/ScatterFeatureConfig.java | 202 +++++++++--------- .../placement/IsEmptyAboveSampledFilter.java | 27 ++- 7 files changed, 150 insertions(+), 198 deletions(-) delete mode 100644 src/main/java/org/betterx/bclib/api/features/BlockPlaceFeature.java delete mode 100644 src/main/java/org/betterx/bclib/api/features/config/BlockPlaceFeatureConfig.java 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 f529b5c8..ff41bb66 100644 --- a/src/main/java/org/betterx/bclib/api/features/BCLFeature.java +++ b/src/main/java/org/betterx/bclib/api/features/BCLFeature.java @@ -15,7 +15,6 @@ 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.BlockPlaceFeatureConfig; import org.betterx.bclib.api.features.config.ScatterFeatureConfig; import java.util.Map.Entry; @@ -25,11 +24,7 @@ public class BCLFeature { public static final Feature SCATTER_ON_SOLID = register( BCLib.makeID("scatter_on_solid"), new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC) - ); - public static final Feature PLACE_BLOCK = register( - BCLib.makeID("place_block"), - new BlockPlaceFeature<>(BlockPlaceFeatureConfig.CODEC) - ); + ); private final Holder placedFeature; private final Decoration featureStep; private final Feature feature; @@ -67,12 +62,12 @@ public class BCLFeature { Holder> configuredFeature; if (!BuiltinRegistries.CONFIGURED_FEATURE.containsKey(id)) { configuredFeature = (Holder>) (Object) FeatureUtils.register(id.toString(), - feature, - configuration); + feature, + configuration); } else { configuredFeature = BuiltinRegistries.CONFIGURED_FEATURE .getHolder(ResourceKey.create(BuiltinRegistries.CONFIGURED_FEATURE.key(), - id)) + id)) .orElseThrow(); } @@ -80,7 +75,7 @@ public class BCLFeature { return PlacementUtils.register(id.toString(), configuredFeature, modifiers); } else { return BuiltinRegistries.PLACED_FEATURE.getHolder(ResourceKey.create(BuiltinRegistries.PLACED_FEATURE.key(), - id)).orElseThrow(); + id)).orElseThrow(); } } 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 618457cf..07efa707 100644 --- a/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java +++ b/src/main/java/org/betterx/bclib/api/features/BCLFeatureBuilder.java @@ -189,10 +189,26 @@ public class BCLFeatureBuilder 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/ScatterFeature.java b/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java index b681ea23..507184b4 100644 --- a/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java +++ b/src/main/java/org/betterx/bclib/api/features/ScatterFeature.java @@ -68,7 +68,7 @@ public class ScatterFeature .modifier(RandomOffsetPlacement.of( ClampedNormalInt.of(0.0f, 2.0f, -6, 6), ClampedNormalInt.of(0.0f, 0.6f, -2, 2))) - .modifier(BiomeFilter.biome()) + .onlyInBiome() .buildAndRegister(configuration); } @@ -107,7 +107,7 @@ public class ScatterFeature final Direction surfaceDirection = direction.getOpposite(); BlockPos.MutableBlockPos POS = new BlockPos.MutableBlockPos(); buildPillarWithBase(level, origin, basePos, direction, centerHeight, config, random); - + final double distNormalizer = (config.maxSpread * Math.sqrt(2)); final int tryCount = config.spreadCount.sample(random); for (int i = 0; i < tryCount; i++) { 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/ScatterFeatureConfig.java b/src/main/java/org/betterx/bclib/api/features/config/ScatterFeatureConfig.java index 9bd897a0..df83dfa9 100644 --- a/src/main/java/org/betterx/bclib/api/features/config/ScatterFeatureConfig.java +++ b/src/main/java/org/betterx/bclib/api/features/config/ScatterFeatureConfig.java @@ -17,7 +17,7 @@ import org.betterx.bclib.api.tag.CommonBlockTags; import java.util.Optional; public abstract class ScatterFeatureConfig implements FeatureConfiguration { - public interface Instancer extends Function15, Float, Float, Float, Float, Integer, Integer, Float, Float, Float, Boolean, IntProvider, T> { + public interface Instancer extends Function15, Optional, Optional, Float, Float, Float, Float, Integer, Integer, Float, Float, Float, Boolean, IntProvider, T> { } public final BlockState clusterBlock; @@ -39,8 +39,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { public final boolean growWhileFree; public ScatterFeatureConfig(BlockState clusterBlock, - BlockState tipBlock, - BlockState bottomBlock, + Optional tipBlock, + Optional bottomBlock, Optional baseState, float baseReplaceChance, float chanceOfDirectionalSpread, @@ -54,8 +54,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { boolean growWhileFree, IntProvider spreadCount) { this.clusterBlock = clusterBlock; - this.tipBlock = tipBlock == null ? clusterBlock : tipBlock; - this.bottomBlock = bottomBlock == null ? clusterBlock : bottomBlock; + this.tipBlock = tipBlock.orElse(clusterBlock); + this.bottomBlock = bottomBlock.orElse(clusterBlock); this.baseState = baseState; this.baseReplaceChance = baseReplaceChance; this.chanceOfDirectionalSpread = chanceOfDirectionalSpread; @@ -81,77 +81,81 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { public static Codec buildCodec(Instancer instancer) { return RecordCodecBuilder.create((instance) -> instance - .group(BlockState.CODEC - .fieldOf("cluster_block") - .forGetter((T cfg) -> cfg.clusterBlock), - BlockState.CODEC - .fieldOf("tip_block") - .orElse(null) - .forGetter((T cfg) -> cfg.tipBlock), - BlockState.CODEC - .fieldOf("bottom_block") - .orElse(null) - .forGetter((T cfg) -> cfg.bottomBlock), - BlockState.CODEC - .optionalFieldOf("base_state") - .forGetter((T cfg) -> cfg.baseState), - Codec - .floatRange(0.0F, 1.0F) - .fieldOf("baseReplaceChance") - .orElse(1.0F) - .forGetter((T cfg) -> cfg.baseReplaceChance), - Codec - .floatRange(0.0F, 1.0F) - .fieldOf("chance_of_directional_spread") - .orElse(0.7F) - .forGetter((T cfg) -> cfg.chanceOfDirectionalSpread), - Codec - .floatRange(0.0F, 1.0F) - .fieldOf("chance_of_spread_radius2") - .orElse(0.5F) - .forGetter((T cfg) -> cfg.chanceOfSpreadRadius2), - Codec - .floatRange(0.0F, 1.0F) - .fieldOf("chance_of_spread_radius3") - .orElse(0.5F) - .forGetter((T cfg) -> cfg.chanceOfSpreadRadius3), - Codec - .intRange(1, 20) - .fieldOf("min_height") - .orElse(2) - .forGetter((T cfg) -> cfg.minHeight), - Codec - .intRange(1, 20) - .fieldOf("max_height") - .orElse(7) - .forGetter((T cfg) -> cfg.maxHeight), - Codec - .floatRange(0, 10) - .fieldOf("max_spread") - .orElse(2f) - .forGetter((T cfg) -> cfg.maxSpread), - Codec - .floatRange(0, 1) - .fieldOf("size_variation") - .orElse(0.7f) - .forGetter((T cfg) -> cfg.sizeVariation), - Codec - .floatRange(0, 1) - .fieldOf("floor_chance") - .orElse(0.5f) - .forGetter((T cfg) -> cfg.floorChance), - Codec - .BOOL - .fieldOf("grow_while_empty") - .orElse(false) - .forGetter((T cfg) -> cfg.growWhileFree), - IntProvider.codec(0, 64) - .fieldOf("length") - .orElse(UniformInt.of(0, 3)) - .forGetter(cfg -> cfg.spreadCount) - ) - .apply(instance, instancer) - ); + .group(BlockState.CODEC + .fieldOf("cluster_block") + .forGetter((T cfg) -> cfg.clusterBlock), + BlockState.CODEC + .optionalFieldOf("tip_block") + .orElse(Optional.empty()) + .forGetter((T cfg) -> cfg.tipBlock == cfg.clusterBlock + ? Optional.empty() + : Optional.of(cfg.tipBlock)), + BlockState.CODEC + .optionalFieldOf("bottom_block") + .orElse(Optional.empty()) + .forGetter((T cfg) -> cfg.bottomBlock == cfg.clusterBlock + ? Optional.empty() + : Optional.of(cfg.bottomBlock)), + BlockState.CODEC + .optionalFieldOf("base_state") + .forGetter((T cfg) -> cfg.baseState), + Codec + .floatRange(0.0F, 1.0F) + .fieldOf("baseReplaceChance") + .orElse(1.0F) + .forGetter((T cfg) -> cfg.baseReplaceChance), + Codec + .floatRange(0.0F, 1.0F) + .fieldOf("chance_of_directional_spread") + .orElse(0.7F) + .forGetter((T cfg) -> cfg.chanceOfDirectionalSpread), + Codec + .floatRange(0.0F, 1.0F) + .fieldOf("chance_of_spread_radius2") + .orElse(0.5F) + .forGetter((T cfg) -> cfg.chanceOfSpreadRadius2), + Codec + .floatRange(0.0F, 1.0F) + .fieldOf("chance_of_spread_radius3") + .orElse(0.5F) + .forGetter((T cfg) -> cfg.chanceOfSpreadRadius3), + Codec + .intRange(1, 20) + .fieldOf("min_height") + .orElse(2) + .forGetter((T cfg) -> cfg.minHeight), + Codec + .intRange(1, 20) + .fieldOf("max_height") + .orElse(7) + .forGetter((T cfg) -> cfg.maxHeight), + Codec + .floatRange(0, 10) + .fieldOf("max_spread") + .orElse(2f) + .forGetter((T cfg) -> cfg.maxSpread), + Codec + .floatRange(0, 1) + .fieldOf("size_variation") + .orElse(0.7f) + .forGetter((T cfg) -> cfg.sizeVariation), + Codec + .floatRange(0, 1) + .fieldOf("floor_chance") + .orElse(0.5f) + .forGetter((T cfg) -> cfg.floorChance), + Codec + .BOOL + .fieldOf("grow_while_empty") + .orElse(false) + .forGetter((T cfg) -> cfg.growWhileFree), + IntProvider.codec(0, 64) + .fieldOf("length") + .orElse(UniformInt.of(0, 3)) + .forGetter(cfg -> cfg.spreadCount) + ) + .apply(instance, instancer) + ); } public static class Builder { @@ -240,10 +244,10 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { float chanceOfSpreadRadius2, float chanceOfSpreadRadius3) { return generateBaseBlock(baseState, - 1, - chanceOfDirectionalSpread, - chanceOfSpreadRadius2, - chanceOfSpreadRadius3); + 1, + chanceOfDirectionalSpread, + chanceOfSpreadRadius2, + chanceOfSpreadRadius3); } public Builder generateBaseBlock(BlockState baseState, @@ -291,8 +295,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { public T build() { return instancer.apply( this.clusterBlock, - this.tipBlock, - this.bottomBlock, + Optional.of(this.tipBlock), + Optional.of(this.bottomBlock), this.baseState, this.baseReplaceChance, this.chanceOfDirectionalSpread, @@ -305,7 +309,7 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { this.floorChance, this.growWhileFree, this.spreadCount - ); + ); } } @@ -313,8 +317,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { public static final Codec CODEC = buildCodec(OnSolid::new); public OnSolid(BlockState clusterBlock, - BlockState tipBlock, - BlockState bottomBlock, + Optional tipBlock, + Optional bottomBlock, Optional baseState, float baseReplaceChance, float chanceOfDirectionalSpread, @@ -328,20 +332,20 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration { boolean growWhileFree, IntProvider spreadCount) { super(clusterBlock, - tipBlock, - bottomBlock, - baseState, - baseReplaceChance, - chanceOfDirectionalSpread, - chanceOfSpreadRadius2, - chanceOfSpreadRadius3, - minHeight, - maxHeight, - maxSpread, - sizeVariation, - floorChance, - growWhileFree, - spreadCount); + tipBlock, + bottomBlock, + baseState, + baseReplaceChance, + chanceOfDirectionalSpread, + chanceOfSpreadRadius2, + chanceOfSpreadRadius3, + minHeight, + maxHeight, + maxSpread, + sizeVariation, + floorChance, + growWhileFree, + spreadCount); } diff --git a/src/main/java/org/betterx/bclib/api/features/placement/IsEmptyAboveSampledFilter.java b/src/main/java/org/betterx/bclib/api/features/placement/IsEmptyAboveSampledFilter.java index c342ed19..46f5feb9 100644 --- a/src/main/java/org/betterx/bclib/api/features/placement/IsEmptyAboveSampledFilter.java +++ b/src/main/java/org/betterx/bclib/api/features/placement/IsEmptyAboveSampledFilter.java @@ -16,21 +16,42 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; public class IsEmptyAboveSampledFilter extends PlacementFilter { private static final IsEmptyAboveSampledFilter DEFAULT = new IsEmptyAboveSampledFilter(4, 2); private static final IsEmptyAboveSampledFilter DEFAULT1 = new IsEmptyAboveSampledFilter(1, 1); + private static final IsEmptyAboveSampledFilter DEFAULT2 = new IsEmptyAboveSampledFilter(1, 2); + + private static final IsEmptyAboveSampledFilter BELOW_DEFAULT = new IsEmptyAboveSampledFilter(-4, -2); + private static final IsEmptyAboveSampledFilter BELOW_DEFAULT1 = new IsEmptyAboveSampledFilter(-1, -1); + private static final IsEmptyAboveSampledFilter BELOW_DEFAULT2 = new IsEmptyAboveSampledFilter(-1, -2); public static final Codec CODEC = RecordCodecBuilder.create((instance) -> instance .group( - Codec.intRange(1, 32).fieldOf("d1").orElse(2).forGetter((p) -> p.distance1), - Codec.intRange(1, 32).fieldOf("d2").orElse(4).forGetter((p) -> p.distance1) - ) + Codec.intRange(-32, 32).fieldOf("d1").orElse(4).forGetter((p) -> p.distance1), + Codec.intRange(-32, 32).fieldOf("d2").orElse(2).forGetter((p) -> p.distance1) + ) .apply(instance, IsEmptyAboveSampledFilter::new)); public static PlacementFilter emptyAbove4() { return DEFAULT; } + public static PlacementFilter emptyAbove2() { + return DEFAULT2; + } + public static PlacementFilter emptyAbove() { return DEFAULT1; } + public static PlacementFilter emptyBelow4() { + return BELOW_DEFAULT; + } + + public static PlacementFilter emptyBelow2() { + return BELOW_DEFAULT2; + } + + public static PlacementFilter emptyBelow() { + return BELOW_DEFAULT1; + } + public IsEmptyAboveSampledFilter(int d1, int d2) { this.distance1 = d1; this.distance2 = d2;