feat: update to 1.20.2 snapshot and implement RespackoptsFS abstraction over resource packs
ci/woodpecker/push/docs Pipeline was successful Details
ci/woodpecker/push/jfmod Pipeline was successful Details

This commit is contained in:
Johannes Frohnmeyer 2023-09-02 12:56:13 +02:00
parent cbed8270f3
commit c88f9918b3
Signed by: Johannes
GPG Key ID: E76429612C2929F4
24 changed files with 255 additions and 123 deletions

View File

@ -5,6 +5,10 @@ plugins {
allprojects { group = "io.gitlab.jfronny" } allprojects { group = "io.gitlab.jfronny" }
base.archivesName = "respackopts" base.archivesName = "respackopts"
loom {
accessWidenerPath.set(file("src/main/resources/respackopts.accesswidener"))
}
repositories { repositories {
maven("https://maven.vram.io/") { maven("https://maven.vram.io/") {
name = "FREX/Canvas" name = "FREX/Canvas"
@ -21,13 +25,14 @@ repositories {
} }
} }
val fabricVersion = "0.87.0+1.20.1" val fabricVersion = "0.87.1+1.20.2"
val muscriptVersion = "1.4-SNAPSHOT" val muscriptVersion = "1.4-SNAPSHOT"
val modmenuVersion = "7.2.1"
jfMod { jfMod {
minecraftVersion = "1.20.1" minecraftVersion = "23w33a"
yarn("build.10") yarn("build.7")
loaderVersion = "0.14.22" loaderVersion = "0.14.22"
libJfVersion = "3.12.4" libJfVersion = "3.13.0-SNAPSHOT"
modrinth { modrinth {
projectId = "respackopts" projectId = "respackopts"
@ -44,6 +49,7 @@ jfMod {
dependencies { dependencies {
modImplementation("net.fabricmc.fabric-api:fabric-api:$fabricVersion") modImplementation("net.fabricmc.fabric-api:fabric-api:$fabricVersion")
include(modImplementation("io.gitlab.jfronny:muscript:$muscriptVersion")!!) include(modImplementation("io.gitlab.jfronny:muscript:$muscriptVersion")!!)
include(modImplementation("io.gitlab.jfronny:muscript-gson:$muscriptVersion")!!)
modImplementation("io.gitlab.jfronny.libjf:libjf-data-manipulation-v0:${jfMod.libJfVersion.get()}") modImplementation("io.gitlab.jfronny.libjf:libjf-data-manipulation-v0:${jfMod.libJfVersion.get()}")
modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v1:${jfMod.libJfVersion.get()}") modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v1:${jfMod.libJfVersion.get()}")
modImplementation("io.gitlab.jfronny.libjf:libjf-config-ui-tiny-v1:${jfMod.libJfVersion.get()}") modImplementation("io.gitlab.jfronny.libjf:libjf-config-ui-tiny-v1:${jfMod.libJfVersion.get()}")
@ -52,8 +58,8 @@ dependencies {
exclude("net.fabricmc") // required to work around duplicate fabric loaders exclude("net.fabricmc") // required to work around duplicate fabric loaders
} }
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil:${jfMod.libJfVersion.get()}", nofabric) modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil:${jfMod.libJfVersion.get()}", nofabric)
modLocalRuntime("com.terraformersmc:modmenu:7.2.1", nofabric) //modLocalRuntime("com.terraformersmc:modmenu:$modmenuVersion", nofabric) // Temporarily disabled since modmenu doesn't support snapshots
modClientCompileOnly("com.terraformersmc:modmenu:7.2.1", nofabric) modClientCompileOnly("com.terraformersmc:modmenu:$modmenuVersion", nofabric)
modClientCompileOnly("io.vram:frex-fabric:20.0.+") modClientCompileOnly("io.vram:frex-fabric:20.0.+")
modClientCompileOnly("dev.notalpha:dashloader:5.0.0-beta.1+1.20.0") modClientCompileOnly("dev.notalpha:dashloader:5.0.0-beta.1+1.20.0")

View File

@ -88,4 +88,9 @@ Corresponds to version 4.5.0-4.5.1
## v12 ## v12
Corresponds to version 4.6.0 Corresponds to version 4.6.0
- Support for whole numbers (not integers!) - Support for whole numbers (not integers!)
## v13
Unreleased
- Supports readString and runScript methods in muScript expressions

View File

@ -1,6 +1,6 @@
# Debugging # Debugging
If you run into issues with respackopts and cannot find a solution here, If you run into issues with respackopts and cannot find a solution here,
you may contact me through my discord server (look at the mod page) you may contact me directly (details are at the bottom of this page)
## Look at the config file ## Look at the config file
Respackopts stores configurations next to their corresponding resource packs (`some pack.zip.rpo` usually) Respackopts stores configurations next to their corresponding resource packs (`some pack.zip.rpo` usually)

View File

@ -1,6 +1,7 @@
package io.gitlab.jfronny.respackopts; package io.gitlab.jfronny.respackopts;
import com.mojang.brigadier.Command; import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer; import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier; import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
@ -40,7 +41,12 @@ public class RpoClientCommand {
return 1; return 1;
}; };
Command<FabricClientCommandSource> dumpScope = ctx -> { Command<FabricClientCommandSource> dumpScope = ctx -> {
ctx.getSource().sendFeedback(dump(MetaCache.getScope(null).toExpr().toString(), "_root.mu")); ctx.getSource().sendFeedback(dump(MetaCache.getScope(Respackopts.META_VERSION).toExpr().toString(), "_root.mu"));
MetaCache.forEach((id, branch) -> ctx.getSource().sendFeedback(dump(branch.executionScope().getOverrides().toExpr().toString(), branch.packId() + ".mu")));
return 1;
};
Command<FabricClientCommandSource> dumpScopeVersioned = ctx -> {
ctx.getSource().sendFeedback(dump(MetaCache.getScope(IntegerArgumentType.getInteger(ctx, "version")).toExpr().toString(), "_root.mu"));
MetaCache.forEach((id, branch) -> ctx.getSource().sendFeedback(dump(branch.executionScope().getOverrides().toExpr().toString(), branch.packId() + ".mu"))); MetaCache.forEach((id, branch) -> ctx.getSource().sendFeedback(dump(branch.executionScope().getOverrides().toExpr().toString(), branch.packId() + ".mu")));
return 1; return 1;
}; };
@ -52,7 +58,7 @@ public class RpoClientCommand {
Command<FabricClientCommandSource> execute = ctx -> { Command<FabricClientCommandSource> execute = ctx -> {
String snippet = StringArgumentType.getString(ctx, "snippet"); String snippet = StringArgumentType.getString(ctx, "snippet");
try { try {
String result = Parser.parse(snippet, "snippet").asStringExpr().get(MetaCache.getScope(null)); String result = Parser.parse(snippet, "snippet").asStringExpr().get(MetaCache.getScope(IntegerArgumentType.getInteger(ctx, "version")));
ctx.getSource().sendFeedback(Text.translatable("respackopts.snippet.success", result)); ctx.getSource().sendFeedback(Text.translatable("respackopts.snippet.success", result));
} catch (LocationalException | Parser.ParseException e) { } catch (LocationalException | Parser.ParseException e) {
Respackopts.LOGGER.error("Could not execute snippet", e); Respackopts.LOGGER.error("Could not execute snippet", e);
@ -75,10 +81,10 @@ public class RpoClientCommand {
dispatcher.register(literal("rpoc").executes(getVersion) dispatcher.register(literal("rpoc").executes(getVersion)
.then(literal("dump").executes(dumpConfig) .then(literal("dump").executes(dumpConfig)
.then(literal("config").executes(dumpConfig)) .then(literal("config").executes(dumpConfig))
.then(literal("scope").executes(dumpScope)) .then(literal("scope").executes(dumpScope).then(argument("version", IntegerArgumentType.integer(1, Respackopts.META_VERSION)).executes(dumpScopeVersioned)))
.then(literal("glsl").executes(dumpGlsl)) .then(literal("glsl").executes(dumpGlsl))
.then(literal("asset").then(argument("asset", IdentifierArgumentType.identifier()).executes(dumpAsset)))) .then(literal("asset").then(argument("asset", IdentifierArgumentType.identifier()).executes(dumpAsset))))
.then(literal("execute").then(argument("snippet", StringArgumentType.greedyString()).executes(execute))) .then(literal("execute").then(argument("version", IntegerArgumentType.integer(1, Respackopts.META_VERSION)).then(argument("snippet", StringArgumentType.greedyString()).executes(execute))))
.then(literal("version").executes(getVersion)) .then(literal("version").executes(getVersion))
.then(literal("reload").executes(reload))); .then(literal("reload").executes(reload)));
}); });

View File

@ -43,23 +43,6 @@ public class Respackopts implements ModInitializer, SaveHook {
.setPrettyPrinting() .setPrettyPrinting()
.create(); .create();
public static final Scope ROOT_SCOPE = StandardLib.createScope();
static {
ROOT_SCOPE.set("version", args -> {
if (args.size() != 2) throw new IllegalArgumentException("Expected 2 arguments on version but got " + args.size());
VersionPredicate predicate;
try {
predicate = VersionPredicate.parse(args.get(1).asString().getValue());
} catch (VersionParsingException e) {
throw new IllegalArgumentException("Could not parse version predicate", e);
}
return DFinal.of(FabricLoader.getInstance().getModContainer(args.get(0).asString().getValue())
.map(c -> predicate.test(c.getMetadata().getVersion()))
.orElse(false));
});
}
public static final String ID = "respackopts"; public static final String ID = "respackopts";
public static final Logger LOGGER = Logger.forName(ID); public static final Logger LOGGER = Logger.forName(ID);

View File

@ -6,8 +6,10 @@ import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.filters.util.DirRpoResult; import io.gitlab.jfronny.respackopts.filters.util.DirRpoResult;
import io.gitlab.jfronny.respackopts.gson.AttachmentHolder; import io.gitlab.jfronny.respackopts.gson.AttachmentHolder;
import io.gitlab.jfronny.respackopts.model.DirRpo; 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.cache.CachedPackState;
import io.gitlab.jfronny.respackopts.model.enums.PackCapability; import io.gitlab.jfronny.respackopts.model.enums.PackCapability;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.minecraft.resource.*; import net.minecraft.resource.*;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -28,14 +30,15 @@ public enum DirFilterEvents implements UserResourceEvents.Open, UserResourceEven
if (!MetaCache.hasCapability(pack, PackCapability.DirFilter)) return previous; if (!MetaCache.hasCapability(pack, PackCapability.DirFilter)) return previous;
String path = new ResourcePath(type, id).getName(); String path = new ResourcePath(type, id).getName();
List<DirRpo> rpo = findDirRpos(pack, parent(path)); List<DirRpo> rpo = findDirRpos(pack, parent(path));
CacheKey key = MetaCache.getKeyByPack(pack);
RespackoptsFS fs = new RespackoptsFS(pack);
//TODO use pattern matching for switch //TODO use pattern matching for switch
DirRpoResult result = DirRpoResult.compute(path, rpo, MetaCache.getKeyByPack(pack)); DirRpoResult result = DirRpoResult.compute(path, rpo, key, fs);
if (result == DirRpoResult.ORIGINAL) return previous; // Using original file if (result == DirRpoResult.ORIGINAL) return previous; // Using original file
if (result == DirRpoResult.IGNORE) return null; // No fallback if (result == DirRpoResult.IGNORE) return null; // No fallback
// Use fallback // Use fallback
DirRpoResult.Replacement replacement = (DirRpoResult.Replacement) result; DirRpoResult.Replacement replacement = (DirRpoResult.Replacement) result;
ResourcePath rp = new ResourcePath(replacement.toFallback(path)); return fs.open(replacement.toFallback(path));
return pack.open(rp.getType(), rp.getId());
} }
@Override @Override
@ -46,11 +49,13 @@ public enum DirFilterEvents implements UserResourceEvents.Open, UserResourceEven
boolean dirFilterAdditive = MetaCache.hasCapability(pack, PackCapability.DirFilterAdditive); boolean dirFilterAdditive = MetaCache.hasCapability(pack, PackCapability.DirFilterAdditive);
String searchPrefix = type.getDirectory() + "/" + namespace + "/" + prefix; String searchPrefix = type.getDirectory() + "/" + namespace + "/" + prefix;
Set<String> additionalSearched = new HashSet<>(); Set<String> additionalSearched = new HashSet<>();
CacheKey key = MetaCache.getKeyByPack(pack);
RespackoptsFS fs = new RespackoptsFS(pack);
return (identifier, value) -> { return (identifier, value) -> {
String path = path(type, identifier); String path = path(type, identifier);
//TODO use pattern matching for switch //TODO use pattern matching for switch
List<DirRpo> relevantRpos = findDirRpos(pack, parent(path)); List<DirRpo> relevantRpos = findDirRpos(pack, parent(path));
DirRpoResult result = DirRpoResult.compute(path, relevantRpos, MetaCache.getKeyByPack(pack)); DirRpoResult result = DirRpoResult.compute(path, relevantRpos, key, fs);
if (result == DirRpoResult.ORIGINAL) { // Using original file if (result == DirRpoResult.ORIGINAL) { // Using original file
previous.accept(identifier, value); previous.accept(identifier, value);
return; return;
@ -65,8 +70,7 @@ public enum DirFilterEvents implements UserResourceEvents.Open, UserResourceEven
} }
if (!dirFilterAdditive) { if (!dirFilterAdditive) {
// Only return this single result, don't search for others // Only return this single result, don't search for others
ResourcePath rp = new ResourcePath(newPath); previous.accept(identifier, fs.open(newPath));
previous.accept(identifier, pack.open(rp.getType(), rp.getId()));
return; return;
} }
// Find other files in the fallback directory // Find other files in the fallback directory
@ -110,7 +114,9 @@ public enum DirFilterEvents implements UserResourceEvents.Open, UserResourceEven
private List<DirRpo> findDirRpos(ResourcePack pack, String path) { private List<DirRpo> findDirRpos(ResourcePack pack, String path) {
if (path == null) return List.of(); if (path == null) return List.of();
CachedPackState state = MetaCache.getState(MetaCache.getKeyByPack(pack)); CacheKey key = MetaCache.getKeyByPack(pack);
RespackoptsFS fs = new RespackoptsFS(pack);
CachedPackState state = MetaCache.getState(key);
var cache = state.cachedDirRPOs(); var cache = state.cachedDirRPOs();
{ {
@ -122,13 +128,8 @@ public enum DirFilterEvents implements UserResourceEvents.Open, UserResourceEven
List<DirRpo> parentRPOs = findDirRpos(pack, parent(path)); List<DirRpo> parentRPOs = findDirRpos(pack, parent(path));
synchronized (cache) { // This is synchronized as multiple resources might be accessed at the same time, potentially causing a CME here synchronized (cache) { // This is synchronized as multiple resources might be accessed at the same time, potentially causing a CME here
return cache.computeIfAbsent(path, $ -> { return cache.computeIfAbsent(path, $ -> {
ResourcePath rp; String rp = path + "/" + Respackopts.FILE_EXTENSION;
try { InputSupplier<InputStream> is = UserResourceEvents.disable(() -> fs.open(rp));
rp = new ResourcePath(path + "/" + Respackopts.FILE_EXTENSION);
} catch (Exception e) {
return parentRPOs;
}
InputSupplier<InputStream> is = UserResourceEvents.disable(() -> pack.open(rp.getType(), rp.getId()));
if (is == null) return parentRPOs; if (is == null) return parentRPOs;
try (Reader w = new InputStreamReader(is.get())) { try (Reader w = new InputStreamReader(is.get())) {
List<DirRpo> currentRPOs = new LinkedList<>(parentRPOs); List<DirRpo> currentRPOs = new LinkedList<>(parentRPOs);
@ -139,7 +140,7 @@ public enum DirFilterEvents implements UserResourceEvents.Open, UserResourceEven
currentRPOs.add(newRPO); currentRPOs.add(newRPO);
return currentRPOs; return currentRPOs;
} catch (IOException e) { } catch (IOException e) {
Respackopts.LOGGER.error("Couldn't open dir rpo " + rp.getName(), e); Respackopts.LOGGER.error("Couldn't open dir rpo " + rp, e);
} }
return parentRPOs; return parentRPOs;
}); });

View File

@ -4,7 +4,9 @@ import io.gitlab.jfronny.libjf.ResourcePath;
import io.gitlab.jfronny.libjf.data.manipulation.api.UserResourceEvents; import io.gitlab.jfronny.libjf.data.manipulation.api.UserResourceEvents;
import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.filters.util.*; 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.model.enums.PackCapability;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.minecraft.resource.*; import net.minecraft.resource.*;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -25,22 +27,22 @@ public enum FileFilterEvents implements UserResourceEvents.OpenRoot, UserResourc
@Override @Override
public InputSupplier<InputStream> openRoot(String[] fileName, InputSupplier<InputStream> previous, ResourcePack pack) { public InputSupplier<InputStream> openRoot(String[] fileName, InputSupplier<InputStream> previous, ResourcePack pack) {
if (skip(pack)) return previous; if (skip(pack)) return previous;
String path = String.join("/", fileName); return open(previous, pack, 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 @Override
public InputSupplier<InputStream> open(ResourceType type, Identifier id, InputSupplier<InputStream> previous, ResourcePack pack) { public InputSupplier<InputStream> open(ResourceType type, Identifier id, InputSupplier<InputStream> previous, ResourcePack pack) {
if (skip(pack)) return previous; if (skip(pack)) return previous;
String name = new ResourcePath(type, id).getName(); return open(previous, pack, new ResourcePath(type, id).getName());
return switch (probe(previous != null, pack, name)) { }
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 MISSING -> null;
case FALLBACK -> FileFallbackProvider.getReplacement(pack, name); case FALLBACK -> FileFallbackProvider.getReplacement(key, fs, name);
case CONTAINS -> FileExpansionProvider.replace(previous, pack, name); case CONTAINS -> FileExpansionProvider.replace(previous, key, fs, name);
}; };
} }
@ -50,30 +52,28 @@ public enum FileFilterEvents implements UserResourceEvents.OpenRoot, UserResourc
// Therefore, it needs to be added when calling a method that generates a ResourcePath! // Therefore, it needs to be added when calling a method that generates a ResourcePath!
if (skip(pack)) return previous; if (skip(pack)) return previous;
Set<Identifier> ids = new HashSet<>(); Set<Identifier> ids = new HashSet<>();
CacheKey key = MetaCache.getKeyByPack(pack);
RespackoptsFS fs = new RespackoptsFS(pack);
return (identifier, value) -> { return (identifier, value) -> {
// Completion of the path is handled separately here // Completion of the path is handled separately here
String fileName = type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath(); String fileName = type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath();
if (!FileExclusionProvider.fileHidden(pack, fileName) || FileFallbackProvider.fileHasFallback(pack, fileName)) { if (!FileExclusionProvider.fileHidden(key, fs, fileName) || FileFallbackProvider.fileHasFallback(key, fs, fileName)) {
ids.add(identifier); ids.add(identifier);
previous.accept(identifier, open(type, identifier, value, pack)); previous.accept(identifier, open(type, identifier, value, pack));
} }
FileFallbackProvider.addFallbackResources(namespace, type, identifier, pack, ids, previous); FileFallbackProvider.addFallbackResources(namespace, type, identifier, key, fs, ids, previous);
}; };
} }
private ContainsResult probe(boolean previous, ResourcePack pack, String name) { private ContainsResult probe(boolean previous, CacheKey key, RespackoptsFS fs, String name) {
if (previous) { if (previous) {
if (!FileExclusionProvider.fileHidden(pack, name)) return ContainsResult.CONTAINS; if (!FileExclusionProvider.fileHidden(key, fs, name)) return ContainsResult.CONTAINS;
else if (FileFallbackProvider.fileHasFallback(pack, name)) return ContainsResult.FALLBACK; else if (FileFallbackProvider.fileHasFallback(key, fs, name)) return ContainsResult.FALLBACK;
else return ContainsResult.MISSING; else return ContainsResult.MISSING;
} }
else { else {
boolean missing; boolean missing = UserResourceEvents.disable(() -> fs.open(name + Respackopts.FILE_EXTENSION)) == null;
if (name.contains("/")) { if (missing && FileFallbackProvider.fileHasFallback(key, fs, name)) return ContainsResult.FALLBACK;
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; else return ContainsResult.MISSING;
} }
} }

View File

@ -7,6 +7,7 @@ import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.Condition; import io.gitlab.jfronny.respackopts.model.Condition;
import io.gitlab.jfronny.respackopts.model.DirRpo; import io.gitlab.jfronny.respackopts.model.DirRpo;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey; import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.util.MetaCache;
import java.util.List; import java.util.List;
@ -20,10 +21,10 @@ public sealed interface DirRpoResult {
return new Replacement(originalPrefix, fallbackPrefix, version); return new Replacement(originalPrefix, fallbackPrefix, version);
} }
static DirRpoResult compute(String file, List<DirRpo> rpos, CacheKey key) { static DirRpoResult compute(String file, List<DirRpo> rpos, CacheKey key, RespackoptsFS fs) {
int version = MetaCache.getState(key).metadata().version; int version = MetaCache.getMeta(key).version;
if (version < 11) rpos = rpos.isEmpty() ? rpos : List.of(rpos.get(rpos.size() - 1)); if (version < 11) rpos = rpos.isEmpty() ? rpos : List.of(rpos.get(rpos.size() - 1));
LazySupplier<Scope> scope = new LazySupplier<>(() -> MetaCache.getScope(key)); LazySupplier<Scope> scope = new LazySupplier<>(() -> MetaCache.getScope(key, fs));
for (DirRpo rpo : rpos) { for (DirRpo rpo : rpos) {
if (rpo.condition == null) continue; if (rpo.condition == null) continue;
try { try {

View File

@ -4,17 +4,17 @@ import io.gitlab.jfronny.muscript.debug.ObjectGraphPrinter;
import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.Condition; import io.gitlab.jfronny.respackopts.model.Condition;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey; import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.minecraft.resource.ResourcePack; import net.minecraft.resource.ResourcePack;
public class FileExclusionProvider { public class FileExclusionProvider {
public static boolean fileHidden(ResourcePack pack, String file) { public static boolean fileHidden(CacheKey key, RespackoptsFS fs, String file) {
return FileRpoSearchProvider.modifyWithRpo(file, pack, rpo -> { return FileRpoSearchProvider.modifyWithRpo(file, key, fs, rpo -> {
if (rpo.condition == null) if (rpo.condition == null)
return false; return false;
CacheKey key = MetaCache.getKeyByPack(pack);
try { try {
return !rpo.condition.get(MetaCache.getScope(key)); return !rpo.condition.get(MetaCache.getScope(key, fs));
} catch (Condition.ConditionException e) { } catch (Condition.ConditionException e) {
String res = "Could not evaluate condition for " + file + " (pack: " + key.packName() + ")"; String res = "Could not evaluate condition for " + file + " (pack: " + key.packName() + ")";
try { try {

View File

@ -2,9 +2,10 @@ package io.gitlab.jfronny.respackopts.filters.util;
import io.gitlab.jfronny.muscript.ast.StringExpr; import io.gitlab.jfronny.muscript.ast.StringExpr;
import io.gitlab.jfronny.muscript.data.dynamic.Dynamic; import io.gitlab.jfronny.muscript.data.dynamic.Dynamic;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.minecraft.resource.InputSupplier; import net.minecraft.resource.InputSupplier;
import net.minecraft.resource.ResourcePack;
import java.io.*; import java.io.*;
import java.util.Map; import java.util.Map;
@ -18,10 +19,10 @@ public class FileExpansionProvider {
return new ByteArrayInputStream(s.getBytes()); return new ByteArrayInputStream(s.getBytes());
} }
public static InputSupplier<InputStream> replace(InputSupplier<InputStream> inputStream, ResourcePack pack, String file) { public static InputSupplier<InputStream> replace(InputSupplier<InputStream> inputStream, CacheKey key, RespackoptsFS fs, String file) {
return FileRpoSearchProvider.modifyWithRpo(file, pack, rpo -> rpo.expansions == null || rpo.expansions.isEmpty() ? inputStream : () -> { return FileRpoSearchProvider.modifyWithRpo(file, key, fs, rpo -> rpo.expansions == null || rpo.expansions.isEmpty() ? inputStream : () -> {
try (InputStream is = inputStream.get()) { try (InputStream is = inputStream.get()) {
return replace(MetaCache.getScope(MetaCache.getKeyByPack(pack)), is, rpo.expansions); return replace(MetaCache.getScope(key, fs), is, rpo.expansions);
} }
}, inputStream); }, inputStream);
} }

View File

@ -1,7 +1,8 @@
package io.gitlab.jfronny.respackopts.filters.util; package io.gitlab.jfronny.respackopts.filters.util;
import io.gitlab.jfronny.libjf.ResourcePath;
import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import net.minecraft.resource.*; import net.minecraft.resource.*;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -9,25 +10,23 @@ import java.io.InputStream;
import java.util.Set; import java.util.Set;
public class FileFallbackProvider { public class FileFallbackProvider {
public static boolean fileHasFallback(ResourcePack pack, String file) { public static boolean fileHasFallback(CacheKey key, RespackoptsFS fs, String file) {
return FileRpoSearchProvider.modifyWithRpo(file, pack, rpo -> { return FileRpoSearchProvider.modifyWithRpo(file, key, fs, rpo -> {
if (rpo.fallbacks != null) { if (rpo.fallbacks != null) {
for (String s : rpo.fallbacks) { for (String s : rpo.fallbacks) {
ResourcePath tmp = new ResourcePath(s); if (fs.open(s) != null) return true;
if (pack.open(tmp.getType(), tmp.getId()) != null) return true;
} }
} }
return false; return false;
}, false); }, false);
} }
public static InputSupplier<InputStream> getReplacement(ResourcePack pack, String file) { public static InputSupplier<InputStream> getReplacement(CacheKey key, RespackoptsFS fs, String file) {
return FileRpoSearchProvider.modifyWithRpo(file, pack, rpo -> { return FileRpoSearchProvider.modifyWithRpo(file, key, fs, rpo -> {
try { try {
if (rpo.fallbacks != null) { if (rpo.fallbacks != null) {
for (String s : rpo.fallbacks) { for (String s : rpo.fallbacks) {
ResourcePath tmp = new ResourcePath(s); InputSupplier<InputStream> is = fs.open(s);
InputSupplier<InputStream> is = pack.open(tmp.getType(), tmp.getId());
if (is != null) return is; if (is != null) return is;
} }
} }
@ -40,15 +39,15 @@ public class FileFallbackProvider {
}, null); }, null);
} }
public static void addFallbackResources(String namespace, ResourceType type, Identifier identifier, ResourcePack pack, Set<Identifier> ids, ResourcePack.ResultConsumer out) { public static void addFallbackResources(String namespace, ResourceType type, Identifier identifier, CacheKey key, RespackoptsFS fs, Set<Identifier> ids, ResourcePack.ResultConsumer out) {
// 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!
String path = identifier.getPath(); String path = identifier.getPath();
if (FileRpoSearchProvider.isRpo(path)) { if (FileRpoSearchProvider.isRpo(path)) {
String expectedTarget = path.substring(0, path.length() - Respackopts.FILE_EXTENSION.length()); String expectedTarget = path.substring(0, path.length() - Respackopts.FILE_EXTENSION.length());
if (ids.stream().noneMatch(s -> s.getPath().equals(expectedTarget)) && fileHasFallback(pack, type.getDirectory() + "/" + expectedTarget)) { if (ids.stream().noneMatch(s -> s.getPath().equals(expectedTarget)) && fileHasFallback(key, fs, type.getDirectory() + "/" + expectedTarget)) {
Identifier id = new Identifier(namespace, expectedTarget); Identifier id = new Identifier(namespace, expectedTarget);
ids.add(id); ids.add(id);
out.accept(id, pack.open(type, id)); out.accept(id, fs.open(type, id));
} }
} }
} }

View File

@ -1,13 +1,13 @@
package io.gitlab.jfronny.respackopts.filters.util; package io.gitlab.jfronny.respackopts.filters.util;
import io.gitlab.jfronny.libjf.ResourcePath;
import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.gson.AttachmentHolder; import io.gitlab.jfronny.respackopts.gson.AttachmentHolder;
import io.gitlab.jfronny.respackopts.model.FileRpo; import io.gitlab.jfronny.respackopts.model.FileRpo;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.model.cache.CachedPackState; import io.gitlab.jfronny.respackopts.model.cache.CachedPackState;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.minecraft.resource.InputSupplier; import net.minecraft.resource.InputSupplier;
import net.minecraft.resource.ResourcePack;
import java.io.*; import java.io.*;
import java.util.Map; import java.util.Map;
@ -17,23 +17,13 @@ public class FileRpoSearchProvider {
return fileName.endsWith(Respackopts.FILE_EXTENSION); return fileName.endsWith(Respackopts.FILE_EXTENSION);
} }
public static <T> T modifyWithRpo(String fileName, ResourcePack pack, Action<T> action, T defaultValue) { public static <T> T modifyWithRpo(String fileName, CacheKey key, RespackoptsFS fs, Action<T> action, T defaultValue) {
if (isRpo(fileName)) return defaultValue; if (isRpo(fileName)) return defaultValue;
CachedPackState state = MetaCache.getState(MetaCache.getKeyByPack(pack)); CachedPackState state = MetaCache.getState(key);
Map<String, FileRpo> rpoCache = state.cachedFileRPOs(); Map<String, FileRpo> rpoCache = state.cachedFileRPOs();
String rpoPathS = fileName + Respackopts.FILE_EXTENSION; String rpoPathS = fileName + Respackopts.FILE_EXTENSION;
if (rpoCache.containsKey(rpoPathS)) return action.run(rpoCache.get(rpoPathS)); if (rpoCache.containsKey(rpoPathS)) return action.run(rpoCache.get(rpoPathS));
ResourcePath rpoPath = null; InputSupplier<InputStream> is = fs.open(rpoPathS);
InputSupplier<InputStream> is;
if (fileName.contains("/")) {
try {
rpoPath = new ResourcePath(rpoPathS);
is = pack.open(rpoPath.getType(), rpoPath.getId());
} catch (Throwable e) {
Respackopts.LOGGER.error("Could not check file filter status", e);
return defaultValue;
}
} else is = pack.openRoot(rpoPathS);
if (is == null) return defaultValue; if (is == null) return defaultValue;
try (Reader w = new InputStreamReader(is.get())) { try (Reader w = new InputStreamReader(is.get())) {
FileRpo frp = AttachmentHolder.deserialize(state.metadata().version, w, FileRpo.class); FileRpo frp = AttachmentHolder.deserialize(state.metadata().version, w, FileRpo.class);
@ -42,7 +32,7 @@ public class FileRpoSearchProvider {
return action.run(frp); return action.run(frp);
} }
catch (Exception e) { catch (Exception e) {
Respackopts.LOGGER.error("Could not get replacement for " + (rpoPath == null ? fileName : rpoPath.getName()) + " in " + pack.getName(), e); Respackopts.LOGGER.error("Could not get replacement for " + fileName + " in " + state.displayName(), e);
return defaultValue; return defaultValue;
} }
} }

View File

@ -2,19 +2,18 @@ package io.gitlab.jfronny.respackopts.mixin;
import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.Respackopts;
import net.minecraft.resource.FileResourcePackProvider; import net.minecraft.resource.FileResourcePackProvider;
import net.minecraft.resource.ResourcePackProfile;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.nio.file.Files; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.*;
@Mixin(FileResourcePackProvider.class) @Mixin(FileResourcePackProvider.class)
public class FileResourcePackProviderMixin { public class FileResourcePackProviderMixin {
@Inject(method = "getFactory(Ljava/nio/file/Path;Z)Lnet/minecraft/resource/ResourcePackProfile$PackFactory;", at = @At("HEAD"), cancellable = true) //TODO use MixinExtras Wrap instead of redirecting
private static void getFactory(Path path, boolean alwaysStable, CallbackInfoReturnable<ResourcePackProfile.PackFactory> cir) { @Redirect(method = "forEachProfile(Ljava/nio/file/Path;Lnet/minecraft/util/path/SymlinkFinder;ZLjava/util/function/BiConsumer;)V", at = @At(value = "INVOKE", target = "Ljava/nio/file/Files;newDirectoryStream(Ljava/nio/file/Path;)Ljava/nio/file/DirectoryStream;"))
if (Files.isRegularFile(path) && path.getFileName().toString().endsWith(Respackopts.FILE_EXTENSION)) cir.setReturnValue(null); private static DirectoryStream<Path> createFilteredStream(Path dir) throws IOException {
return Files.newDirectoryStream(dir, path -> !(Files.isRegularFile(path) && path.getFileName().toString().endsWith(Respackopts.FILE_EXTENSION)));
} }
} }

View File

@ -50,7 +50,7 @@ public class ResourcePackManagerMixin {
if (pack != null) dataLocation = pack.getParent().resolve(pack.getFileName() + Respackopts.FILE_EXTENSION); if (pack != null) dataLocation = pack.getParent().resolve(pack.getFileName() + Respackopts.FILE_EXTENSION);
else Respackopts.LOGGER.warn("Base path of directory resource pack " + rpi.getName() + " is null. This shouldn't happen!"); else Respackopts.LOGGER.warn("Base path of directory resource pack " + rpi.getName() + " is null. This shouldn't happen!");
} else if (rpi instanceof ZipResourcePack zrp) { } else if (rpi instanceof ZipResourcePack zrp) {
File pack = ((ZipResourcePackAccessor) zrp).getBackingZipFile(); File pack = ((ZipFileWrapperAccessor) ((ZipResourcePackAccessor) zrp).getZipFile()).getFile();
if (pack != null) dataLocation = pack.toPath().getParent().resolve(pack.getName() + Respackopts.FILE_EXTENSION); if (pack != null) dataLocation = pack.toPath().getParent().resolve(pack.getName() + Respackopts.FILE_EXTENSION);
else Respackopts.LOGGER.warn("Base path of zip resource pack " + rpi.getName() + " is null. This shouldn't happen!"); else Respackopts.LOGGER.warn("Base path of zip resource pack " + rpi.getName() + " is null. This shouldn't happen!");
} }

View File

@ -0,0 +1,13 @@
package io.gitlab.jfronny.respackopts.mixin;
import net.minecraft.resource.ZipResourcePack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.io.File;
@Mixin(ZipResourcePack.ZipFileWrapper.class)
public interface ZipFileWrapperAccessor {
@Accessor("file")
File getFile();
}

View File

@ -4,10 +4,8 @@ import net.minecraft.resource.ZipResourcePack;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Accessor;
import java.io.File;
@Mixin(ZipResourcePack.class) @Mixin(ZipResourcePack.class)
public interface ZipResourcePackAccessor { public interface ZipResourcePackAccessor {
@Accessor("backingZipFile") @Accessor("zipFile")
File getBackingZipFile(); ZipResourcePack.ZipFileWrapper getZipFile();
} }

View File

@ -1,9 +1,10 @@
package io.gitlab.jfronny.respackopts.model.cache; package io.gitlab.jfronny.respackopts.model.cache;
import io.gitlab.jfronny.muscript.data.Scope; import io.gitlab.jfronny.muscript.data.Scope;
import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.muscript.data.Script;
import io.gitlab.jfronny.respackopts.model.*; import io.gitlab.jfronny.respackopts.model.*;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch; import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch;
import io.gitlab.jfronny.respackopts.muscript.MuScriptScope;
import java.util.*; import java.util.*;
@ -15,6 +16,8 @@ public record CachedPackState(
PackMeta metadata, PackMeta metadata,
Map<String, FileRpo> cachedFileRPOs, Map<String, FileRpo> cachedFileRPOs,
Map<String, List<DirRpo>> cachedDirRPOs, // Directory RPOs, from outermost to innermost Map<String, List<DirRpo>> cachedDirRPOs, // Directory RPOs, from outermost to innermost
Map<String, Script> cachedScripts, // Scripts, available via runScript
Map<String, String> cachedFiles, // Files, read by readString
Scope executionScope Scope executionScope
) { ) {
public CachedPackState(CacheKey key, PackMeta meta, ConfigBranch branch) { public CachedPackState(CacheKey key, PackMeta meta, ConfigBranch branch) {
@ -26,7 +29,9 @@ public record CachedPackState(
meta, meta,
new HashMap<>(), new HashMap<>(),
new HashMap<>(), new HashMap<>(),
branch.addTo(Respackopts.ROOT_SCOPE.fork()) new HashMap<>(),
new HashMap<>(),
branch.addTo(MuScriptScope.fork(meta.version))
); );
} }
} }

View File

@ -90,7 +90,7 @@ public class ConfigNumericEntry extends ConfigEntry<Double> implements DNumber {
@Override @Override
public CategoryBuilder<?> buildEntry(GuiEntryBuilderParam args) { public CategoryBuilder<?> buildEntry(GuiEntryBuilderParam args) {
double min = this.min == null ? Double.NEGATIVE_INFINITY : this.min; double min = this.min == null ? Double.NEGATIVE_INFINITY : this.min;
double max = this.max == null ? Double.NEGATIVE_INFINITY : this.max; double max = this.max == null ? Double.POSITIVE_INFINITY : this.max;
if (integer) { if (integer) {
return args.builder().value( return args.builder().value(
args.name(), args.name(),

View File

@ -0,0 +1,65 @@
package io.gitlab.jfronny.respackopts.muscript;
import io.gitlab.jfronny.muscript.StandardLib;
import io.gitlab.jfronny.muscript.compiler.Parser;
import io.gitlab.jfronny.muscript.compiler.SourceFS;
import io.gitlab.jfronny.muscript.data.Scope;
import io.gitlab.jfronny.muscript.data.Script;
import io.gitlab.jfronny.muscript.data.dynamic.DList;
import io.gitlab.jfronny.muscript.data.dynamic.Dynamic;
import io.gitlab.jfronny.muscript.data.dynamic.additional.DFinal;
import io.gitlab.jfronny.muscript.gson.GsonLib;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.model.cache.CachedPackState;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.VersionParsingException;
import net.fabricmc.loader.api.metadata.version.VersionPredicate;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import static io.gitlab.jfronny.muscript.data.dynamic.additional.DFinal.of;
public class MuScriptScope {
private static final Scope SCOPE_12;
private static final Scope SCOPE_13;
static {
SCOPE_12 = StandardLib.createScope().set("version", args -> {
if (args.size() != 2) throw new IllegalArgumentException("Expected 2 arguments on version but got " + args.size());
VersionPredicate predicate;
try {
predicate = VersionPredicate.parse(args.get(1).asString().getValue());
} catch (VersionParsingException e) {
throw new IllegalArgumentException("Could not parse version predicate", e);
}
return DFinal.of(FabricLoader.getInstance().getModContainer(args.get(0).asString().getValue())
.map(c -> predicate.test(c.getMetadata().getVersion()))
.orElse(false));
});
SCOPE_13 = GsonLib.addTo(SCOPE_12.fork());
}
public static Scope fork(int version) {
if (version <= 12) return SCOPE_12.fork();
else return SCOPE_13.fork();
}
public static Scope configureFS(Scope scope, CachedPackState state, SourceFS fs) {
int version = state.metadata().version;
if (version <= 12) return scope;
else return scope.set("readString", args -> {
if (args.size() != 1) throw new IllegalArgumentException("Invalid number of arguments for readString: expected 1 but got " + args.size());
return DFinal.of(state.cachedFiles().computeIfAbsent(args.get(0).asString().getValue(), fs::read));
}).set("runScript", args -> {
if (args.isEmpty()) throw new IllegalArgumentException("Invalid number of arguments for evaluateScript: expected 1 or more but got " + args.size());
Script script = state.cachedScripts().computeIfAbsent(
args.get(0).asString().getValue(),
sourceFile -> Parser.parseMultiScript(sourceFile, fs)
);
List<? extends Dynamic> l = args.getValue();
DList innerArgs = of(l.subList(1, l.size()));
return script.bindTo(scope).call(innerArgs);
});
}
}

View File

@ -0,0 +1,42 @@
package io.gitlab.jfronny.respackopts.muscript;
import io.gitlab.jfronny.libjf.ResourcePath;
import io.gitlab.jfronny.muscript.compiler.SourceFS;
import io.gitlab.jfronny.respackopts.Respackopts;
import net.minecraft.resource.*;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.InputStream;
public class RespackoptsFS implements SourceFS {
private final ResourcePack pack;
public RespackoptsFS(ResourcePack pack) {
this.pack = pack;
}
@Override
public @Nullable String read(String file) {
InputSupplier<InputStream> op = open(file);
if (op == null) return null;
try (InputStream is = op.get()) {
return new String(is.readAllBytes());
} catch (IOException e) {
Respackopts.LOGGER.error("Could not open file", e);
return null;
}
}
public @Nullable InputSupplier<InputStream> open(String file) {
String[] segments = file.split("/");
if (segments.length < 3) return pack.openRoot(segments);
ResourcePath path = new ResourcePath(file);
return open(path.getType(), path.getId());
}
public @Nullable InputSupplier<InputStream> open(ResourceType type, Identifier id) {
return pack.open(type, id);
}
}

View File

@ -11,9 +11,12 @@ import io.gitlab.jfronny.respackopts.model.cache.CachedPackState;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode; import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.model.enums.PackCapability; import io.gitlab.jfronny.respackopts.model.enums.PackCapability;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch; import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch;
import io.gitlab.jfronny.respackopts.muscript.MuScriptScope;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.resource.ResourcePack; import net.minecraft.resource.ResourcePack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.*; import java.io.*;
@ -158,9 +161,19 @@ public class MetaCache {
return PACK_STATES.get(key); return PACK_STATES.get(key);
} }
public static Scope getScope(@Nullable CacheKey key) { public static Scope getScope(int version) {
Scope scope = (key == null ? Respackopts.ROOT_SCOPE : MetaCache.getState(key).executionScope()).fork(); Scope scope = MuScriptScope.fork(version);
MetaCache.forEach((id, state) -> { return populate(scope);
}
public static Scope getScope(@NotNull CacheKey key, RespackoptsFS fs) {
CachedPackState state = MetaCache.getState(key);
Scope scope = state.executionScope().fork();
return populate(MuScriptScope.configureFS(scope, state, fs));
}
private static Scope populate(Scope scope) {
forEach((id, state) -> {
if (!scope.has(state.packId())) { if (!scope.has(state.packId())) {
scope.set(state.packId(), state.configBranch()); scope.set(state.packId(), state.configBranch());
} }

View File

@ -30,6 +30,7 @@
"environment": "client" "environment": "client"
} }
], ],
"accessWidener": "respackopts.accesswidener",
"depends": { "depends": {
"fabricloader": ">=0.12.0", "fabricloader": ">=0.12.0",
"fabric-api": "*", "fabric-api": "*",

View File

@ -0,0 +1,3 @@
accessWidener v2 named
accessible class net/minecraft/resource/ZipResourcePack$ZipFileWrapper

View File

@ -7,6 +7,7 @@
"DirectoryResourcePackAccessor", "DirectoryResourcePackAccessor",
"FileResourcePackProviderMixin", "FileResourcePackProviderMixin",
"ResourcePackManagerMixin", "ResourcePackManagerMixin",
"ZipFileWrapperAccessor",
"ZipResourcePackAccessor" "ZipResourcePackAccessor"
], ],
"injectors": { "injectors": {