diff --git a/gradle.properties b/gradle.properties index c84a489..2e1d74f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ minecraft_version=1.17.1 yarn_mappings=build.43 loader_version=0.11.6 # Mod Properties -mod_version=2.4.0 +mod_version=2.5.0 maven_group=io.gitlab.jfronny archives_base_name=respackopts diff --git a/run/resourcepacks/testpack/assets/minecraft/lang/.rpo b/run/resourcepacks/testpack/assets/minecraft/lang/.rpo new file mode 100644 index 0000000..afc6001 --- /dev/null +++ b/run/resourcepacks/testpack/assets/minecraft/lang/.rpo @@ -0,0 +1,4 @@ +{ + "conditions": ["false"], + "fallback": "assets/minecraft/langer" +} \ No newline at end of file diff --git a/run/resourcepacks/testpack/assets/minecraft/lang/de_de.json.rpo b/run/resourcepacks/testpack/assets/minecraft/langer/de_de.json.rpo similarity index 100% rename from run/resourcepacks/testpack/assets/minecraft/lang/de_de.json.rpo rename to run/resourcepacks/testpack/assets/minecraft/langer/de_de.json.rpo diff --git a/run/resourcepacks/testpack/assets/minecraft/lang/en_us.json b/run/resourcepacks/testpack/assets/minecraft/langer/en_us.json similarity index 100% rename from run/resourcepacks/testpack/assets/minecraft/lang/en_us.json rename to run/resourcepacks/testpack/assets/minecraft/langer/en_us.json diff --git a/run/resourcepacks/testpack/assets/minecraft/lang/en_us.json.rpo b/run/resourcepacks/testpack/assets/minecraft/langer/en_us.json.rpo similarity index 100% rename from run/resourcepacks/testpack/assets/minecraft/lang/en_us.json.rpo rename to run/resourcepacks/testpack/assets/minecraft/langer/en_us.json.rpo diff --git a/run/resourcepacks/testpack/assets/minecraft/lang/en_us_joke.json b/run/resourcepacks/testpack/assets/minecraft/langer/en_us_joke.json similarity index 100% rename from run/resourcepacks/testpack/assets/minecraft/lang/en_us_joke.json rename to run/resourcepacks/testpack/assets/minecraft/langer/en_us_joke.json diff --git a/run/resourcepacks/testpack/assets/minecraft/lang/en_us_joke.json.rpo b/run/resourcepacks/testpack/assets/minecraft/langer/en_us_joke.json.rpo similarity index 100% rename from run/resourcepacks/testpack/assets/minecraft/lang/en_us_joke.json.rpo rename to run/resourcepacks/testpack/assets/minecraft/langer/en_us_joke.json.rpo diff --git a/src/main/java/io/gitlab/jfronny/respackopts/Respackopts.java b/src/main/java/io/gitlab/jfronny/respackopts/Respackopts.java index d605ad1..f954019 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/Respackopts.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/Respackopts.java @@ -3,7 +3,8 @@ package io.gitlab.jfronny.respackopts; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.gitlab.jfronny.respackopts.data.entry.*; -import io.gitlab.jfronny.respackopts.filters.FilterProvider; +import io.gitlab.jfronny.respackopts.filters.DirFilterProvider; +import io.gitlab.jfronny.respackopts.filters.FileFilterProvider; import io.gitlab.jfronny.respackopts.gson.*; import meteordevelopment.starscript.Script; import meteordevelopment.starscript.StandardLib; @@ -85,7 +86,8 @@ public class Respackopts implements ClientModInitializer { STAR_SCRIPT.set(sanitizeString(e.getKey()), () -> e.getValue().buildStarscript()); } }); - FilterProvider.init(); + DirFilterProvider.init(); + FileFilterProvider.init(); } public static void save() { diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/DirRpo.java b/src/main/java/io/gitlab/jfronny/respackopts/data/DirRpo.java new file mode 100644 index 0000000..cec3482 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/DirRpo.java @@ -0,0 +1,12 @@ +package io.gitlab.jfronny.respackopts.data; + +import com.google.gson.JsonArray; +import io.gitlab.jfronny.libjf.gson.GsonHidden; + +public class DirRpo { + public JsonArray conditions; + public String fallback; + + @GsonHidden + public String path; +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/entry/ConfigBranch.java b/src/main/java/io/gitlab/jfronny/respackopts/data/entry/ConfigBranch.java index 7018107..e4281c1 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/data/entry/ConfigBranch.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/entry/ConfigBranch.java @@ -58,6 +58,11 @@ public class ConfigBranch extends ConfigEntry>> { } } } + if (mode == SyncMode.RESPACK_LOAD) + for (Map.Entry> e : super.getValue().entrySet()) { + if (!source.getValue().containsKey(e.getKey())) + getValue().remove(e.getKey()); + } } private void syncSub(ConfigEntry current, ConfigEntry next, SyncMode mode) { diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterProvider.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterProvider.java new file mode 100644 index 0000000..e27c3a6 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterProvider.java @@ -0,0 +1,100 @@ +package io.gitlab.jfronny.respackopts.filters; + +import io.gitlab.jfronny.libjf.data.ResourcePath; +import io.gitlab.jfronny.libjf.data.UserResourceEvents; +import io.gitlab.jfronny.libjf.data.WrappedPack; +import io.gitlab.jfronny.respackopts.Respackopts; +import io.gitlab.jfronny.respackopts.data.DirRpo; +import io.gitlab.jfronny.respackopts.data.RpoError; +import io.gitlab.jfronny.respackopts.filters.conditions.ConditionEvaluator; +import net.minecraft.util.Identifier; + +import java.io.*; + +public class DirFilterProvider { + public static void init() { + UserResourceEvents.OPEN.register((type, id, previous, pack) -> { + String path = new ResourcePath(type, id).getName(); + DirRpo rpo = findDirRpo(pack, path); + if (rpo != null && dirHidden(rpo)) { + path = findReplacementDir(path, rpo); + if (path == null) throw new FileNotFoundException(); + ResourcePath rp = new ResourcePath(path); + return pack.open(rp.getType(), rp.getId()); + } + return previous; + }); + UserResourceEvents.FIND_RESOURCE.register((type, namespace, prefix, maxDepth, pathFilter, 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! + //TODO support files that weren't there at the original location + for (Identifier identifier : previous) { + String path = type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath(); + DirRpo rpo = findDirRpo(pack, path); + if (rpo != null && dirHidden(rpo)) { + path = findReplacementDir(path, rpo); + if (path == null) + previous.remove(identifier); + } + } + return previous; + }); + UserResourceEvents.CONTAINS.register((type, id, previous, pack) -> { + String path = new ResourcePath(type, id).getName(); + DirRpo rpo = findDirRpo(pack, path); + if (rpo != null && dirHidden(rpo)) { + path = findReplacementDir(path, rpo); + if (path == null) + return false; + ResourcePath rp = new ResourcePath(path); + return pack.contains(rp.getType(), rp.getId()); + } + return previous; + }); + } + + private static String findReplacementDir(String dir, DirRpo rpo) { + if (rpo.fallback == null) return null; + return dir.replace(rpo.path + "/", rpo.fallback); + } + + private static boolean dirHidden(DirRpo rpo) { + if (rpo.conditions == null) + return false; + try { + return !ConditionEvaluator.evaluate(rpo.conditions); + } catch (RpoError e) { + Respackopts.LOGGER.error("Couldn't parse dir conditions", e); + } + return false; + } + + private static DirRpo findDirRpo(WrappedPack pack, String name) { + int li = name.lastIndexOf('/'); + if (li <= 0) + return null; + name = name.substring(0, li); + DirRpo drp = findDirRpo(pack, name); + if (drp != null) + return drp; + ResourcePath rp; + try { + rp = new ResourcePath(name + "/.rpo"); + } + catch (Exception e) { + return null; + } + if (pack.getUnderlying().contains(rp.getType(), rp.getId())) { + try (InputStream stream = pack.getUnderlying().open(rp.getType(), rp.getId()); Reader w = new InputStreamReader(stream)) { + drp = Respackopts.GSON.fromJson(w, DirRpo.class); + drp.path = name; + if (drp.fallback != null && !drp.fallback.endsWith("/")) + drp.fallback += "/"; + return drp; + } catch (IOException e) { + Respackopts.LOGGER.error("Couldn't open dir rpo", e); + } + } + return null; + } +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/FilterProvider.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterProvider.java similarity index 83% rename from src/main/java/io/gitlab/jfronny/respackopts/filters/FilterProvider.java rename to src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterProvider.java index b29ca06..b515e86 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/FilterProvider.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterProvider.java @@ -13,22 +13,25 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.util.concurrent.atomic.AtomicBoolean; -public class FilterProvider { +public class FileFilterProvider { public static void init() { AtomicBoolean containsFileWasFallback = new AtomicBoolean(false); UserResourceEvents.OPEN.register((type, id, previous, pack) -> { if (skip(pack)) return previous; String name = new ResourcePath(type, id).getName(); IOException ex = new FileNotFoundException(); - if (pack.contains(type, id) && containsFileWasFallback.get()) { - return FallbackFilter.getReplacement(pack, name, ex); + if (pack.contains(type, id)) { + if (containsFileWasFallback.get()) + return FallbackFilter.getReplacement(pack, name, ex); + return DataExpander.replace(previous, pack, name, ex); } - return DataExpander.replace(previous, pack, name, ex); + throw ex; }); UserResourceEvents.FIND_RESOURCE.register((type, namespace, prefix, maxDepth, pathFilter, 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! + // 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; - previous.removeIf(s -> ResourcePackFilter.fileHidden(pack, type.getDirectory() + "/" + s.getPath()) && !FallbackFilter.fileVisible(pack, namespace)); + previous.removeIf(s -> ResourcePackFilter.fileHidden(pack, type.getDirectory() + "/" + s.getNamespace() + "/" + s.getPath()) && !FallbackFilter.fileVisible(pack, namespace)); // Completion of the path is handled separately here FallbackFilter.addFallbackResources(pack, previous, namespace, type); return previous;