Flooded Deltas

This commit is contained in:
Frank 2022-06-06 01:00:50 +02:00
parent f94a8f158f
commit db0c89e7e7
19 changed files with 559 additions and 237 deletions

View file

@ -14,9 +14,11 @@ import net.fabricmc.loader.api.FabricLoader;
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.blockpredicates.Types;
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.commands.CommandRegistry;
import org.betterx.bclib.config.Configs;
import org.betterx.bclib.presets.worldgen.BCLWorldPresets;
import org.betterx.bclib.recipes.AnvilRecipe;
@ -38,6 +40,7 @@ public class BCLib implements ModInitializer {
@Override
public void onInitialize() {
Types.ensureStaticInitialization();
BaseRegistry.register();
GeneratorOptions.init();
BaseBlockEntities.register();
@ -51,6 +54,7 @@ public class BCLib implements ModInitializer {
BCLWorldPresets.registerPresets();
AnvilRecipe.register();
Conditions.registerAll();
CommandRegistry.register();
DataExchangeAPI.registerDescriptors(List.of(
HelloClient.DESCRIPTOR,

View file

@ -11,14 +11,13 @@ import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
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.NoneFeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.RandomFeatureConfiguration;
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;
import org.betterx.bclib.api.features.config.*;
import java.util.Map.Entry;
import java.util.Optional;
@ -37,6 +36,16 @@ public class BCLFeature {
public static final Feature<TemplateFeatureConfig> TEMPLATE = register(BCLib.makeID("template"),
new TemplateFeature(
TemplateFeatureConfig.CODEC));
public static final Feature<NoneFeatureConfiguration> MARK_POSTPROCESSING = register(BCLib.makeID(
"mark_postprocessing"),
new MarkPostProcessingFeature());
public static final Feature<SequenceFeatureConfig> SEQUENCE = register(BCLib.makeID("sequence"),
new SequenceFeature());
public static final Feature<ConditionFeatureConfig> CONDITION = register(BCLib.makeID("condition"),
new ConditionFeature());
private final Holder<PlacedFeature> placedFeature;
private final Decoration featureStep;
private final Feature<?> feature;

View file

@ -6,10 +6,15 @@ import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.valueproviders.IntProvider;
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.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.SimpleBlockFeature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.SimpleBlockConfiguration;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import net.minecraft.world.level.levelgen.placement.*;
import net.minecraft.world.level.material.Material;
@ -24,6 +29,7 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
private ResourceLocation featureID;
private Decoration decoration = Decoration.VEGETAL_DECORATION;
private final F feature;
private BlockStateProvider provider;
private BCLFeatureBuilder(ResourceLocation featureID, F feature) {
this.featureID = featureID;
@ -41,6 +47,26 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
return new BCLFeatureBuilder(featureID, feature);
}
public static BCLFeatureBuilder<SimpleBlockConfiguration, SimpleBlockFeature> start(ResourceLocation featureID,
Block block) {
return start(featureID, BlockStateProvider.simple(block));
}
public static BCLFeatureBuilder<SimpleBlockConfiguration, SimpleBlockFeature> start(ResourceLocation featureID,
BlockState state) {
return start(featureID, BlockStateProvider.simple(state));
}
public static BCLFeatureBuilder<SimpleBlockConfiguration, SimpleBlockFeature> start(ResourceLocation featureID,
BlockStateProvider provider) {
BCLFeatureBuilder<SimpleBlockConfiguration, SimpleBlockFeature> builder = new BCLFeatureBuilder(
featureID,
Feature.SIMPLE_BLOCK
);
builder.provider = provider;
return builder;
}
/**
* Set generation step for the feature. Default is {@code VEGETAL_DECORATION}.
*
@ -143,6 +169,10 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
return modifier(Stencil.all());
}
public BCLFeatureBuilder all() {
return modifier(All.simple());
}
public BCLFeatureBuilder stencilOneIn4() {
return modifier(Stencil.oneIn4());
}
@ -331,6 +361,8 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
* @return created {@link BCLFeature} instance.
*/
public BCLFeature buildAndRegister() {
if (this.feature == Feature.SIMPLE_BLOCK && provider != null)
return buildAndRegister((FC) new SimpleBlockConfiguration(provider));
return buildAndRegister((FC) FeatureConfiguration.NONE);
}

View file

@ -0,0 +1,38 @@
package org.betterx.bclib.api.features;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.PlacementContext;
import org.betterx.bclib.api.features.config.ConditionFeatureConfig;
import java.util.Optional;
import java.util.stream.Stream;
public class ConditionFeature extends Feature<ConditionFeatureConfig> {
public ConditionFeature() {
super(ConditionFeatureConfig.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<ConditionFeatureConfig> ctx) {
final ConditionFeatureConfig cfg = ctx.config();
final WorldGenLevel level = ctx.level();
final RandomSource random = ctx.random();
final BlockPos pos = ctx.origin();
final PlacementContext c = new PlacementContext(level, ctx.chunkGenerator(), Optional.empty());
Stream<BlockPos> stream = cfg.filter.getPositions(c, ctx.random(), pos);
Holder<PlacedFeature> state = (stream.findFirst().isPresent() ? cfg.okFeature : cfg.failFeature.orElse(null));
if (state != null) {
return state.value().place(level, ctx.chunkGenerator(), random, pos);
}
return false;
}
}

View file

@ -90,6 +90,19 @@ public class FastFeatures {
return simple(location, searchDist, rare, feature, NoneFeatureConfiguration.NONE);
}
public static BCLFeature
single(ResourceLocation location, Block block) {
return single(location, BlockStateProvider.simple(block));
}
public static BCLFeature
single(ResourceLocation location, BlockStateProvider provider) {
return BCLFeatureBuilder
.start(location, provider)
.buildAndRegister();
}
public static BCLFeature
simple(ResourceLocation location,
int searchDist,

View file

@ -0,0 +1,20 @@
package org.betterx.bclib.api.features;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
public class MarkPostProcessingFeature extends Feature<NoneFeatureConfiguration> {
public MarkPostProcessingFeature() {
super(NoneFeatureConfiguration.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> ctx) {
BlockPos pos = ctx.origin();
ctx.level().getChunk(pos.getX() >> 4, pos.getZ() >> 4)
.markPosForPostprocessing(new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15));
return true;
}
}

View file

@ -0,0 +1,17 @@
package org.betterx.bclib.api.features;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import org.betterx.bclib.api.features.config.SequenceFeatureConfig;
public class SequenceFeature extends Feature<SequenceFeatureConfig> {
public SequenceFeature() {
super(SequenceFeatureConfig.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<SequenceFeatureConfig> featurePlaceContext) {
return featurePlaceContext.config().placeAll(featurePlaceContext);
}
}

View file

@ -0,0 +1,42 @@
package org.betterx.bclib.api.features.blockpredicates;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicateType;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
public class IsFullShape implements BlockPredicate {
public static final IsFullShape HERE = new IsFullShape();
public static final Codec<IsFullShape> CODEC = RecordCodecBuilder.create(
instance -> instance
.group(
Vec3i.offsetCodec(16).optionalFieldOf("offset", Vec3i.ZERO).forGetter((p) -> p.offset)
).apply(instance, IsFullShape::new));
protected final Vec3i offset;
private IsFullShape() {
this(Vec3i.ZERO);
}
public IsFullShape(Vec3i offset) {
super();
this.offset = offset;
}
public BlockPredicateType<IsFullShape> type() {
return Types.FULL_SHAPE;
}
@Override
public boolean test(WorldGenLevel worldGenLevel, BlockPos blockPos) {
BlockState state = worldGenLevel.getBlockState(blockPos.offset(this.offset));
return state.isCollisionShapeFullBlock(worldGenLevel, blockPos);
}
}

View file

@ -0,0 +1,22 @@
package org.betterx.bclib.api.features.blockpredicates;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicateType;
import com.mojang.serialization.Codec;
import org.betterx.bclib.BCLib;
public class Types {
public static final BlockPredicateType<IsFullShape> FULL_SHAPE = register(BCLib.makeID("full_shape"),
IsFullShape.CODEC);
public static <P extends BlockPredicate> BlockPredicateType<P> register(ResourceLocation location, Codec<P> codec) {
return Registry.register(Registry.BLOCK_PREDICATE_TYPES, location, () -> codec);
}
public static void ensureStaticInitialization() {
}
}

View file

@ -0,0 +1,60 @@
package org.betterx.bclib.api.features.config;
import net.minecraft.core.Holder;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.PlacementFilter;
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import org.betterx.bclib.api.features.BCLFeature;
import java.util.Optional;
import org.jetbrains.annotations.NotNull;
public class ConditionFeatureConfig implements FeatureConfiguration {
public static final Codec<ConditionFeatureConfig> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
PlacementModifier.CODEC.fieldOf("filter").forGetter(p -> p.filter),
PlacedFeature.CODEC.fieldOf("filter_pass").forGetter(p -> p.okFeature),
PlacedFeature.CODEC.optionalFieldOf("filter_fail").forGetter(p -> p.failFeature)
).apply(instance, ConditionFeatureConfig::new)
);
public final PlacementModifier filter;
public final Holder<PlacedFeature> okFeature;
public final Optional<Holder<PlacedFeature>> failFeature;
public ConditionFeatureConfig(@NotNull PlacementFilter filter,
@NotNull BCLFeature okFeature) {
this(filter, okFeature.getPlacedFeature(), Optional.empty());
}
public ConditionFeatureConfig(@NotNull PlacementFilter filter,
@NotNull BCLFeature okFeature,
@NotNull BCLFeature failFeature) {
this(filter, okFeature.getPlacedFeature(), Optional.of(failFeature.getPlacedFeature()));
}
public ConditionFeatureConfig(@NotNull PlacementFilter filter,
@NotNull Holder<PlacedFeature> okFeature) {
this(filter, okFeature, Optional.empty());
}
public ConditionFeatureConfig(@NotNull PlacementFilter filter,
@NotNull Holder<PlacedFeature> okFeature,
@NotNull Holder<PlacedFeature> failFeature) {
this(filter, okFeature, Optional.of(failFeature));
}
protected ConditionFeatureConfig(@NotNull PlacementModifier filter,
@NotNull Holder<PlacedFeature> okFeature,
@NotNull Optional<Holder<PlacedFeature>> failFeature) {
this.filter = filter;
this.okFeature = okFeature;
this.failFeature = failFeature;
}
}

View file

@ -8,22 +8,22 @@ 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 net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import net.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider;
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)
protected static <T extends PlaceBlockFeatureConfig> RecordCodecBuilder<T, BlockStateProvider> blockStateCodec() {
return BlockStateProvider.CODEC
.fieldOf("entries")
.forGetter((T o) -> o.weightedList);
.forGetter((T o) -> o.stateProvider);
}
protected final SimpleWeightedRandomList<BlockState> weightedList;
protected final BlockStateProvider stateProvider;
protected static SimpleWeightedRandomList<BlockState> buildWeightedList(List<BlockState> states) {
@ -44,7 +44,7 @@ public abstract class PlaceBlockFeatureConfig implements FeatureConfiguration {
}
public PlaceBlockFeatureConfig(BlockState state) {
this(buildWeightedList(state));
this(BlockStateProvider.simple(state));
}
@ -53,19 +53,20 @@ public abstract class PlaceBlockFeatureConfig implements FeatureConfiguration {
}
public PlaceBlockFeatureConfig(SimpleWeightedRandomList<BlockState> blocks) {
this.weightedList = blocks;
this.stateProvider = new WeightedStateProvider(blocks);
}
public Optional<BlockState> getRandomBlock(RandomSource random) {
return this.weightedList.getRandomValue(random);
public PlaceBlockFeatureConfig(BlockStateProvider blocks) {
this.stateProvider = blocks;
}
public BlockState getRandomBlock(RandomSource random, BlockPos pos) {
return this.stateProvider.getState(random, pos);
}
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;
BlockState state = getRandomBlock(ctx.random(), ctx.origin());
return placeBlock(ctx, ctx.level(), ctx.origin(), state);
}

View file

@ -9,6 +9,8 @@ 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 net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import net.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@ -45,7 +47,7 @@ public class PlaceFacingBlockConfig extends PlaceBlockFeatureConfig {
}
public PlaceFacingBlockConfig(BlockState state, List<Direction> dir) {
this(buildWeightedList(state), dir);
this(BlockStateProvider.simple(state), dir);
}
public PlaceFacingBlockConfig(List<BlockState> states, List<Direction> dir) {
@ -53,6 +55,10 @@ public class PlaceFacingBlockConfig extends PlaceBlockFeatureConfig {
}
public PlaceFacingBlockConfig(SimpleWeightedRandomList<BlockState> blocks, List<Direction> dir) {
this(new WeightedStateProvider(blocks), dir);
}
public PlaceFacingBlockConfig(BlockStateProvider blocks, List<Direction> dir) {
super(blocks);
directions = dir;
}

View file

@ -0,0 +1,42 @@
package org.betterx.bclib.api.features.config;
import net.minecraft.core.Holder;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import org.betterx.bclib.api.features.BCLFeature;
import java.util.List;
public class SequenceFeatureConfig implements FeatureConfiguration {
public static final Codec<SequenceFeatureConfig> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
ExtraCodecs.nonEmptyList(PlacedFeature.CODEC.listOf())
.fieldOf("features")
.forGetter(a -> a.features)
).apply(instance, SequenceFeatureConfig::new)
);
private final List<Holder<PlacedFeature>> features;
public static SequenceFeatureConfig create(List<BCLFeature> features) {
return new SequenceFeatureConfig(features.stream().map(f -> f.getPlacedFeature()).toList());
}
public SequenceFeatureConfig(List<Holder<PlacedFeature>> features) {
this.features = features;
}
public boolean placeAll(FeaturePlaceContext<SequenceFeatureConfig> ctx) {
boolean placed = false;
for (Holder<PlacedFeature> f : features) {
placed |= f.value().place(ctx.level(), ctx.chunkGenerator(), ctx.random(), ctx.origin());
}
return placed;
}
}

View file

@ -0,0 +1,33 @@
package org.betterx.bclib.api.features.placement;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.placement.PlacementContext;
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
import com.mojang.serialization.Codec;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class All extends PlacementModifier {
private static final All INSTANCE = new All();
public static final Codec<All> CODEC = Codec.unit(All::new);
@Override
public Stream<BlockPos> getPositions(PlacementContext placementContext,
RandomSource randomSource,
BlockPos blockPos) {
return IntStream.range(0, 16 * 16 - 1).mapToObj(i -> blockPos.offset(i & 0xF, 0, i >> 4));
}
public static PlacementModifier simple() {
return INSTANCE;
}
@Override
public PlacementModifierType<?> type() {
return PlacementModifiers.ALL;
}
}

View file

@ -38,7 +38,7 @@ public class IsBasin extends PlacementFilter {
this.topPredicate = topPredicate;
}
public static IsBasin simple(BlockPredicate predicate) {
public static PlacementFilter simple(BlockPredicate predicate) {
return new IsBasin(predicate);
}

View file

@ -25,6 +25,10 @@ public class PlacementModifiers {
"stencil",
Stencil.CODEC);
public static final PlacementModifierType<All> ALL = register(
"all",
All.CODEC);
public static final PlacementModifierType<IsBasin> IS_BASIN = register(
"is_basin",
IsBasin.CODEC);

View file

@ -2,44 +2,18 @@ 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 {
@ -73,159 +47,5 @@ public class BCLibClient implements ClientModInitializer, ModelResourceProvider,
: modelBakery.getBlockModel(modelId);
}
public static void dumpDatapack() {
final RegistryAccess registryAccess = RegistryAccess.builtinCopy();
final RegistryOps<JsonElement> 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 <T> void dumpDatapack(RegistryAccess.RegistryEntry<T> registry,
RegistryOps<JsonElement> 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");
}
});
;
}
}

View file

@ -0,0 +1,196 @@
package org.betterx.bclib.commands;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.RegistryOps;
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 com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.context.CommandContext;
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.blocks.BaseStairsBlock;
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;
public class DumpDatapack {
static int dumpDatapack(CommandContext<CommandSourceStack> ctx) {
dumpDatapack();
return Command.SINGLE_SUCCESS;
}
public static void dumpDatapack() {
final RegistryAccess registryAccess = RegistryAccess.builtinCopy();
final RegistryOps<JsonElement> 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));
}
private static <T> void dumpDatapack(RegistryAccess.RegistryEntry<T> registry,
RegistryOps<JsonElement> 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");
}
});
;
}
}

View file

@ -1,37 +0,0 @@
{
"type": "minecraft:the_nether",
"generator": {
"biome_source": {
"biomes": [
{
"parameters": {
"erosion": 0.0,
"depth": 0.0,
"weirdness": 0.0,
"offset": 0.0,
"temperature": 0.4,
"humidity": 0.0,
"continentalness": 0.0
},
"biome": "minecraft:crimson_forest"
},
{
"parameters": {
"erosion": 0.0,
"depth": 0.0,
"weirdness": 0.0,
"offset": 0.375,
"temperature": 0.0,
"humidity": 0.5,
"continentalness": 0.0
},
"biome": "minecraft:warped_forest"
}
],
"type": "minecraft:multi_noise"
},
"seed": 41,
"settings": "minecraft:nether",
"type": "minecraft:noise"
}
}