125 lines
5.5 KiB
Java
125 lines
5.5 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.muscript.debug.ObjectGraphPrinter;
|
|
import io.gitlab.jfronny.respackopts.Respackopts;
|
|
import io.gitlab.jfronny.respackopts.gson.AttachmentHolder;
|
|
import io.gitlab.jfronny.respackopts.model.Condition;
|
|
import io.gitlab.jfronny.respackopts.model.DirRpo;
|
|
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
|
|
import io.gitlab.jfronny.respackopts.model.cache.CachedPackState;
|
|
import io.gitlab.jfronny.respackopts.model.enums.PackCapability;
|
|
import io.gitlab.jfronny.respackopts.util.MetaCache;
|
|
import net.minecraft.resource.*;
|
|
import net.minecraft.util.Identifier;
|
|
|
|
import java.io.*;
|
|
import java.util.Map;
|
|
|
|
public enum DirFilterEvents implements UserResourceEvents.Open, UserResourceEvents.FindResource {
|
|
INSTANCE;
|
|
|
|
public static void init() {
|
|
UserResourceEvents.OPEN.register(INSTANCE);
|
|
UserResourceEvents.FIND_RESOURCE.register(INSTANCE);
|
|
}
|
|
|
|
@Override
|
|
public InputSupplier<InputStream> open(ResourceType type, Identifier id, InputSupplier<InputStream> previous, ResourcePack pack) {
|
|
if (!MetaCache.hasCapability(pack, PackCapability.DirFilter)) return previous;
|
|
String path = new ResourcePath(type, id).getName();
|
|
DirRpo rpo = findDirRpo(pack, path);
|
|
if (rpo != null && dirHidden(rpo, MetaCache.getKeyByPack(pack), path)) {
|
|
path = findReplacementDir(path, rpo);
|
|
if (path == null) return null;
|
|
ResourcePath rp = new ResourcePath(path);
|
|
return pack.open(rp.getType(), rp.getId());
|
|
}
|
|
return previous;
|
|
}
|
|
|
|
@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;
|
|
boolean dirFilterAdditive = MetaCache.hasCapability(pack, PackCapability.DirFilterAdditive);
|
|
return (identifier, value) -> {
|
|
String path = type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath();
|
|
DirRpo rpo = findDirRpo(pack, path);
|
|
if (rpo != null && dirHidden(rpo, MetaCache.getKeyByPack(pack), path)) {
|
|
path = findReplacementDir(path, rpo);
|
|
if (path != null && dirFilterAdditive) {
|
|
String[] s = path.split("/", 3);
|
|
if (s.length == 3) {
|
|
ResourcePath rp = new ResourcePath(path);
|
|
//TODO improve this impl (used for files that aren't at the original location
|
|
pack.findResources(rp.getType(), rp.getId().getNamespace(), rp.getId().getPath(), (resource, resVal) -> {
|
|
String p = type.getDirectory() + "/" + resource.getNamespace() + "/" + resource.getPath();
|
|
p = p.replace(rpo.fallback, rpo.path + "/");
|
|
previous.accept(new ResourcePath(p).getId(), resVal);
|
|
});
|
|
}
|
|
}
|
|
} else previous.accept(identifier, value);
|
|
};
|
|
}
|
|
|
|
private String findReplacementDir(String dir, DirRpo rpo) {
|
|
if (rpo.fallback == null) return null;
|
|
return dir.replace(rpo.path + "/", rpo.fallback);
|
|
}
|
|
|
|
private boolean dirHidden(DirRpo rpo, CacheKey key, String file) {
|
|
if (rpo.condition == null)
|
|
return false;
|
|
try {
|
|
return !rpo.condition.get(MetaCache.getParameter(key));
|
|
} catch (Condition.ConditionException e) {
|
|
String res = "Could not evaluate condition " + file + " (pack: " + key.packName() + ")";
|
|
try {
|
|
Respackopts.LOGGER.error(res + " with condition:\n" + ObjectGraphPrinter.printGraph(rpo.condition) + ")", e);
|
|
} catch (Throwable ex) {
|
|
Respackopts.LOGGER.error(res, e);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private DirRpo findDirRpo(ResourcePack pack, String name) {
|
|
CachedPackState state = MetaCache.getState(MetaCache.getKeyByPack(pack));
|
|
Map<String, DirRpo> drpReg = state.cachedDirRPOs();
|
|
int li = name.lastIndexOf('/');
|
|
if (li <= 0)
|
|
return null;
|
|
name = name.substring(0, li);
|
|
if (drpReg.containsKey(name)) return drpReg.get(name);
|
|
DirRpo drp = findDirRpo(pack, name);
|
|
if (drp != null) {
|
|
drpReg.put(name, drp);
|
|
return drp;
|
|
}
|
|
ResourcePath rp;
|
|
try {
|
|
rp = new ResourcePath(name + "/" + Respackopts.FILE_EXTENSION);
|
|
}
|
|
catch (Exception e) {
|
|
return null;
|
|
}
|
|
InputSupplier<InputStream> is = UserResourceEvents.disable(() -> pack.open(rp.getType(), rp.getId()));
|
|
if (is == null) return null;
|
|
try (Reader w = new InputStreamReader(is.get())) {
|
|
drp = AttachmentHolder.deserialize(state.metadata().version, w, DirRpo.class);
|
|
drp.path = name;
|
|
if (drp.fallback != null && !drp.fallback.endsWith("/"))
|
|
drp.fallback += "/";
|
|
drpReg.put(name, drp);
|
|
return drp;
|
|
} catch (IOException e) {
|
|
Respackopts.LOGGER.error("Couldn't open dir rpo " + rp.getName(), e);
|
|
}
|
|
return null;
|
|
}
|
|
}
|