package io.gitlab.jfronny.respackopts.filters; import io.gitlab.jfronny.libjf.ResourcePath; import io.gitlab.jfronny.libjf.data.manipulation.api.UserResourceEvents; import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.model.enums.PackCapability; import io.gitlab.jfronny.respackopts.filters.util.FileExclusionProvider; import io.gitlab.jfronny.respackopts.filters.util.FileExpansionProvider; import io.gitlab.jfronny.respackopts.filters.util.FileFallbackProvider; import net.minecraft.resource.*; import net.minecraft.util.Identifier; import java.io.InputStream; import java.util.*; public enum FileFilterEvents implements UserResourceEvents.OpenRoot, UserResourceEvents.Open, UserResourceEvents.FindResource { INSTANCE; public static void init() { UserResourceEvents.OPEN_ROOT.register(INSTANCE); UserResourceEvents.OPEN.register(INSTANCE); UserResourceEvents.FIND_RESOURCE.register(INSTANCE); } @Override public InputSupplier openRoot(String[] fileName, InputSupplier previous, ResourcePack pack) { if (skip(pack)) return previous; String path = String.join("/", fileName); return switch (probe(previous != null, pack, path)) { case MISSING -> null; case FALLBACK -> FileFallbackProvider.getReplacement(pack, path); case CONTAINS -> FileExpansionProvider.replace(previous, pack, path); }; } @Override public InputSupplier open(ResourceType type, Identifier id, InputSupplier previous, ResourcePack pack) { if (skip(pack)) return previous; String name = new ResourcePath(type, id).getName(); return switch (probe(previous != null, pack, name)) { case MISSING -> null; case FALLBACK -> FileFallbackProvider.getReplacement(pack, name); case CONTAINS -> FileExpansionProvider.replace(previous, pack, name); }; } @Override public ResourcePack.ResultConsumer findResources(ResourceType type, String namespace, String prefix, ResourcePack.ResultConsumer previous, ResourcePack pack) { // Warning: the Identifiers here DON'T CONTAIN THE TYPE! // Therefore, it needs to be added when calling a method that generates a ResourcePath! if (skip(pack)) return previous; Set ids = new HashSet<>(); return (identifier, value) -> { // Completion of the path is handled separately here String fileName = type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath(); if (!FileExclusionProvider.fileHidden(pack, fileName) || FileFallbackProvider.fileHasFallback(pack, fileName)) { ids.add(identifier); previous.accept(identifier, open(type, identifier, value, pack)); } FileFallbackProvider.addFallbackResources(namespace, type, identifier, pack, ids, previous); }; } private ContainsResult probe(boolean previous, ResourcePack pack, String name) { if (previous) { if (!FileExclusionProvider.fileHidden(pack, name)) return ContainsResult.CONTAINS; else if (FileFallbackProvider.fileHasFallback(pack, name)) return ContainsResult.FALLBACK; else return ContainsResult.MISSING; } else { boolean missing; if (name.contains("/")) { ResourcePath rp = new ResourcePath(name + Respackopts.FILE_EXTENSION); missing = UserResourceEvents.disable(() -> pack.open(rp.getType(), rp.getId())) == null; } else missing = UserResourceEvents.disable(() -> pack.openRoot(name + Respackopts.FILE_EXTENSION)) == null; if (missing && FileFallbackProvider.fileHasFallback(pack, name)) return ContainsResult.FALLBACK; else return ContainsResult.MISSING; } } enum ContainsResult { MISSING, CONTAINS, FALLBACK } private boolean skip(ResourcePack pack) { return !(pack instanceof AbstractFileResourcePack && MetaCache.hasCapability(pack, PackCapability.FileFilter)); } }