Respackopts/src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterEvents.java

89 lines
4.0 KiB
Java

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.filters.util.*;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.model.enums.PackCapability;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.minecraft.resource.*;
import net.minecraft.util.Identifier;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;
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<InputStream> openRoot(String[] fileName, InputSupplier<InputStream> previous, ResourcePack pack) {
if (skip(pack)) return previous;
return open(previous, pack, String.join("/", fileName));
}
@Override
public InputSupplier<InputStream> open(ResourceType type, Identifier id, InputSupplier<InputStream> previous, ResourcePack pack) {
if (skip(pack)) return previous;
return open(previous, pack, new ResourcePath(type, id).getName());
}
private InputSupplier<InputStream> open(InputSupplier<InputStream> previous, ResourcePack pack, String name) {
CacheKey key = MetaCache.getKeyByPack(pack);
RespackoptsFS fs = new RespackoptsFS(pack);
return switch (probe(previous != null, key, fs, name)) {
case MISSING -> null;
case FALLBACK -> FileFallbackProvider.getReplacement(key, fs, name);
case CONTAINS -> FileExpansionProvider.replace(previous, key, fs, 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<Identifier> ids = new HashSet<>();
CacheKey key = MetaCache.getKeyByPack(pack);
RespackoptsFS fs = new RespackoptsFS(pack);
return (identifier, value) -> {
// Completion of the path is handled separately here
String fileName = type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath();
if (!FileExclusionProvider.fileHidden(key, fs, fileName) || FileFallbackProvider.fileHasFallback(key, fs, fileName)) {
ids.add(identifier);
previous.accept(identifier, open(type, identifier, value, pack));
}
FileFallbackProvider.addFallbackResources(namespace, type, identifier, key, fs, ids, previous);
};
}
private ContainsResult probe(boolean previous, CacheKey key, RespackoptsFS fs, String name) {
if (previous) {
if (!FileExclusionProvider.fileHidden(key, fs, name)) return ContainsResult.CONTAINS;
else if (FileFallbackProvider.fileHasFallback(key, fs, name)) return ContainsResult.FALLBACK;
else return ContainsResult.MISSING;
}
else {
boolean missing = UserResourceEvents.disable(() -> fs.open(name + Respackopts.FILE_EXTENSION)) == null;
if (missing && FileFallbackProvider.fileHasFallback(key, fs, name)) return ContainsResult.FALLBACK;
else return ContainsResult.MISSING;
}
}
enum ContainsResult {
MISSING, CONTAINS, FALLBACK
}
private boolean skip(ResourcePack pack) {
return !MetaCache.hasCapability(pack, PackCapability.FileFilter);
}
}