From 29cf285f0935666c90a6866da3ca67830fa6a064 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 26 Jul 2022 13:25:21 +0200 Subject: [PATCH] [Change] `/bclib dump_datapack` without reflection (quiqueck/BetterNether#41) --- .../betterx/bclib/commands/DumpDatapack.java | 293 +++++++++++++++--- 1 file changed, 250 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/betterx/bclib/commands/DumpDatapack.java b/src/main/java/org/betterx/bclib/commands/DumpDatapack.java index 7b6f4f06..5a5eff21 100644 --- a/src/main/java/org/betterx/bclib/commands/DumpDatapack.java +++ b/src/main/java/org/betterx/bclib/commands/DumpDatapack.java @@ -2,8 +2,11 @@ package org.betterx.bclib.commands; import org.betterx.bclib.BCLib; import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome; +import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry; import org.betterx.bclib.api.v2.levelgen.biomes.BiomeData; import org.betterx.bclib.blocks.BaseStairsBlock; +import org.betterx.worlds.together.surfaceRules.AssignedSurfaceRule; +import org.betterx.worlds.together.surfaceRules.SurfaceRuleRegistry; import com.mojang.brigadier.Command; import com.mojang.brigadier.context.CommandContext; @@ -12,23 +15,39 @@ import com.mojang.serialization.JsonOps; import com.mojang.serialization.codecs.KeyDispatchCodec; import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.Holder; +import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Style; import net.minecraft.resources.RegistryOps; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; import net.minecraft.tags.TagEntry; import net.minecraft.tags.TagFile; import net.minecraft.util.KeyDispatchDataCodec; import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeSource; +import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.world.level.levelgen.DensityFunction; +import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.WorldGenSettings; +import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorPreset; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import net.minecraft.world.level.levelgen.presets.WorldPreset; import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.levelgen.structure.StructureSet; +import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool; import net.minecraft.world.level.levelgen.structure.templatesystem.PosRuleTestType; import net.minecraft.world.level.levelgen.structure.templatesystem.RuleTestType; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; +import net.minecraft.world.level.levelgen.synth.NormalNoise; import net.minecraft.world.level.material.Fluid; import com.google.gson.Gson; @@ -44,11 +63,26 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; public class DumpDatapack { + private record Dumper, H extends Holder>( + Function codecFunction, + Function, T> contentTransform + ) { + Dumper(Function codecFunction) { + this(codecFunction, h -> h.value()); + } + } + + private static final Map DUMPERS = new HashMap<>(); + static int dumpDatapack(CommandContext ctx) { File base = new File(System.getProperty("user.dir"), "bclib_datapack_dump"); - dumpDatapack(base, ctx.getSource().getLevel().registryAccess()); + dumpDatapack(base, ctx.getSource().getLevel().registryAccess(), ctx); + ctx.getSource().sendSuccess( Component.literal("Succesfully written to:\n ").append( @@ -59,53 +93,185 @@ public class DumpDatapack { return Command.SINGLE_SUCCESS; } - public static void dumpDatapack(File base, RegistryAccess registryAccess) { + public static void dumpDatapack(File base, RegistryAccess registryAccess, CommandContext ctx) { final RegistryOps registryOps = RegistryOps.create(JsonOps.INSTANCE, registryAccess); GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder = gsonBuilder.setPrettyPrinting(); Gson gson = gsonBuilder.create(); - registryAccess.registries().forEach(r -> dumpDatapack(base, r, registryOps, gson)); + + registryAccess.registries().forEach(r -> dump(base, r, registryOps, gson)); + + BCLib.LOGGER.info("- Serializing Dimensions "); + + for (ServerLevel serverLevel : ctx.getSource().getLevel().getServer().getAllLevels()) { + File f1 = new File(base, serverLevel.dimension().location().getNamespace()); + f1 = new File(f1, "dimension"); + f1 = new File(f1, serverLevel.dimension().location().getPath() + ".json"); + f1.getParentFile().mkdirs(); + + try { + LevelStem stem = new LevelStem( + serverLevel.dimensionTypeRegistration(), + serverLevel.getChunkSource().getGenerator() + ); + Codec codec = LevelStem.CODEC; + var o = codec + .encodeStart(registryOps, stem) + .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()); + } + } + } - private static void dumpDatapack( + + private static void dump( + File base, RegistryAccess.RegistryEntry registry, + RegistryOps registryOps, + Gson gson + ) { + BCLib.LOGGER.info("- Serializing: " + registry.key().toString()); + DUMPERS.clear(); + DUMPERS.put(Registry.BIOME_REGISTRY.location(), new Dumper<>((Biome v) -> Biome.DIRECT_CODEC)); + DUMPERS.put( + Registry.CONFIGURED_FEATURE_REGISTRY.location(), + new Dumper<>((ConfiguredFeature v) -> ConfiguredFeature.DIRECT_CODEC) + ); + DUMPERS.put( + Registry.WORLD_PRESET_REGISTRY.location(), + new Dumper<>((WorldPreset v) -> WorldPreset.DIRECT_CODEC) + ); + DUMPERS.put( + Registry.NOISE_GENERATOR_SETTINGS_REGISTRY.location(), + new Dumper<>((NoiseGeneratorSettings v) -> NoiseGeneratorSettings.DIRECT_CODEC) + ); + DUMPERS.put(Registry.STRUCTURE_REGISTRY.location(), new Dumper<>((Structure v) -> Structure.DIRECT_CODEC)); + DUMPERS.put( + Registry.DIMENSION_TYPE_REGISTRY.location(), + new Dumper<>((DimensionType v) -> DimensionType.DIRECT_CODEC) + ); + DUMPERS.put(BCLBiomeRegistry.BCL_BIOMES_REGISTRY.location(), new Dumper<>((BCLBiome v) -> v.codec().codec())); + DUMPERS.put( + SurfaceRuleRegistry.SURFACE_RULES_REGISTRY.location(), + new Dumper<>((AssignedSurfaceRule v) -> AssignedSurfaceRule.CODEC) + ); + DUMPERS.put(Registry.SOUND_EVENT_REGISTRY.location(), new Dumper<>((SoundEvent v) -> SoundEvent.CODEC)); + DUMPERS.put( + Registry.CONFIGURED_CARVER_REGISTRY.location(), + new Dumper<>((ConfiguredWorldCarver v) -> ConfiguredWorldCarver.DIRECT_CODEC) + ); + DUMPERS.put( + Registry.PROCESSOR_LIST_REGISTRY.location(), + new Dumper<>((StructureProcessorList v) -> StructureProcessorType.DIRECT_CODEC) + ); + DUMPERS.put( + Registry.FLAT_LEVEL_GENERATOR_PRESET_REGISTRY.location(), + new Dumper<>((FlatLevelGeneratorPreset v) -> FlatLevelGeneratorPreset.DIRECT_CODEC) + ); + DUMPERS.put( + Registry.DENSITY_FUNCTION_REGISTRY.location(), + new Dumper<>((DensityFunction v) -> DensityFunction.DIRECT_CODEC) + ); + DUMPERS.put( + Registry.PLACED_FEATURE_REGISTRY.location(), + new Dumper<>((PlacedFeature v) -> PlacedFeature.DIRECT_CODEC) + ); + DUMPERS.put( + Registry.NOISE_REGISTRY.location(), + new Dumper<>((NormalNoise.NoiseParameters v) -> NormalNoise.NoiseParameters.DIRECT_CODEC) + ); + DUMPERS.put( + Registry.NOISE_REGISTRY.location(), + new Dumper<>((NormalNoise.NoiseParameters v) -> NormalNoise.NoiseParameters.DIRECT_CODEC) + ); + + + DUMPERS.put( + Registry.TEMPLATE_POOL_REGISTRY.location(), + new Dumper<>((StructureTemplatePool v) -> StructureTemplatePool.DIRECT_CODEC) + ); + DUMPERS.put( + Registry.STRUCTURE_SET_REGISTRY.location(), + new Dumper<>((StructureSet v) -> StructureSet.DIRECT_CODEC) + ); + + + Dumper d = DUMPERS.getOrDefault(registry.key().location(), new Dumper(v -> registry.value().byNameCodec())); + //Dumper d = DUMPERS.get(registry.key().location()); + if (d != null) + dump(base, registry, registryOps, gson, d.codecFunction, d.contentTransform); + else + BCLib.LOGGER.warning(" No Codec Found"); + + } + + private static void dump( + File base, RegistryAccess.RegistryEntry registry, + RegistryOps registryOps, + Gson gson, + Function> codecFunction, + Function, Object> contentTransform + ) { + BCLib.LOGGER.info(" - Serializing Tags"); + dumpTags(base, registry, registryOps, gson); + + BCLib.LOGGER.info(" - Serializing Content"); + int[] count = {0, 0}; + 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"); + f1.getParentFile().mkdirs(); + //BCLib.LOGGER.info(" - " + f1); + + Object obj = contentTransform.apply(holder); + try { + Codec codec = codecFunction.apply(obj); + var o = codec + .encodeStart(registryOps, obj) + .result() + .orElse(new JsonObject()); + + String content = gson.toJson(o); + try { + Files.writeString(f1.toPath(), content, StandardCharsets.UTF_8); + count[0]++; + } catch (IOException e) { + count[1]++; + BCLib.LOGGER.error(" ->> Unable to WRITE: " + e.getMessage()); + } + } catch (Exception e) { + count[1]++; + BCLib.LOGGER.error(" ->> Unable to encode: " + e.getMessage()); + } + }); + BCLib.LOGGER.info(" -> Wrote " + count[0] + " files (" + count[1] + " errors)"); + } + + + private static void dumpDatapackOld( File base, RegistryAccess.RegistryEntry registry, RegistryOps registryOps, Gson gson ) { BCLib.LOGGER.info(registry.key().toString()); - // Tag Output - registry.value() - .getTagNames() - .map(tagKey -> registry.value().getTag(tagKey)) - .filter(tag -> tag.isPresent()) - .map(tag -> tag.get()) - .forEach(tag -> { - File f1 = new File(base, tag.key().location().getNamespace()); - f1 = new File(f1, "tags"); - f1 = new File(f1, registry.key().location().getPath()); - f1.mkdirs(); - f1 = new File(f1, tag.key().location().getPath() + ".json"); - - TagFile tf = new TagFile( - tag.stream() - .map(holder -> holder.unwrapKey()) - .filter(k -> k.isPresent()) - .map(k -> TagEntry.element(k.get().location())) - .toList(), - true - ); - var o = TagFile.CODEC - .encodeStart(registryOps, tf) - .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()); - } - }); + dumpTags(base, registry, registryOps, gson); registry .value() @@ -121,7 +287,7 @@ public class DumpDatapack { Codec[] codec = {null}; - BCLib.LOGGER.info(" - " + f1); + //BCLib.LOGGER.info(" - " + f1); Object obj = holder; while (obj instanceof Holder) { @@ -131,6 +297,7 @@ public class DumpDatapack { if (obj instanceof BiomeSource || obj instanceof Feature) { System.out.print(""); } + System.out.println(obj.getClass()); if (obj instanceof Structure s) { codec[0] = s.type().codec(); @@ -164,7 +331,7 @@ public class DumpDatapack { if (Codec.class.isAssignableFrom(m.getReturnType())) { try { codec[0] = (Codec) m.invoke(obj); - BCLib.LOGGER.info(" Got Codec from " + m); + BCLib.LOGGER.debug(" Got Codec from " + m); break; } catch (Exception e) { BCLib.LOGGER.error(" !!! Unable to get Codec from " + m); @@ -172,7 +339,7 @@ public class DumpDatapack { } else if (KeyDispatchCodec.class.isAssignableFrom(m.getReturnType())) { try { codec[0] = ((KeyDispatchCodec) m.invoke(obj)).codec(); - BCLib.LOGGER.info(" Got Codec from " + m); + BCLib.LOGGER.debug(" Got Codec from " + m); break; } catch (Exception e) { BCLib.LOGGER.error(" !!! Unable to get Codec from " + m); @@ -180,7 +347,7 @@ public class DumpDatapack { } else if (KeyDispatchDataCodec.class.isAssignableFrom(m.getReturnType())) { try { codec[0] = ((KeyDispatchDataCodec) m.invoke(obj)).codec(); - BCLib.LOGGER.info(" Got Codec from " + m); + BCLib.LOGGER.debug(" Got Codec from " + m); break; } catch (Exception e) { BCLib.LOGGER.error(" !!! Unable to get Codec from " + m); @@ -199,7 +366,7 @@ public class DumpDatapack { f.setAccessible(true); try { codec[0] = (Codec) f.get(null); - BCLib.LOGGER.info(" Got Codec from " + f); + BCLib.LOGGER.debug(" Got Codec from " + f); } catch (Exception e) { BCLib.LOGGER.error(" !!! Unable to get Codec from " + f); } @@ -216,7 +383,7 @@ public class DumpDatapack { try { f.setAccessible(true); codec[0] = (Codec) f.get(null); - BCLib.LOGGER.info(" Got Codec from " + f); + BCLib.LOGGER.debug(" Got Codec from " + f); } catch (Exception e) { BCLib.LOGGER.error(" !!! Unable to get Codec from " + f); } @@ -233,7 +400,7 @@ public class DumpDatapack { f.setAccessible(true); try { codec[0] = (Codec) f.get(null); - BCLib.LOGGER.info(" Got Codec from " + f); + BCLib.LOGGER.debug(" Got Codec from " + f); } catch (Exception e) { BCLib.LOGGER.error(" !!! Unable to get Codec from " + f); } @@ -273,4 +440,44 @@ public class DumpDatapack { }); } + + private static void dumpTags( + File base, + RegistryAccess.RegistryEntry registry, + RegistryOps registryOps, + Gson gson + ) { + // Tag Output + registry.value() + .getTagNames() + .map(tagKey -> registry.value().getTag(tagKey)) + .filter(tag -> tag.isPresent()) + .map(tag -> tag.get()) + .forEach(tag -> { + File f1 = new File(base, tag.key().location().getNamespace()); + f1 = new File(f1, "tags"); + f1 = new File(f1, registry.key().location().getPath()); + f1 = new File(f1, tag.key().location().getPath() + ".json"); + f1.getParentFile().mkdirs(); + + TagFile tf = new TagFile( + tag.stream() + .map(holder -> holder.unwrapKey()) + .filter(k -> k.isPresent()) + .map(k -> TagEntry.element(k.get().location())) + .toList(), + true + ); + var o = TagFile.CODEC + .encodeStart(registryOps, tf) + .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()); + } + }); + } }