/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.gson.JsonElement * com.mojang.logging.LogUtils * com.mojang.serialization.DynamicOps * com.mojang.serialization.JsonOps * com.mojang.serialization.Lifecycle * org.slf4j.Logger */ package net.minecraft.server; import com.google.gson.JsonElement; import com.mojang.logging.LogUtils; import com.mojang.serialization.DynamicOps; import com.mojang.serialization.JsonOps; import com.mojang.serialization.Lifecycle; import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.stream.Stream; import net.minecraft.core.HolderGetter; import net.minecraft.core.HolderLookup; import net.minecraft.core.LayeredRegistryAccess; import net.minecraft.core.MappedRegistry; import net.minecraft.core.RegistrationInfo; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.core.WritableRegistry; import net.minecraft.core.registries.Registries; import net.minecraft.resources.Identifier; import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; import net.minecraft.server.RegistryLayer; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; import net.minecraft.tags.TagLoader; import net.minecraft.util.ProblemReporter; import net.minecraft.util.Util; import net.minecraft.world.level.storage.loot.LootDataType; import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.ValidationContext; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import org.slf4j.Logger; public class ReloadableServerRegistries { private static final Logger LOGGER = LogUtils.getLogger(); private static final RegistrationInfo DEFAULT_REGISTRATION_INFO = new RegistrationInfo(Optional.empty(), Lifecycle.experimental()); public static CompletableFuture reload(LayeredRegistryAccess context, List> updatedContextTags, ResourceManager manager, Executor executor) { List> contextRegistriesWithTags = TagLoader.buildUpdatedLookups(context.getAccessForLoading(RegistryLayer.RELOADABLE), updatedContextTags); HolderLookup.Provider loadingContextWithTags = HolderLookup.Provider.create(contextRegistriesWithTags.stream()); RegistryOps ops = loadingContextWithTags.createSerializationContext(JsonOps.INSTANCE); List registryLoads = LootDataType.values().map(type -> ReloadableServerRegistries.scheduleRegistryLoad(type, ops, manager, executor)).toList(); CompletableFuture sequence = Util.sequence(registryLoads); return sequence.thenApplyAsync(newlyLoadedRegistries -> ReloadableServerRegistries.createAndValidateFullContext(context, loadingContextWithTags, newlyLoadedRegistries), executor); } private static CompletableFuture> scheduleRegistryLoad(LootDataType type, RegistryOps ops, ResourceManager manager, Executor taskExecutor) { return CompletableFuture.supplyAsync(() -> { MappedRegistry registry = new MappedRegistry(type.registryKey(), Lifecycle.experimental()); HashMap elements = new HashMap(); SimpleJsonResourceReloadListener.scanDirectory(manager, type.registryKey(), (DynamicOps)ops, type.codec(), elements); elements.forEach((id, element) -> registry.register(ResourceKey.create(type.registryKey(), id), element, DEFAULT_REGISTRATION_INFO)); TagLoader.loadTagsForRegistry(manager, registry); return registry; }, taskExecutor); } private static LoadResult createAndValidateFullContext(LayeredRegistryAccess contextLayers, HolderLookup.Provider contextLookupWithUpdatedTags, List> newRegistries) { LayeredRegistryAccess fullLayers = ReloadableServerRegistries.createUpdatedRegistries(contextLayers, newRegistries); HolderLookup.Provider fullLookupWithUpdatedTags = ReloadableServerRegistries.concatenateLookups(contextLookupWithUpdatedTags, fullLayers.getLayer(RegistryLayer.RELOADABLE)); ReloadableServerRegistries.validateLootRegistries(fullLookupWithUpdatedTags); return new LoadResult(fullLayers, fullLookupWithUpdatedTags); } private static HolderLookup.Provider concatenateLookups(HolderLookup.Provider first, HolderLookup.Provider second) { return HolderLookup.Provider.create(Stream.concat(first.listRegistries(), second.listRegistries())); } private static void validateLootRegistries(HolderLookup.Provider fullContextWithNewTags) { ProblemReporter.Collector problems = new ProblemReporter.Collector(); ValidationContext validationContext = new ValidationContext(problems, LootContextParamSets.ALL_PARAMS, fullContextWithNewTags); LootDataType.values().forEach(lootDataType -> ReloadableServerRegistries.validateRegistry(validationContext, lootDataType, fullContextWithNewTags)); problems.forEach((id, problem) -> LOGGER.warn("Found loot table element validation problem in {}: {}", id, (Object)problem.description())); } private static LayeredRegistryAccess createUpdatedRegistries(LayeredRegistryAccess context, List> registries) { return context.replaceFrom(RegistryLayer.RELOADABLE, new RegistryAccess.ImmutableRegistryAccess(registries).freeze()); } private static void validateRegistry(ValidationContext validationContext, LootDataType type, HolderLookup.Provider registries) { HolderGetter registry = registries.lookupOrThrow(type.registryKey()); registry.listElements().forEach(element -> type.runValidation(validationContext, element.key(), element.value())); } public record LoadResult(LayeredRegistryAccess layers, HolderLookup.Provider lookupWithUpdatedTags) { } public static class Holder { private final HolderLookup.Provider registries; public Holder(HolderLookup.Provider registries) { this.registries = registries; } public HolderLookup.Provider lookup() { return this.registries; } public LootTable getLootTable(ResourceKey id) { return this.registries.lookup(Registries.LOOT_TABLE).flatMap(r -> r.get(id)).map(net.minecraft.core.Holder::value).orElse(LootTable.EMPTY); } } }