From 7039bcada7cd8196b836f613e1785c4bed056c8c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 29 Apr 2023 21:24:06 -0400 Subject: [PATCH] Reintroduce separate root listing list --- .../resources/PackResourcesCacheEngine.java | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java b/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java index 47577b5f..30590ac7 100644 --- a/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java +++ b/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java @@ -1,5 +1,9 @@ package org.embeddedt.modernfix.resources; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.mojang.datafixers.util.Pair; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; @@ -14,9 +18,16 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; +/** + * The core of the resource pack cache system. + * + * Using a dedicated set and also separate lists is important; testing without this showed a huge performance + * drop. + */ public class PackResourcesCacheEngine { private final Map> namespacesByType; private final Set containedPaths; + private final EnumMap>> resourceListings; public PackResourcesCacheEngine(Function> namespacesRetriever, BiFunction basePathRetriever) { this.namespacesByType = new EnumMap<>(PackType.class); @@ -26,22 +37,31 @@ public class PackResourcesCacheEngine { this.namespacesByType.put(type, namespacesRetriever.apply(type)); } this.containedPaths = new ObjectOpenHashSet<>(); + this.resourceListings = new EnumMap<>(PackType.class); for(PackType type : PackType.values()) { Collection namespaces = PackTypeHelper.isVanillaPackType(type) ? this.namespacesByType.get(type) : namespacesRetriever.apply(type); + ImmutableMap.Builder> packTypedMap = ImmutableMap.builder(); for(String namespace : namespaces) { try { + ImmutableList.Builder namespacedList = ImmutableList.builder(); Path root = basePathRetriever.apply(type, namespace).toAbsolutePath(); + String[] prefix = new String[] { type.getDirectory(), namespace }; try (Stream stream = Files.walk(root)) { stream .map(path -> root.relativize(path.toAbsolutePath())) .filter(PackResourcesCacheEngine::isValidCachedResourcePath) .forEach(path -> { - this.containedPaths.add(new CachedResourcePath(new String[] { type.getDirectory(), namespace }, path)); + CachedResourcePath cachedPath = new CachedResourcePath(prefix, path); + this.containedPaths.add(cachedPath); + if(!cachedPath.getFileName().endsWith(".mcmeta")) + namespacedList.add(cachedPath); }); } + packTypedMap.put(namespace, namespacedList.build()); } catch(IOException ignored) { } } + this.resourceListings.put(type, packTypedMap.build()); } ((ObjectOpenHashSet)this.containedPaths).trim(); } @@ -73,20 +93,16 @@ public class PackResourcesCacheEngine { } public Collection getResources(PackType type, String resourceNamespace, String pathIn, int maxDepth, Predicate filter) { + if(!PackTypeHelper.isVanillaPackType(type)) + throw new IllegalArgumentException("Only vanilla PackTypes are supported"); + List paths = resourceListings.get(type).getOrDefault(resourceNamespace, Collections.emptyList()); + if(paths.isEmpty()) + return Collections.emptyList(); String testPath = pathIn.endsWith("/") ? pathIn : (pathIn + "/"); ArrayList resources = new ArrayList<>(); - String typeDirectory = CachedResourcePath.PATH_COMPONENT_INTERNER.intern(type.getDirectory()); - resourceNamespace = CachedResourcePath.PATH_COMPONENT_INTERNER.intern(resourceNamespace); - for(CachedResourcePath cachePath : this.containedPaths) { - if(cachePath.getNameCount() < 2) - continue; + for(CachedResourcePath cachePath : paths) { if((cachePath.getNameCount() - 2) > maxDepth) continue; - // we interned, so reference equality is safe - if(cachePath.getNameAt(0) != typeDirectory || cachePath.getNameAt(1) != resourceNamespace) - continue; - if(cachePath.getFileName().endsWith(".mcmeta")) - continue; String fullPath = cachePath.getFullPath(2); if(!fullPath.startsWith(testPath)) continue;