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.AbstractFileResourcePack; import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.HashMap; import java.util.Map; public class FileFilterEventImpl { private static final Map containsFileWasFallback = new HashMap<>(); private static boolean containsFileWasFallback() { boolean v = FileFilterEventImpl.containsFileWasFallback.getOrDefault(Thread.currentThread().getId(), false); containsFileWasFallback(false); return v; } private static void containsFileWasFallback(boolean value) { FileFilterEventImpl.containsFileWasFallback.put(Thread.currentThread().getId(), value); } public static void init() { UserResourceEvents.OPEN.register((type, id, previous, pack) -> { if (skip(pack)) return previous.get(); String name = new ResourcePath(type, id).getName(); if (pack.contains(type, id)) { return containsFileWasFallback() ? FileFallbackProvider.getReplacement(pack, name) : FileExpansionProvider.replace(previous.get(), pack, name); } else return null; }); UserResourceEvents.FIND_RESOURCE.register((type, namespace, prefix, allowedPathPredicate, previous, pack) -> { // Warning: the Identifiers here DON'T CONTAIN THE TYPE! // Therefore, it needs to be added when calling a method that generates a ResourcePath! Collection prevVals = previous.get(); if (skip(pack)) return prevVals; prevVals.removeIf(s -> { String fileName = type.getDirectory() + "/" + s.getNamespace() + "/" + s.getPath(); return FileExclusionProvider.fileHidden(pack, fileName) && !FileFallbackProvider.fileHasFallback(pack, fileName); }); // Completion of the path is handled separately here FileFallbackProvider.addFallbackResources(pack, prevVals, namespace, type); return prevVals; }); UserResourceEvents.CONTAINS.register((type, id, previous, pack) -> { if (skip(pack)) return previous.get(); containsFileWasFallback(false); return containsHook(previous.get(), pack, new ResourcePath(type, id).getName()); }); UserResourceEvents.OPEN_ROOT.register((fileName, previous, pack) -> { if (skip(pack)) return previous.get(); InputStream is = previous.get(); if (containsHook(is != null, pack, fileName)) { return containsFileWasFallback() ? FileFallbackProvider.getReplacement(pack, fileName) : FileExpansionProvider.replace(previous.get(), pack, fileName); } else return null; }); } private static boolean containsHook(boolean previous, ResourcePack pack, String name) { if (previous) { if (FileExclusionProvider.fileHidden(pack, name)) { if (FileFallbackProvider.fileHasFallback(pack, name)) { containsFileWasFallback(true); } else { return false; } } return true; } else { boolean hasRpo; try { hasRpo = UserResourceEvents.disable(() -> { if (name.contains("/")) { ResourcePath rp = new ResourcePath(name + Respackopts.FILE_EXTENSION); return pack.contains(rp.getType(), rp.getId()); } return pack.openRoot(name + Respackopts.FILE_EXTENSION) != null; }); } catch (IOException e) { hasRpo = false; } if (hasRpo && FileFallbackProvider.fileHasFallback(pack, name)) { containsFileWasFallback(true); return true; } return false; } } private static boolean skip(ResourcePack pack) { return !(pack instanceof AbstractFileResourcePack) || !MetaCache.hasCapability(pack, PackCapability.FileFilter); } }