Merge branch '1.19' of github.com:quiqueck/BCLib into 1.19

This commit is contained in:
Frank 2022-06-03 15:38:35 +02:00
commit 51bd560fa0
11 changed files with 414 additions and 238 deletions

View file

@ -15,7 +15,6 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.PlacementModifier; import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import org.betterx.bclib.BCLib; import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.features.config.BlockPlaceFeatureConfig;
import org.betterx.bclib.api.features.config.ScatterFeatureConfig; import org.betterx.bclib.api.features.config.ScatterFeatureConfig;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -26,10 +25,6 @@ public class BCLFeature {
BCLib.makeID("scatter_on_solid"), BCLib.makeID("scatter_on_solid"),
new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC) new ScatterFeature<>(ScatterFeatureConfig.OnSolid.CODEC)
); );
public static final Feature<BlockPlaceFeatureConfig> PLACE_BLOCK = register(
BCLib.makeID("place_block"),
new BlockPlaceFeature<>(BlockPlaceFeatureConfig.CODEC)
);
private final Holder<PlacedFeature> placedFeature; private final Holder<PlacedFeature> placedFeature;
private final Decoration featureStep; private final Decoration featureStep;
private final Feature<?> feature; private final Feature<?> feature;

View file

@ -189,10 +189,26 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
return modifier(IsEmptyAboveSampledFilter.emptyAbove4()); return modifier(IsEmptyAboveSampledFilter.emptyAbove4());
} }
public BCLFeatureBuilder isEmptyAbove2() {
return modifier(IsEmptyAboveSampledFilter.emptyAbove2());
}
public BCLFeatureBuilder isEmptyAbove() { public BCLFeatureBuilder isEmptyAbove() {
return modifier(IsEmptyAboveSampledFilter.emptyAbove()); return modifier(IsEmptyAboveSampledFilter.emptyAbove());
} }
public BCLFeatureBuilder isEmptyBelow4() {
return modifier(IsEmptyAboveSampledFilter.emptyBelow4());
}
public BCLFeatureBuilder isEmptyBelow2() {
return modifier(IsEmptyAboveSampledFilter.emptyBelow2());
}
public BCLFeatureBuilder isEmptyBelow() {
return modifier(IsEmptyAboveSampledFilter.emptyBelow());
}
public BCLFeatureBuilder isEmptyAbove(int d1, int d2) { public BCLFeatureBuilder isEmptyAbove(int d1, int d2) {
return modifier(new IsEmptyAboveSampledFilter(d1, d2)); return modifier(new IsEmptyAboveSampledFilter(d1, d2));
} }
@ -275,6 +291,10 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
return modifier(new FindSolidInDirection(dir, distance)); return modifier(new FindSolidInDirection(dir, distance));
} }
public BCLFeatureBuilder findSolidSurface(List<Direction> dir, int distance) {
return modifier(new FindSolidInDirection(dir, distance));
}
public BCLFeatureBuilder heightmap() { public BCLFeatureBuilder heightmap() {
return modifier(PlacementUtils.HEIGHTMAP); return modifier(PlacementUtils.HEIGHTMAP);
} }

View file

@ -1,25 +0,0 @@
package org.betterx.bclib.api.features;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import com.mojang.serialization.Codec;
import org.betterx.bclib.api.features.config.BlockPlaceFeatureConfig;
import org.betterx.bclib.util.BlocksHelper;
import java.util.Optional;
public class BlockPlaceFeature<FC extends BlockPlaceFeatureConfig> extends Feature<FC> {
public BlockPlaceFeature(Codec<FC> codec) {
super(codec);
}
@Override
public boolean place(FeaturePlaceContext<FC> ctx) {
Optional<BlockState> state = ctx.config().getRandomBlock(ctx.random());
if (state.isPresent())
BlocksHelper.setWithoutUpdate(ctx.level(), ctx.origin(), state.get());
return true;
}
}

View file

@ -67,7 +67,7 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
.modifier(RandomOffsetPlacement.of( .modifier(RandomOffsetPlacement.of(
ClampedNormalInt.of(0.0f, 2.0f, -6, 6), ClampedNormalInt.of(0.0f, 2.0f, -6, 6),
ClampedNormalInt.of(0.0f, 0.6f, -2, 2))) ClampedNormalInt.of(0.0f, 0.6f, -2, 2)))
.modifier(BiomeFilter.biome()) .onlyInBiome()
.buildAndRegister(configuration); .buildAndRegister(configuration);
} }
@ -86,7 +86,8 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
if (direction.isEmpty()) { if (direction.isEmpty()) {
return false; 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); int i = (int) (random.nextFloat() * (1 + config.maxHeight - config.minHeight) + config.minHeight);
growCenterPillar(level, origin, basePos, direction.get(), i, config, random); growCenterPillar(level, origin, basePos, direction.get(), i, config, random);
@ -104,10 +105,8 @@ public class ScatterFeature<FC extends ScatterFeatureConfig>
if (config.isValidBase(level.getBlockState(basePos))) { if (config.isValidBase(level.getBlockState(basePos))) {
final Direction surfaceDirection = direction.getOpposite(); final Direction surfaceDirection = direction.getOpposite();
BlockPos.MutableBlockPos POS = new BlockPos.MutableBlockPos(); BlockPos.MutableBlockPos POS = new BlockPos.MutableBlockPos();
basePos = basePos.relative(direction, 1);
buildPillarWithBase(level, origin, basePos, direction, centerHeight, config, random); buildPillarWithBase(level, origin, basePos, direction, centerHeight, config, random);
final double distNormalizer = (config.maxSpread * Math.sqrt(2)); final double distNormalizer = (config.maxSpread * Math.sqrt(2));
final int tryCount = config.spreadCount.sample(random); final int tryCount = config.spreadCount.sample(random);
for (int i = 0; i < tryCount; i++) { for (int i = 0; i < tryCount; i++) {

View file

@ -1,59 +0,0 @@
package org.betterx.bclib.api.features.config;
import net.minecraft.util.RandomSource;
import net.minecraft.util.random.SimpleWeightedRandomList;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import java.util.List;
import java.util.Optional;
public class BlockPlaceFeatureConfig implements FeatureConfiguration {
public static final Codec<BlockPlaceFeatureConfig> CODEC = SimpleWeightedRandomList
.wrappedCodec(BlockState.CODEC)
.comapFlatMap(BlockPlaceFeatureConfig::create, cfg -> cfg.weightedList)
.fieldOf("entries").codec();
private final SimpleWeightedRandomList<BlockState> weightedList;
private static DataResult<BlockPlaceFeatureConfig> create(SimpleWeightedRandomList<BlockState> simpleWeightedRandomList) {
if (simpleWeightedRandomList.isEmpty()) {
return DataResult.error("BlockPlaceFeatureConfig with no states");
}
return DataResult.success(new BlockPlaceFeatureConfig(simpleWeightedRandomList));
}
private static SimpleWeightedRandomList<BlockState> convert(List<BlockState> states) {
var builder = SimpleWeightedRandomList.<BlockState>builder();
for (BlockState s : states) builder.add(s, 1);
return builder.build();
}
public BlockPlaceFeatureConfig(Block block) {
this(block.defaultBlockState());
}
public BlockPlaceFeatureConfig(BlockState state) {
this(SimpleWeightedRandomList
.<BlockState>builder()
.add(state, 1)
.build());
}
public BlockPlaceFeatureConfig(List<BlockState> states) {
this(convert(states));
}
public BlockPlaceFeatureConfig(SimpleWeightedRandomList<BlockState> blocks) {
this.weightedList = blocks;
}
public Optional<BlockState> getRandomBlock(RandomSource random) {
return this.weightedList.getRandomValue(random);
}
}

View file

@ -17,7 +17,7 @@ import org.betterx.bclib.util.BlocksHelper;
import java.util.Optional; import java.util.Optional;
public abstract class ScatterFeatureConfig implements FeatureConfiguration { public abstract class ScatterFeatureConfig implements FeatureConfiguration {
public interface Instancer<T extends ScatterFeatureConfig> extends Function15<BlockState, BlockState, BlockState, Optional<BlockState>, Float, Float, Float, Float, Integer, Integer, Float, Float, Float, Boolean, IntProvider, T> { public interface Instancer<T extends ScatterFeatureConfig> extends Function15<BlockState, Optional<BlockState>, Optional<BlockState>, Optional<BlockState>, Float, Float, Float, Float, Integer, Integer, Float, Float, Float, Boolean, IntProvider, T> {
} }
public final BlockState clusterBlock; public final BlockState clusterBlock;
@ -39,8 +39,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration {
public final boolean growWhileFree; public final boolean growWhileFree;
public ScatterFeatureConfig(BlockState clusterBlock, public ScatterFeatureConfig(BlockState clusterBlock,
BlockState tipBlock, Optional<BlockState> tipBlock,
BlockState bottomBlock, Optional<BlockState> bottomBlock,
Optional<BlockState> baseState, Optional<BlockState> baseState,
float baseReplaceChance, float baseReplaceChance,
float chanceOfDirectionalSpread, float chanceOfDirectionalSpread,
@ -54,8 +54,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration {
boolean growWhileFree, boolean growWhileFree,
IntProvider spreadCount) { IntProvider spreadCount) {
this.clusterBlock = clusterBlock; this.clusterBlock = clusterBlock;
this.tipBlock = tipBlock == null ? clusterBlock : tipBlock; this.tipBlock = tipBlock.orElse(clusterBlock);
this.bottomBlock = bottomBlock == null ? clusterBlock : bottomBlock; this.bottomBlock = bottomBlock.orElse(clusterBlock);
this.baseState = baseState; this.baseState = baseState;
this.baseReplaceChance = baseReplaceChance; this.baseReplaceChance = baseReplaceChance;
this.chanceOfDirectionalSpread = chanceOfDirectionalSpread; this.chanceOfDirectionalSpread = chanceOfDirectionalSpread;
@ -85,13 +85,17 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration {
.fieldOf("cluster_block") .fieldOf("cluster_block")
.forGetter((T cfg) -> cfg.clusterBlock), .forGetter((T cfg) -> cfg.clusterBlock),
BlockState.CODEC BlockState.CODEC
.fieldOf("tip_block") .optionalFieldOf("tip_block")
.orElse(null) .orElse(Optional.empty())
.forGetter((T cfg) -> cfg.tipBlock), .forGetter((T cfg) -> cfg.tipBlock == cfg.clusterBlock
? Optional.empty()
: Optional.of(cfg.tipBlock)),
BlockState.CODEC BlockState.CODEC
.fieldOf("bottom_block") .optionalFieldOf("bottom_block")
.orElse(null) .orElse(Optional.empty())
.forGetter((T cfg) -> cfg.bottomBlock), .forGetter((T cfg) -> cfg.bottomBlock == cfg.clusterBlock
? Optional.empty()
: Optional.of(cfg.bottomBlock)),
BlockState.CODEC BlockState.CODEC
.optionalFieldOf("base_state") .optionalFieldOf("base_state")
.forGetter((T cfg) -> cfg.baseState), .forGetter((T cfg) -> cfg.baseState),
@ -291,8 +295,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration {
public T build() { public T build() {
return instancer.apply( return instancer.apply(
this.clusterBlock, this.clusterBlock,
this.tipBlock, Optional.of(this.tipBlock),
this.bottomBlock, Optional.of(this.bottomBlock),
this.baseState, this.baseState,
this.baseReplaceChance, this.baseReplaceChance,
this.chanceOfDirectionalSpread, this.chanceOfDirectionalSpread,
@ -313,8 +317,8 @@ public abstract class ScatterFeatureConfig implements FeatureConfiguration {
public static final Codec<OnSolid> CODEC = buildCodec(OnSolid::new); public static final Codec<OnSolid> CODEC = buildCodec(OnSolid::new);
public OnSolid(BlockState clusterBlock, public OnSolid(BlockState clusterBlock,
BlockState tipBlock, Optional<BlockState> tipBlock,
BlockState bottomBlock, Optional<BlockState> bottomBlock,
Optional<BlockState> baseState, Optional<BlockState> baseState,
float baseReplaceChance, float baseReplaceChance,
float chanceOfDirectionalSpread, float chanceOfDirectionalSpread,

View file

@ -2,6 +2,7 @@ package org.betterx.bclib.api.features.placement;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.placement.PlacementContext; import net.minecraft.world.level.levelgen.placement.PlacementContext;
import net.minecraft.world.level.levelgen.placement.PlacementModifier; import net.minecraft.world.level.levelgen.placement.PlacementModifier;
@ -12,20 +13,30 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
import org.betterx.bclib.api.tag.CommonBlockTags; import org.betterx.bclib.api.tag.CommonBlockTags;
import org.betterx.bclib.util.BlocksHelper; import org.betterx.bclib.util.BlocksHelper;
import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
public class FindSolidInDirection extends PlacementModifier { public class FindSolidInDirection extends PlacementModifier {
public static final Codec<FindSolidInDirection> 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 DOWN = new FindSolidInDirection(Direction.DOWN, 6);
protected static final FindSolidInDirection UP = new FindSolidInDirection(Direction.UP, 6); protected static final FindSolidInDirection UP = new FindSolidInDirection(Direction.UP, 6);
public static final Codec<FindSolidInDirection> CODEC = RecordCodecBuilder.create((instance) -> instance private final List<Direction> direction;
.group( private final int maxSearchDistance;
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));
public FindSolidInDirection(Direction direction, int maxSearchDistance) { public FindSolidInDirection(Direction direction, int maxSearchDistance) {
this(List.of(direction), maxSearchDistance);
}
public FindSolidInDirection(List<Direction> direction, int maxSearchDistance) {
this.direction = direction; this.direction = direction;
this.maxSearchDistance = maxSearchDistance; this.maxSearchDistance = maxSearchDistance;
} }
@ -48,25 +59,26 @@ public class FindSolidInDirection extends PlacementModifier {
return new FindSolidInDirection(Direction.UP, dist); 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 @Override
public Stream<BlockPos> getPositions(PlacementContext placementContext, public Stream<BlockPos> getPositions(PlacementContext placementContext,
RandomSource randomSource, RandomSource randomSource,
BlockPos blockPos) { BlockPos blockPos) {
BlockPos.MutableBlockPos POS = blockPos.mutable(); BlockPos.MutableBlockPos POS = blockPos.mutable();
if (BlocksHelper.findSurroundingSurface(placementContext.getLevel(), Direction d = randomDirection(randomSource);
if (BlocksHelper.findOnSurroundingSurface(placementContext.getLevel(),
POS, POS,
direction, d,
maxSearchDistance, maxSearchDistance,
state -> state.is(CommonBlockTags.TERRAIN)) state -> state.is(CommonBlockTags.TERRAIN)))
) return Stream.of(POS); return Stream.of(POS);
return Stream.of(); return Stream.of();
} }
private final Direction direction;
private final int maxSearchDistance;
@Override @Override
public PlacementModifierType<?> type() { public PlacementModifierType<?> type() {
return PlacementModifiers.SOLID_IN_DIR; return PlacementModifiers.SOLID_IN_DIR;

View file

@ -16,10 +16,15 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
public class IsEmptyAboveSampledFilter extends PlacementFilter { public class IsEmptyAboveSampledFilter extends PlacementFilter {
private static final IsEmptyAboveSampledFilter DEFAULT = new IsEmptyAboveSampledFilter(4, 2); private static final IsEmptyAboveSampledFilter DEFAULT = new IsEmptyAboveSampledFilter(4, 2);
private static final IsEmptyAboveSampledFilter DEFAULT1 = new IsEmptyAboveSampledFilter(1, 1); 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<IsEmptyAboveSampledFilter> CODEC = RecordCodecBuilder.create((instance) -> instance public static final Codec<IsEmptyAboveSampledFilter> CODEC = RecordCodecBuilder.create((instance) -> instance
.group( .group(
Codec.intRange(1, 32).fieldOf("d1").orElse(2).forGetter((p) -> p.distance1), Codec.intRange(-32, 32).fieldOf("d1").orElse(4).forGetter((p) -> p.distance1),
Codec.intRange(1, 32).fieldOf("d2").orElse(4).forGetter((p) -> p.distance1) Codec.intRange(-32, 32).fieldOf("d2").orElse(2).forGetter((p) -> p.distance1)
) )
.apply(instance, IsEmptyAboveSampledFilter::new)); .apply(instance, IsEmptyAboveSampledFilter::new));
@ -27,10 +32,26 @@ public class IsEmptyAboveSampledFilter extends PlacementFilter {
return DEFAULT; return DEFAULT;
} }
public static PlacementFilter emptyAbove2() {
return DEFAULT2;
}
public static PlacementFilter emptyAbove() { public static PlacementFilter emptyAbove() {
return DEFAULT1; 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) { public IsEmptyAboveSampledFilter(int d1, int d2) {
this.distance1 = d1; this.distance1 = d1;
this.distance2 = d2; this.distance2 = d2;

View file

@ -2,18 +2,44 @@ package org.betterx.bclib.client;
import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.UnbakedModel; 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.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.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.model.*; 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.ModIntegrationAPI;
import org.betterx.bclib.api.PostInitAPI; import org.betterx.bclib.api.PostInitAPI;
import org.betterx.bclib.api.dataexchange.DataExchangeAPI; 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.models.CustomModelBakery;
import org.betterx.bclib.client.presets.WorldPresetsUI; import org.betterx.bclib.client.presets.WorldPresetsUI;
import org.betterx.bclib.registry.BaseBlockEntityRenders; 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; import org.jetbrains.annotations.Nullable;
public class BCLibClient implements ClientModInitializer, ModelResourceProvider, ModelVariantProvider { public class BCLibClient implements ClientModInitializer, ModelResourceProvider, ModelVariantProvider {
@ -30,6 +56,7 @@ public class BCLibClient implements ClientModInitializer, ModelResourceProvider,
ModelLoadingRegistry.INSTANCE.registerVariantProvider(rm -> this); ModelLoadingRegistry.INSTANCE.registerVariantProvider(rm -> this);
WorldPresetsUI.setupClientside(); WorldPresetsUI.setupClientside();
//dumpDatapack();
} }
@Override @Override
@ -45,4 +72,160 @@ public class BCLibClient implements ClientModInitializer, ModelResourceProvider,
? modelBakery.getItemModel(modelId) ? modelBakery.getItemModel(modelId)
: modelBakery.getBlockModel(modelId); : 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

@ -14,4 +14,5 @@ public class BCLibServer implements DedicatedServerModInitializer {
PostInitAPI.postInit(false); PostInitAPI.postInit(false);
} }
} }

View file

@ -221,6 +221,31 @@ public class BlocksHelper {
return false; return false;
} }
public static boolean findOnSurroundingSurface(LevelAccessor level,
MutableBlockPos startPos,
Direction dir,
int length,
Predicate<BlockState> 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, public static boolean findSurroundingSurface(LevelAccessor level,
MutableBlockPos startPos, MutableBlockPos startPos,
Direction dir, Direction dir,