package net.minecraft.server.packs.resources; import com.mojang.logging.LogUtils; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.TreeMap; import java.util.function.Predicate; import java.util.stream.Stream; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackResources; import net.minecraft.server.packs.PackType; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; public class MultiPackResourceManager implements CloseableResourceManager { private static final Logger LOGGER = LogUtils.getLogger(); private final Map namespacedManagers; private final List packs; public MultiPackResourceManager(PackType type, List packs) { this.packs = List.copyOf(packs); Map map = new HashMap(); List list = packs.stream().flatMap(packResourcesx -> packResourcesx.getNamespaces(type).stream()).distinct().toList(); for (PackResources packResources : packs) { ResourceFilterSection resourceFilterSection = this.getPackFilterSection(packResources); Set set = packResources.getNamespaces(type); Predicate predicate = resourceFilterSection != null ? resourceLocation -> resourceFilterSection.isPathFiltered(resourceLocation.getPath()) : null; for (String string : list) { boolean bl = set.contains(string); boolean bl2 = resourceFilterSection != null && resourceFilterSection.isNamespaceFiltered(string); if (bl || bl2) { FallbackResourceManager fallbackResourceManager = (FallbackResourceManager)map.get(string); if (fallbackResourceManager == null) { fallbackResourceManager = new FallbackResourceManager(type, string); map.put(string, fallbackResourceManager); } if (bl && bl2) { fallbackResourceManager.push(packResources, predicate); } else if (bl) { fallbackResourceManager.push(packResources); } else { fallbackResourceManager.pushFilterOnly(packResources.packId(), predicate); } } } } this.namespacedManagers = map; } @Nullable private ResourceFilterSection getPackFilterSection(PackResources packResources) { try { return packResources.getMetadataSection(ResourceFilterSection.TYPE); } catch (IOException var3) { LOGGER.error("Failed to get filter section from pack {}", packResources.packId()); return null; } } @Override public Set getNamespaces() { return this.namespacedManagers.keySet(); } @Override public Optional getResource(ResourceLocation resourceLocation) { ResourceManager resourceManager = (ResourceManager)this.namespacedManagers.get(resourceLocation.getNamespace()); return resourceManager != null ? resourceManager.getResource(resourceLocation) : Optional.empty(); } @Override public List getResourceStack(ResourceLocation location) { ResourceManager resourceManager = (ResourceManager)this.namespacedManagers.get(location.getNamespace()); return resourceManager != null ? resourceManager.getResourceStack(location) : List.of(); } @Override public Map listResources(String path, Predicate filter) { checkTrailingDirectoryPath(path); Map map = new TreeMap(); for (FallbackResourceManager fallbackResourceManager : this.namespacedManagers.values()) { map.putAll(fallbackResourceManager.listResources(path, filter)); } return map; } @Override public Map> listResourceStacks(String path, Predicate filter) { checkTrailingDirectoryPath(path); Map> map = new TreeMap(); for (FallbackResourceManager fallbackResourceManager : this.namespacedManagers.values()) { map.putAll(fallbackResourceManager.listResourceStacks(path, filter)); } return map; } private static void checkTrailingDirectoryPath(String path) { if (path.endsWith("/")) { throw new IllegalArgumentException("Trailing slash in path " + path); } } @Override public Stream listPacks() { return this.packs.stream(); } @Override public void close() { this.packs.forEach(PackResources::close); } }