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

110 lines
4.8 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.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<Long, Boolean> 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<Identifier> 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);
}
}