2025-11-24 22:52:51 +03:00

293 lines
22 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* com.google.gson.JsonElement
* com.mojang.logging.LogUtils
* com.mojang.serialization.Codec
* com.mojang.serialization.DataResult
* com.mojang.serialization.Decoder
* com.mojang.serialization.JsonOps
* com.mojang.serialization.Lifecycle
* org.slf4j.Logger
*/
package net.minecraft.resources;
import com.google.gson.JsonElement;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.Decoder;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.Lifecycle;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.RegistrationInfo;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.RegistrySynchronization;
import net.minecraft.core.WritableRegistry;
import net.minecraft.core.registries.Registries;
import net.minecraft.gametest.framework.GameTestInstance;
import net.minecraft.gametest.framework.TestEnvironmentDefinition;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.ChatType;
import net.minecraft.resources.FileToIdConverter;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.dialog.Dialog;
import net.minecraft.server.packs.repository.KnownPack;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceProvider;
import net.minecraft.tags.TagLoader;
import net.minecraft.tags.TagNetworkSerialization;
import net.minecraft.util.StrictJsonParser;
import net.minecraft.util.Util;
import net.minecraft.world.damagesource.DamageType;
import net.minecraft.world.entity.animal.CatVariant;
import net.minecraft.world.entity.animal.ChickenVariant;
import net.minecraft.world.entity.animal.CowVariant;
import net.minecraft.world.entity.animal.PigVariant;
import net.minecraft.world.entity.animal.ZombieNautilusVariant;
import net.minecraft.world.entity.animal.frog.FrogVariant;
import net.minecraft.world.entity.animal.wolf.WolfSoundVariant;
import net.minecraft.world.entity.animal.wolf.WolfVariant;
import net.minecraft.world.entity.decoration.PaintingVariant;
import net.minecraft.world.item.Instrument;
import net.minecraft.world.item.JukeboxSong;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.providers.EnchantmentProvider;
import net.minecraft.world.item.equipment.trim.TrimMaterial;
import net.minecraft.world.item.equipment.trim.TrimPattern;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.MultiNoiseBiomeSourceParameterList;
import net.minecraft.world.level.block.entity.BannerPattern;
import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerConfig;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
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.StructureProcessorList;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType;
import net.minecraft.world.level.levelgen.synth.NormalNoise;
import net.minecraft.world.timeline.Timeline;
import org.slf4j.Logger;
public class RegistryDataLoader {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Comparator<ResourceKey<?>> ERROR_KEY_COMPARATOR = Comparator.comparing(ResourceKey::registry).thenComparing(ResourceKey::identifier);
private static final RegistrationInfo NETWORK_REGISTRATION_INFO = new RegistrationInfo(Optional.empty(), Lifecycle.experimental());
private static final Function<Optional<KnownPack>, RegistrationInfo> REGISTRATION_INFO_CACHE = Util.memoize(knownPack -> {
Lifecycle lifecycle = knownPack.map(KnownPack::isVanilla).map(info -> Lifecycle.stable()).orElse(Lifecycle.experimental());
return new RegistrationInfo((Optional<KnownPack>)knownPack, lifecycle);
});
public static final List<RegistryData<?>> WORLDGEN_REGISTRIES = List.of(new RegistryData<DimensionType>(Registries.DIMENSION_TYPE, DimensionType.DIRECT_CODEC), new RegistryData<Biome>(Registries.BIOME, Biome.DIRECT_CODEC), new RegistryData<ChatType>(Registries.CHAT_TYPE, ChatType.DIRECT_CODEC), new RegistryData(Registries.CONFIGURED_CARVER, ConfiguredWorldCarver.DIRECT_CODEC), new RegistryData(Registries.CONFIGURED_FEATURE, ConfiguredFeature.DIRECT_CODEC), new RegistryData<PlacedFeature>(Registries.PLACED_FEATURE, PlacedFeature.DIRECT_CODEC), new RegistryData<Structure>(Registries.STRUCTURE, Structure.DIRECT_CODEC), new RegistryData<StructureSet>(Registries.STRUCTURE_SET, StructureSet.DIRECT_CODEC), new RegistryData<StructureProcessorList>(Registries.PROCESSOR_LIST, StructureProcessorType.DIRECT_CODEC), new RegistryData<StructureTemplatePool>(Registries.TEMPLATE_POOL, StructureTemplatePool.DIRECT_CODEC), new RegistryData<NoiseGeneratorSettings>(Registries.NOISE_SETTINGS, NoiseGeneratorSettings.DIRECT_CODEC), new RegistryData<NormalNoise.NoiseParameters>(Registries.NOISE, NormalNoise.NoiseParameters.DIRECT_CODEC), new RegistryData<DensityFunction>(Registries.DENSITY_FUNCTION, DensityFunction.DIRECT_CODEC), new RegistryData<WorldPreset>(Registries.WORLD_PRESET, WorldPreset.DIRECT_CODEC), new RegistryData<FlatLevelGeneratorPreset>(Registries.FLAT_LEVEL_GENERATOR_PRESET, FlatLevelGeneratorPreset.DIRECT_CODEC), new RegistryData<TrimPattern>(Registries.TRIM_PATTERN, TrimPattern.DIRECT_CODEC), new RegistryData<TrimMaterial>(Registries.TRIM_MATERIAL, TrimMaterial.DIRECT_CODEC), new RegistryData<TrialSpawnerConfig>(Registries.TRIAL_SPAWNER_CONFIG, TrialSpawnerConfig.DIRECT_CODEC), new RegistryData<WolfVariant>(Registries.WOLF_VARIANT, WolfVariant.DIRECT_CODEC, true), new RegistryData<WolfSoundVariant>(Registries.WOLF_SOUND_VARIANT, WolfSoundVariant.DIRECT_CODEC, true), new RegistryData<PigVariant>(Registries.PIG_VARIANT, PigVariant.DIRECT_CODEC, true), new RegistryData<FrogVariant>(Registries.FROG_VARIANT, FrogVariant.DIRECT_CODEC, true), new RegistryData<CatVariant>(Registries.CAT_VARIANT, CatVariant.DIRECT_CODEC, true), new RegistryData<CowVariant>(Registries.COW_VARIANT, CowVariant.DIRECT_CODEC, true), new RegistryData<ChickenVariant>(Registries.CHICKEN_VARIANT, ChickenVariant.DIRECT_CODEC, true), new RegistryData<ZombieNautilusVariant>(Registries.ZOMBIE_NAUTILUS_VARIANT, ZombieNautilusVariant.DIRECT_CODEC, true), new RegistryData<PaintingVariant>(Registries.PAINTING_VARIANT, PaintingVariant.DIRECT_CODEC, true), new RegistryData<DamageType>(Registries.DAMAGE_TYPE, DamageType.DIRECT_CODEC), new RegistryData<MultiNoiseBiomeSourceParameterList>(Registries.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST, MultiNoiseBiomeSourceParameterList.DIRECT_CODEC), new RegistryData<BannerPattern>(Registries.BANNER_PATTERN, BannerPattern.DIRECT_CODEC), new RegistryData<Enchantment>(Registries.ENCHANTMENT, Enchantment.DIRECT_CODEC), new RegistryData<EnchantmentProvider>(Registries.ENCHANTMENT_PROVIDER, EnchantmentProvider.DIRECT_CODEC), new RegistryData<JukeboxSong>(Registries.JUKEBOX_SONG, JukeboxSong.DIRECT_CODEC), new RegistryData<Instrument>(Registries.INSTRUMENT, Instrument.DIRECT_CODEC), new RegistryData<TestEnvironmentDefinition>(Registries.TEST_ENVIRONMENT, TestEnvironmentDefinition.DIRECT_CODEC), new RegistryData<GameTestInstance>(Registries.TEST_INSTANCE, GameTestInstance.DIRECT_CODEC), new RegistryData<Dialog>(Registries.DIALOG, Dialog.DIRECT_CODEC), new RegistryData<Timeline>(Registries.TIMELINE, Timeline.DIRECT_CODEC));
public static final List<RegistryData<?>> DIMENSION_REGISTRIES = List.of(new RegistryData<LevelStem>(Registries.LEVEL_STEM, LevelStem.CODEC));
public static final List<RegistryData<?>> SYNCHRONIZED_REGISTRIES = List.of(new RegistryData<Biome>(Registries.BIOME, Biome.NETWORK_CODEC), new RegistryData<ChatType>(Registries.CHAT_TYPE, ChatType.DIRECT_CODEC), new RegistryData<TrimPattern>(Registries.TRIM_PATTERN, TrimPattern.DIRECT_CODEC), new RegistryData<TrimMaterial>(Registries.TRIM_MATERIAL, TrimMaterial.DIRECT_CODEC), new RegistryData<WolfVariant>(Registries.WOLF_VARIANT, WolfVariant.NETWORK_CODEC, true), new RegistryData<WolfSoundVariant>(Registries.WOLF_SOUND_VARIANT, WolfSoundVariant.NETWORK_CODEC, true), new RegistryData<PigVariant>(Registries.PIG_VARIANT, PigVariant.NETWORK_CODEC, true), new RegistryData<FrogVariant>(Registries.FROG_VARIANT, FrogVariant.NETWORK_CODEC, true), new RegistryData<CatVariant>(Registries.CAT_VARIANT, CatVariant.NETWORK_CODEC, true), new RegistryData<CowVariant>(Registries.COW_VARIANT, CowVariant.NETWORK_CODEC, true), new RegistryData<ChickenVariant>(Registries.CHICKEN_VARIANT, ChickenVariant.NETWORK_CODEC, true), new RegistryData<ZombieNautilusVariant>(Registries.ZOMBIE_NAUTILUS_VARIANT, ZombieNautilusVariant.NETWORK_CODEC, true), new RegistryData<PaintingVariant>(Registries.PAINTING_VARIANT, PaintingVariant.DIRECT_CODEC, true), new RegistryData<DimensionType>(Registries.DIMENSION_TYPE, DimensionType.NETWORK_CODEC), new RegistryData<DamageType>(Registries.DAMAGE_TYPE, DamageType.DIRECT_CODEC), new RegistryData<BannerPattern>(Registries.BANNER_PATTERN, BannerPattern.DIRECT_CODEC), new RegistryData<Enchantment>(Registries.ENCHANTMENT, Enchantment.DIRECT_CODEC), new RegistryData<JukeboxSong>(Registries.JUKEBOX_SONG, JukeboxSong.DIRECT_CODEC), new RegistryData<Instrument>(Registries.INSTRUMENT, Instrument.DIRECT_CODEC), new RegistryData<TestEnvironmentDefinition>(Registries.TEST_ENVIRONMENT, TestEnvironmentDefinition.DIRECT_CODEC), new RegistryData<GameTestInstance>(Registries.TEST_INSTANCE, GameTestInstance.DIRECT_CODEC), new RegistryData<Dialog>(Registries.DIALOG, Dialog.DIRECT_CODEC), new RegistryData<Timeline>(Registries.TIMELINE, Timeline.NETWORK_CODEC));
public static RegistryAccess.Frozen load(ResourceManager resourceManager, List<HolderLookup.RegistryLookup<?>> contextRegistries, List<RegistryData<?>> registriesToLoad) {
return RegistryDataLoader.load((Loader<?> loader, RegistryOps.RegistryInfoLookup context) -> loader.loadFromResources(resourceManager, context), contextRegistries, registriesToLoad);
}
public static RegistryAccess.Frozen load(Map<ResourceKey<? extends Registry<?>>, NetworkedRegistryData> entries, ResourceProvider knownDataSource, List<HolderLookup.RegistryLookup<?>> contextRegistries, List<RegistryData<?>> registriesToLoad) {
return RegistryDataLoader.load((Loader<?> loader, RegistryOps.RegistryInfoLookup context) -> loader.loadFromNetwork(entries, knownDataSource, context), contextRegistries, registriesToLoad);
}
private static RegistryAccess.Frozen load(LoadingFunction loadingFunction, List<HolderLookup.RegistryLookup<?>> contextRegistries, List<RegistryData<?>> registriesToLoad) {
HashMap loadingErrors = new HashMap();
List<Loader<?>> newRegistriesAndLoaders = registriesToLoad.stream().map(r -> r.create(Lifecycle.stable(), loadingErrors)).collect(Collectors.toUnmodifiableList());
RegistryOps.RegistryInfoLookup contextAndNewRegistries = RegistryDataLoader.createContext(contextRegistries, newRegistriesAndLoaders);
newRegistriesAndLoaders.forEach(loader -> loadingFunction.apply((Loader<?>)loader, contextAndNewRegistries));
newRegistriesAndLoaders.forEach(p -> {
WritableRegistry registry = p.registry();
try {
registry.freeze();
}
catch (Exception e) {
loadingErrors.put(registry.key(), e);
}
if (p.data.requiredNonEmpty && registry.size() == 0) {
loadingErrors.put(registry.key(), new IllegalStateException("Registry must be non-empty: " + String.valueOf(registry.key().identifier())));
}
});
if (!loadingErrors.isEmpty()) {
throw RegistryDataLoader.logErrors(loadingErrors);
}
return new RegistryAccess.ImmutableRegistryAccess(newRegistriesAndLoaders.stream().map(Loader::registry).toList()).freeze();
}
private static RegistryOps.RegistryInfoLookup createContext(List<HolderLookup.RegistryLookup<?>> contextRegistries, List<Loader<?>> newRegistriesAndLoaders) {
final HashMap result = new HashMap();
contextRegistries.forEach(e -> result.put(e.key(), RegistryDataLoader.createInfoForContextRegistry(e)));
newRegistriesAndLoaders.forEach(e -> result.put(e.registry.key(), RegistryDataLoader.createInfoForNewRegistry(e.registry)));
return new RegistryOps.RegistryInfoLookup(){
@Override
public <T> Optional<RegistryOps.RegistryInfo<T>> lookup(ResourceKey<? extends Registry<? extends T>> key) {
return Optional.ofNullable((RegistryOps.RegistryInfo)result.get(key));
}
};
}
private static <T> RegistryOps.RegistryInfo<T> createInfoForNewRegistry(WritableRegistry<T> e) {
return new RegistryOps.RegistryInfo<T>(e, e.createRegistrationLookup(), e.registryLifecycle());
}
private static <T> RegistryOps.RegistryInfo<T> createInfoForContextRegistry(HolderLookup.RegistryLookup<T> lookup) {
return new RegistryOps.RegistryInfo<T>(lookup, lookup, lookup.registryLifecycle());
}
private static ReportedException logErrors(Map<ResourceKey<?>, Exception> loadingErrors) {
RegistryDataLoader.printFullDetailsToLog(loadingErrors);
return RegistryDataLoader.createReportWithBriefInfo(loadingErrors);
}
private static void printFullDetailsToLog(Map<ResourceKey<?>, Exception> loadingErrors) {
StringWriter collectedErrors = new StringWriter();
PrintWriter errorPrinter = new PrintWriter(collectedErrors);
Map<Identifier, Map<Identifier, Exception>> errorsByRegistry = loadingErrors.entrySet().stream().collect(Collectors.groupingBy(e -> ((ResourceKey)e.getKey()).registry(), Collectors.toMap(e -> ((ResourceKey)e.getKey()).identifier(), Map.Entry::getValue)));
errorsByRegistry.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(registryEntry -> {
errorPrinter.printf(Locale.ROOT, "> Errors in registry %s:%n", registryEntry.getKey());
((Map)registryEntry.getValue()).entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(elementError -> {
errorPrinter.printf(Locale.ROOT, ">> Errors in element %s:%n", elementError.getKey());
((Exception)elementError.getValue()).printStackTrace(errorPrinter);
});
});
errorPrinter.flush();
LOGGER.error("Registry loading errors:\n{}", (Object)collectedErrors);
}
private static ReportedException createReportWithBriefInfo(Map<ResourceKey<?>, Exception> loadingErrors) {
CrashReport report = CrashReport.forThrowable(new IllegalStateException("Failed to load registries due to errors"), "Registry Loading");
CrashReportCategory errors = report.addCategory("Loading info");
errors.setDetail("Errors", () -> {
StringBuilder briefDetails = new StringBuilder();
loadingErrors.entrySet().stream().sorted(Map.Entry.comparingByKey(ERROR_KEY_COMPARATOR)).forEach(e -> briefDetails.append("\n\t\t").append(((ResourceKey)e.getKey()).registry()).append("/").append(((ResourceKey)e.getKey()).identifier()).append(": ").append(((Exception)e.getValue()).getMessage()));
return briefDetails.toString();
});
return new ReportedException(report);
}
private static <E> void loadElementFromResource(WritableRegistry<E> output, Decoder<E> elementDecoder, RegistryOps<JsonElement> ops, ResourceKey<E> elementKey, Resource thunk, RegistrationInfo registrationInfo) throws IOException {
try (BufferedReader reader = thunk.openAsReader();){
JsonElement json = StrictJsonParser.parse(reader);
DataResult parseResult = elementDecoder.parse(ops, (Object)json);
Object parsedElement = parseResult.getOrThrow();
output.register(elementKey, parsedElement, registrationInfo);
}
}
private static <E> void loadContentsFromManager(ResourceManager resourceManager, RegistryOps.RegistryInfoLookup lookup, WritableRegistry<E> registry, Decoder<E> elementDecoder, Map<ResourceKey<?>, Exception> loadingErrors) {
FileToIdConverter lister = FileToIdConverter.registry(registry.key());
RegistryOps<JsonElement> ops = RegistryOps.create(JsonOps.INSTANCE, lookup);
for (Map.Entry<Identifier, Resource> resourceEntry : lister.listMatchingResources(resourceManager).entrySet()) {
Identifier resourceId = resourceEntry.getKey();
ResourceKey elementKey = ResourceKey.create(registry.key(), lister.fileToId(resourceId));
Resource thunk = resourceEntry.getValue();
RegistrationInfo registrationInfo = REGISTRATION_INFO_CACHE.apply(thunk.knownPackInfo());
try {
RegistryDataLoader.loadElementFromResource(registry, elementDecoder, ops, elementKey, thunk, registrationInfo);
}
catch (Exception e) {
loadingErrors.put(elementKey, new IllegalStateException(String.format(Locale.ROOT, "Failed to parse %s from pack %s", resourceId, thunk.sourcePackId()), e));
}
}
TagLoader.loadTagsForRegistry(resourceManager, registry);
}
private static <E> void loadContentsFromNetwork(Map<ResourceKey<? extends Registry<?>>, NetworkedRegistryData> entries, ResourceProvider knownDataSource, RegistryOps.RegistryInfoLookup lookup, WritableRegistry<E> registry, Decoder<E> elementDecoder, Map<ResourceKey<?>, Exception> loadingErrors) {
NetworkedRegistryData registryEntries = entries.get(registry.key());
if (registryEntries == null) {
return;
}
RegistryOps<Tag> nbtOps = RegistryOps.create(NbtOps.INSTANCE, lookup);
RegistryOps<JsonElement> jsonOps = RegistryOps.create(JsonOps.INSTANCE, lookup);
FileToIdConverter knownDataPathConverter = FileToIdConverter.registry(registry.key());
for (RegistrySynchronization.PackedRegistryEntry entry : registryEntries.elements) {
ResourceKey elementKey = ResourceKey.create(registry.key(), entry.id());
Optional<Tag> data = entry.data();
if (data.isPresent()) {
try {
DataResult parseResult = elementDecoder.parse(nbtOps, (Object)data.get());
Object parsedElement = parseResult.getOrThrow();
registry.register(elementKey, parsedElement, NETWORK_REGISTRATION_INFO);
}
catch (Exception e) {
loadingErrors.put(elementKey, new IllegalStateException(String.format(Locale.ROOT, "Failed to parse value %s from server", data.get()), e));
}
continue;
}
Identifier knownDataPath = knownDataPathConverter.idToFile(entry.id());
try {
Resource thunk = knownDataSource.getResourceOrThrow(knownDataPath);
RegistryDataLoader.loadElementFromResource(registry, elementDecoder, jsonOps, elementKey, thunk, NETWORK_REGISTRATION_INFO);
}
catch (Exception e) {
loadingErrors.put(elementKey, new IllegalStateException("Failed to parse local data", e));
}
}
TagLoader.loadTagsFromNetwork(registryEntries.tags, registry);
}
@FunctionalInterface
private static interface LoadingFunction {
public void apply(Loader<?> var1, RegistryOps.RegistryInfoLookup var2);
}
public record NetworkedRegistryData(List<RegistrySynchronization.PackedRegistryEntry> elements, TagNetworkSerialization.NetworkPayload tags) {
}
private record Loader<T>(RegistryData<T> data, WritableRegistry<T> registry, Map<ResourceKey<?>, Exception> loadingErrors) {
public void loadFromResources(ResourceManager resourceManager, RegistryOps.RegistryInfoLookup context) {
RegistryDataLoader.loadContentsFromManager(resourceManager, context, this.registry, this.data.elementCodec, this.loadingErrors);
}
public void loadFromNetwork(Map<ResourceKey<? extends Registry<?>>, NetworkedRegistryData> entries, ResourceProvider knownDataSource, RegistryOps.RegistryInfoLookup context) {
RegistryDataLoader.loadContentsFromNetwork(entries, knownDataSource, context, this.registry, this.data.elementCodec, this.loadingErrors);
}
}
public record RegistryData<T>(ResourceKey<? extends Registry<T>> key, Codec<T> elementCodec, boolean requiredNonEmpty) {
private RegistryData(ResourceKey<? extends Registry<T>> key, Codec<T> elementCodec) {
this(key, elementCodec, false);
}
private Loader<T> create(Lifecycle lifecycle, Map<ResourceKey<?>, Exception> loadingErrors) {
MappedRegistry result = new MappedRegistry(this.key, lifecycle);
return new Loader(this, result, loadingErrors);
}
public void runWithArguments(BiConsumer<ResourceKey<? extends Registry<T>>, Codec<T>> output) {
output.accept(this.key, this.elementCodec);
}
}
}