174 lines
7.2 KiB
Java
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);
|
|
}
|
|
}
|
|
}
|