diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterEvents.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterEvents.java index f55f750..6edc5e4 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterEvents.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterEvents.java @@ -19,97 +19,108 @@ import net.minecraft.util.Identifier; import java.io.*; import java.util.*; -public enum DirFilterEvents implements UserResourceEvents.Open, UserResourceEvents.FindResource { +public enum DirFilterEvents 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; + return open(previous, pack, String.join("/", fileName)); + } + @Override public InputSupplier open(ResourceType type, Identifier id, InputSupplier previous, ResourcePack pack) { - if (!MetaCache.hasCapability(pack, PackCapability.DirFilter)) return previous; - String path = new ResourcePath(type, id).getName(); - List rpo = findDirRpos(pack, parent(path)); + if (skip(pack)) return previous; + return open(previous, pack, new ResourcePath(type, id).getName()); + } + + private InputSupplier open(InputSupplier previous, ResourcePack pack, String name) { + List rpo = findDirRpos(pack, parent(name)); CacheKey key = MetaCache.getKeyByPack(pack); RespackoptsFS fs = new RespackoptsFS(pack); - //TODO use pattern matching for switch - DirRpoResult result = DirRpoResult.compute(path, rpo, key, fs); - if (result == DirRpoResult.ORIGINAL) return previous; // Using original file - if (result == DirRpoResult.IGNORE) return null; // No fallback - // Use fallback - DirRpoResult.Replacement replacement = (DirRpoResult.Replacement) result; - String fallback = replacement.toFallback(path); - MetaCache.addDependency(key, path, fallback); - return fs.open(fallback); + return switch (DirRpoResult.compute(name, rpo, key, fs)) { + case DirRpoResult.FixedState.ORIGINAL -> previous; // Using original file + case DirRpoResult.FixedState.IGNORE -> null; // No fallback + case DirRpoResult.Replacement replacement -> { + // Use fallback + String fallback = replacement.toFallback(name); + MetaCache.addDependency(key, name, fallback); + yield fs.open(fallback); + } + }; } @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 (!MetaCache.hasCapability(pack, PackCapability.DirFilter)) return previous; + if (skip(pack)) return previous; boolean dirFilterAdditive = MetaCache.hasCapability(pack, PackCapability.DirFilterAdditive); String searchPrefix = type.getDirectory() + "/" + namespace + "/" + prefix; Set additionalSearched = new HashSet<>(); CacheKey key = MetaCache.getKeyByPack(pack); RespackoptsFS fs = new RespackoptsFS(pack); return (identifier, value) -> { - String path = path(type, identifier); - //TODO use pattern matching for switch + String path = new ResourcePath(type, identifier).getName(); List relevantRpos = findDirRpos(pack, parent(path)); - DirRpoResult result = DirRpoResult.compute(path, relevantRpos, key, fs); - if (result == DirRpoResult.ORIGINAL) { // Using original file - previous.accept(identifier, value); - return; - } - if (result == DirRpoResult.IGNORE) return; // No fallback - // New search for fallback path - DirRpoResult.Replacement replacement = (DirRpoResult.Replacement) result; - String newPath = replacement.toFallback(path); - if (newPath.split("/", 3).length != 3) { - Respackopts.LOGGER.error("Directory fallback path MUST be long enough to support representation as identifier (3 segments), but is too short: " + newPath); - return; - } - if (!dirFilterAdditive) { - // Only return this single result, don't search for others - MetaCache.addDependency(key, path, newPath); - previous.accept(identifier, fs.open(newPath)); - return; - } - // Find other files in the fallback directory - String fallbackDir = replacement.fallback.prefix(); - if (!additionalSearched.add(fallbackDir)) return; // Already searched - int prefixSize = replacement.original.prefix().length(); - if (prefixSize < searchPrefix.length()) { - if (!searchPrefix.startsWith(replacement.original.prefix())) { - Respackopts.LOGGER.error("Unexpected prefix path " + replacement.original.prefix() + " for search prefix " + searchPrefix + ", skipping"); - return; + switch (DirRpoResult.compute(path, relevantRpos, key, fs)) { + case DirRpoResult.FixedState.ORIGINAL -> { + // Using original file + previous.accept(identifier, value); + } + case DirRpoResult.FixedState.IGNORE -> { + // No fallback + } + case DirRpoResult.Replacement replacement -> { + // New search for fallback path + String newPath = replacement.toFallback(path); + if (newPath.split("/", 3).length != 3) { + Respackopts.LOGGER.error("Directory fallback path MUST be long enough to support representation as identifier (3 segments), but is too short: " + newPath); + return; + } + if (!dirFilterAdditive) { + // Only return this single result, don't search for others + MetaCache.addDependency(key, path, newPath); + previous.accept(identifier, fs.open(newPath)); + return; + } + // Find other files in the fallback directory + String fallbackDir = replacement.fallback.prefix(); + if (!additionalSearched.add(fallbackDir)) return; // Already searched + int prefixSize = replacement.original.prefix().length(); + if (prefixSize < searchPrefix.length()) { + if (!searchPrefix.startsWith(replacement.original.prefix())) { + Respackopts.LOGGER.error("Unexpected prefix path " + replacement.original.prefix() + " for search prefix " + searchPrefix + ", skipping"); + return; + } + fallbackDir += searchPrefix.substring(prefixSize); + } else if (!replacement.original.prefix().startsWith(searchPrefix)) { + Respackopts.LOGGER.error("Unexpected prefix path " + replacement.original.prefix() + " for search prefix " + searchPrefix + ", skipping"); + return; + } + if (fallbackDir.split("/", 3).length != 3) { + Respackopts.LOGGER.error("Directory fallback path MUST be long enough to support representation as identifier (3 segments), but is too short: " + fallbackDir); + return; + } + ResourcePath rp = new ResourcePath(fallbackDir); + pack.findResources(rp.getType(), rp.getId().getNamespace(), rp.getId().getPath(), (resource, resVal) -> { + ResourceType type1 = rp.getType(); + String fallbackPath = new ResourcePath(type1, resource).getName(); + String orig = replacement.toOriginal(fallbackPath); + MetaCache.addDependency(key, orig, fallbackPath); + previous.accept(new ResourcePath(orig).getId(), resVal); + }); } - fallbackDir += searchPrefix.substring(prefixSize); - } else if (!replacement.original.prefix().startsWith(searchPrefix)) { - Respackopts.LOGGER.error("Unexpected prefix path " + replacement.original.prefix() + " for search prefix " + searchPrefix + ", skipping"); - return; } - if (fallbackDir.split("/", 3).length != 3) { - Respackopts.LOGGER.error("Directory fallback path MUST be long enough to support representation as identifier (3 segments), but is too short: " + fallbackDir); - return; - } - ResourcePath rp = new ResourcePath(fallbackDir); - pack.findResources(rp.getType(), rp.getId().getNamespace(), rp.getId().getPath(), (resource, resVal) -> { - String fallbackPath = path(rp.getType(), resource); - String orig = replacement.toOriginal(fallbackPath); - MetaCache.addDependency(key, orig, fallbackPath); - previous.accept(new ResourcePath(orig).getId(), resVal); - }); }; } - private String path(ResourceType type, Identifier identifier) { - return type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath(); - } - private String parent(String path) { int li = path.lastIndexOf('/'); return li <= 0 ? null : path.substring(0, li); @@ -154,4 +165,8 @@ public enum DirFilterEvents implements UserResourceEvents.Open, UserResourceEven }); } } + + private boolean skip(ResourcePack pack) { + return !MetaCache.hasCapability(pack, PackCapability.DirFilter); + } } diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterEvents.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterEvents.java index 8324f72..b698fe4 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterEvents.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterEvents.java @@ -83,6 +83,6 @@ public enum FileFilterEvents implements UserResourceEvents.OpenRoot, UserResourc } private boolean skip(ResourcePack pack) { - return !(pack instanceof AbstractFileResourcePack && MetaCache.hasCapability(pack, PackCapability.FileFilter)); + return !MetaCache.hasCapability(pack, PackCapability.FileFilter); } } diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/util/DirRpoResult.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/util/DirRpoResult.java index 6b4d5f8..2c2b90f 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/util/DirRpoResult.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/filters/util/DirRpoResult.java @@ -23,7 +23,7 @@ public sealed interface DirRpoResult { static DirRpoResult compute(String file, List rpos, CacheKey key, RespackoptsFS fs) { int version = MetaCache.getMeta(key).version; - if (version < 11) rpos = rpos.isEmpty() ? rpos : List.of(rpos.get(rpos.size() - 1)); + if (version < 11) rpos = rpos.isEmpty() ? rpos : List.of(rpos.getLast()); LazySupplier scope = new LazySupplier<>(() -> MetaCache.getScope(key, fs)); for (DirRpo rpo : rpos) { if (rpo.condition == null) continue;