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

90 lines
4.2 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.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<InputStream> openRoot(String[] fileName, InputSupplier<InputStream> 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<InputStream> open(ResourceType type, Identifier id, InputSupplier<InputStream> 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<Identifier> 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));
}
}