minecraft-src/net/minecraft/client/multiplayer/RegistryDataCollector.java
2025-07-04 02:49:36 +03:00

174 lines
7.2 KiB
Java

package net.minecraft.client.multiplayer;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.CrashReportDetail;
import net.minecraft.ReportedException;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.LayeredRegistryAccess;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.RegistrySynchronization;
import net.minecraft.resources.RegistryDataLoader;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.packs.resources.ResourceProvider;
import net.minecraft.tags.TagLoader;
import net.minecraft.tags.TagNetworkSerialization;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public class RegistryDataCollector {
@Nullable
private RegistryDataCollector.ContentsCollector contentsCollector;
@Nullable
private RegistryDataCollector.TagCollector tagCollector;
public void appendContents(ResourceKey<? extends Registry<?>> registryKey, List<RegistrySynchronization.PackedRegistryEntry> registryEntries) {
if (this.contentsCollector == null) {
this.contentsCollector = new RegistryDataCollector.ContentsCollector();
}
this.contentsCollector.append(registryKey, registryEntries);
}
public void appendTags(Map<ResourceKey<? extends Registry<?>>, TagNetworkSerialization.NetworkPayload> tags) {
if (this.tagCollector == null) {
this.tagCollector = new RegistryDataCollector.TagCollector();
}
tags.forEach(this.tagCollector::append);
}
private static <T> Registry.PendingTags<T> resolveRegistryTags(
RegistryAccess.Frozen registryAccess, ResourceKey<? extends Registry<? extends T>> registryKey, TagNetworkSerialization.NetworkPayload payload
) {
Registry<T> registry = registryAccess.lookupOrThrow(registryKey);
return registry.prepareTagReload(payload.resolve(registry));
}
private RegistryAccess loadNewElementsAndTags(
ResourceProvider resourceProvider, RegistryDataCollector.ContentsCollector contentCollector, boolean isMemoryConnection
) {
LayeredRegistryAccess<ClientRegistryLayer> layeredRegistryAccess = ClientRegistryLayer.createRegistryAccess();
RegistryAccess.Frozen frozen = layeredRegistryAccess.getAccessForLoading(ClientRegistryLayer.REMOTE);
Map<ResourceKey<? extends Registry<?>>, RegistryDataLoader.NetworkedRegistryData> map = new HashMap();
contentCollector.elements
.forEach((resourceKey, listx) -> map.put(resourceKey, new RegistryDataLoader.NetworkedRegistryData(listx, TagNetworkSerialization.NetworkPayload.EMPTY)));
List<Registry.PendingTags<?>> list = new ArrayList();
if (this.tagCollector != null) {
this.tagCollector.forEach((resourceKey, networkPayload) -> {
if (!networkPayload.isEmpty()) {
if (RegistrySynchronization.isNetworkable(resourceKey)) {
map.compute(resourceKey, (resourceKeyx, networkedRegistryData) -> {
List<RegistrySynchronization.PackedRegistryEntry> listxx = networkedRegistryData != null ? networkedRegistryData.elements() : List.of();
return new RegistryDataLoader.NetworkedRegistryData(listxx, networkPayload);
});
} else if (!isMemoryConnection) {
list.add(resolveRegistryTags(frozen, resourceKey, networkPayload));
}
}
});
}
List<HolderLookup.RegistryLookup<?>> list2 = TagLoader.buildUpdatedLookups(frozen, list);
RegistryAccess.Frozen frozen2;
try {
frozen2 = RegistryDataLoader.load(map, resourceProvider, list2, RegistryDataLoader.SYNCHRONIZED_REGISTRIES).freeze();
} catch (Exception var13) {
CrashReport crashReport = CrashReport.forThrowable(var13, "Network Registry Load");
addCrashDetails(crashReport, map, list);
throw new ReportedException(crashReport);
}
RegistryAccess registryAccess = layeredRegistryAccess.replaceFrom(ClientRegistryLayer.REMOTE, frozen2).compositeAccess();
list.forEach(Registry.PendingTags::apply);
return registryAccess;
}
private static void addCrashDetails(
CrashReport crashReport,
Map<ResourceKey<? extends Registry<?>>, RegistryDataLoader.NetworkedRegistryData> dynamicRegistries,
List<Registry.PendingTags<?>> staticRegistries
) {
CrashReportCategory crashReportCategory = crashReport.addCategory("Received Elements and Tags");
crashReportCategory.setDetail(
"Dynamic Registries",
(CrashReportDetail<String>)(() -> (String)dynamicRegistries.entrySet()
.stream()
.sorted(Comparator.comparing(entry -> ((ResourceKey)entry.getKey()).location()))
.map(
entry -> String.format(
Locale.ROOT,
"\n\t\t%s: elements=%d tags=%d",
((ResourceKey)entry.getKey()).location(),
((RegistryDataLoader.NetworkedRegistryData)entry.getValue()).elements().size(),
((RegistryDataLoader.NetworkedRegistryData)entry.getValue()).tags().size()
)
)
.collect(Collectors.joining()))
);
crashReportCategory.setDetail(
"Static Registries",
(CrashReportDetail<String>)(() -> (String)staticRegistries.stream()
.sorted(Comparator.comparing(pendingTags -> pendingTags.key().location()))
.map(pendingTags -> String.format(Locale.ROOT, "\n\t\t%s: tags=%d", pendingTags.key().location(), pendingTags.size()))
.collect(Collectors.joining()))
);
}
private void loadOnlyTags(RegistryDataCollector.TagCollector tagCollector, RegistryAccess.Frozen registryAccess, boolean isMemoryConnection) {
tagCollector.forEach((resourceKey, networkPayload) -> {
if (isMemoryConnection || RegistrySynchronization.isNetworkable(resourceKey)) {
resolveRegistryTags(registryAccess, resourceKey, networkPayload).apply();
}
});
}
public RegistryAccess.Frozen collectGameRegistries(ResourceProvider resourceProvider, RegistryAccess.Frozen registryAccess, boolean isMemoryConnection) {
RegistryAccess registryAccess2;
if (this.contentsCollector != null) {
registryAccess2 = this.loadNewElementsAndTags(resourceProvider, this.contentsCollector, isMemoryConnection);
} else {
if (this.tagCollector != null) {
this.loadOnlyTags(this.tagCollector, registryAccess, !isMemoryConnection);
}
registryAccess2 = registryAccess;
}
return registryAccess2.freeze();
}
@Environment(EnvType.CLIENT)
static class ContentsCollector {
final Map<ResourceKey<? extends Registry<?>>, List<RegistrySynchronization.PackedRegistryEntry>> elements = new HashMap();
public void append(ResourceKey<? extends Registry<?>> registryKey, List<RegistrySynchronization.PackedRegistryEntry> entries) {
((List)this.elements.computeIfAbsent(registryKey, resourceKey -> new ArrayList())).addAll(entries);
}
}
@Environment(EnvType.CLIENT)
static class TagCollector {
private final Map<ResourceKey<? extends Registry<?>>, TagNetworkSerialization.NetworkPayload> tags = new HashMap();
public void append(ResourceKey<? extends Registry<?>> registryKey, TagNetworkSerialization.NetworkPayload payload) {
this.tags.put(registryKey, payload);
}
public void forEach(BiConsumer<? super ResourceKey<? extends Registry<?>>, ? super TagNetworkSerialization.NetworkPayload> action) {
this.tags.forEach(action);
}
}
}