Use CacheKey/CachedPackState abstractions for MetaCache

This commit is contained in:
Johannes Frohnmeyer 2022-03-27 11:39:01 +02:00
parent dc8fae467b
commit 998056636c
Signed by: Johannes
GPG Key ID: E76429612C2929F4
11 changed files with 124 additions and 78 deletions

View File

@ -2,7 +2,6 @@ package io.gitlab.jfronny.respackopts;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import io.gitlab.jfronny.respackopts.filters.DirFilterEventImpl; import io.gitlab.jfronny.respackopts.filters.DirFilterEventImpl;
import io.gitlab.jfronny.respackopts.filters.FileFilterEventImpl; import io.gitlab.jfronny.respackopts.filters.FileFilterEventImpl;
@ -36,7 +35,6 @@ import net.fabricmc.loader.impl.gui.FabricGuiEntry;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.server.integrated.IntegratedServer; import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.JsonHelper;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -104,14 +102,14 @@ public class Respackopts implements ClientModInitializer {
} }
if (CONFIG.debugLogs) if (CONFIG.debugLogs)
SAVE_ACTIONS.add(() -> LOGGER.info("Save")); SAVE_ACTIONS.add(() -> LOGGER.info("Save"));
SAVE_ACTIONS.add(() -> MetaCache.forEach((dataLocation, branch) -> STAR_SCRIPT.set(sanitizeString(MetaCache.getId(dataLocation)), branch::buildStarScript))); SAVE_ACTIONS.add(() -> MetaCache.forEach((key, state) -> STAR_SCRIPT.set(sanitizeString(state.packId()), state.configBranch()::buildStarScript)));
SAVE_ACTIONS.add(() -> { SAVE_ACTIONS.add(() -> {
if (CONFIG.debugLogs) if (CONFIG.debugLogs)
LOGGER.info("Generating shader code"); LOGGER.info("Generating shader code");
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("#ifndef respackopts_loaded"); sb.append("#ifndef respackopts_loaded");
sb.append("\n#define respackopts_loaded"); sb.append("\n#define respackopts_loaded");
MetaCache.forEach((dataLocation, branch) -> branch.buildShader(sb, sanitizeString(MetaCache.getId(dataLocation)))); MetaCache.forEach((key, state) -> state.configBranch().buildShader(sb, sanitizeString(state.packId())));
sb.append("\n#endif"); sb.append("\n#endif");
shaderImportSource = sb.toString(); shaderImportSource = sb.toString();
}); });

View File

@ -22,7 +22,7 @@ public class DirFilterEventImpl {
return previous.get(); return previous.get();
String path = new ResourcePath(type, id).getName(); String path = new ResourcePath(type, id).getName();
DirRpo rpo = findDirRpo(pack, path); DirRpo rpo = findDirRpo(pack, path);
if (rpo != null && dirHidden(rpo, MetaCache.getId(MetaCache.getDataLocation(pack)), path)) { if (rpo != null && dirHidden(rpo, MetaCache.getId(MetaCache.getKeyByPack(pack)), path)) {
path = findReplacementDir(path, rpo); path = findReplacementDir(path, rpo);
if (path == null) throw new FileNotFoundException(); if (path == null) throw new FileNotFoundException();
ResourcePath rp = new ResourcePath(path); ResourcePath rp = new ResourcePath(path);
@ -42,7 +42,7 @@ public class DirFilterEventImpl {
String path = type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath(); String path = type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath();
DirRpo rpo = findDirRpo(pack, path); DirRpo rpo = findDirRpo(pack, path);
if (rpo != null) { if (rpo != null) {
if (dirHidden(rpo, MetaCache.getId(MetaCache.getDataLocation(pack)), path)) { if (dirHidden(rpo, MetaCache.getId(MetaCache.getKeyByPack(pack)), path)) {
path = findReplacementDir(path, rpo); path = findReplacementDir(path, rpo);
if (path == null) if (path == null)
nextRes.remove(identifier); nextRes.remove(identifier);
@ -70,7 +70,7 @@ public class DirFilterEventImpl {
return previous.get(); return previous.get();
String path = new ResourcePath(type, id).getName(); String path = new ResourcePath(type, id).getName();
DirRpo rpo = findDirRpo(pack, path); DirRpo rpo = findDirRpo(pack, path);
if (rpo != null && dirHidden(rpo, MetaCache.getId(MetaCache.getDataLocation(pack)), path)) { if (rpo != null && dirHidden(rpo, MetaCache.getId(MetaCache.getKeyByPack(pack)), path)) {
path = findReplacementDir(path, rpo); path = findReplacementDir(path, rpo);
if (path == null) if (path == null)
return false; return false;
@ -98,7 +98,7 @@ public class DirFilterEventImpl {
} }
private static DirRpo findDirRpo(ResourcePack pack, String name) { private static DirRpo findDirRpo(ResourcePack pack, String name) {
Map<String, DirRpo> drpReg = MetaCache.DIR_RPOS.get(MetaCache.getDataLocation(pack)); Map<String, DirRpo> drpReg = MetaCache.getState(MetaCache.getKeyByPack(pack)).cachedDirRPOs();
int li = name.lastIndexOf('/'); int li = name.lastIndexOf('/');
if (li <= 0) if (li <= 0)
return null; return null;

View File

@ -11,7 +11,7 @@ public class FileExclusionProvider {
if (rpo.conditions == null) if (rpo.conditions == null)
return false; return false;
try { try {
return !rpo.conditions.evaluate(MetaCache.getId(MetaCache.getDataLocation(pack))); return !rpo.conditions.evaluate(MetaCache.getId(MetaCache.getKeyByPack(pack)));
} catch (RpoFormatException e) { } catch (RpoFormatException e) {
Respackopts.LOGGER.error("Could not evaluate condition " + file, e); Respackopts.LOGGER.error("Could not evaluate condition " + file, e);
return false; return false;

View File

@ -2,6 +2,7 @@ package io.gitlab.jfronny.respackopts.filters.util;
import io.gitlab.jfronny.libjf.ResourcePath; import io.gitlab.jfronny.libjf.ResourcePath;
import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.DirRpo;
import io.gitlab.jfronny.respackopts.model.FileRpo; import io.gitlab.jfronny.respackopts.model.FileRpo;
import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.minecraft.resource.ResourceNotFoundException; import net.minecraft.resource.ResourceNotFoundException;
@ -21,7 +22,7 @@ public class FileRpoSearchProvider {
public static <T> T modifyWithRpo(String fileName, ResourcePack pack, ModifiedGenerator<T> getModified, T defaultValue) { public static <T> T modifyWithRpo(String fileName, ResourcePack pack, ModifiedGenerator<T> getModified, T defaultValue) {
if (FileRpoSearchProvider.isRpo(fileName)) if (FileRpoSearchProvider.isRpo(fileName))
return defaultValue; return defaultValue;
Map<String, FileRpo> frpReg = MetaCache.FILE_RPOS.get(MetaCache.getDataLocation(pack)); Map<String, FileRpo> frpReg = MetaCache.getState(MetaCache.getKeyByPack(pack)).cachedFileRPOs();
String rpPathName = fileName + Respackopts.FILE_EXTENSION; String rpPathName = fileName + Respackopts.FILE_EXTENSION;
if (frpReg.containsKey(rpPathName)) if (frpReg.containsKey(rpPathName))
return getModified.getModified(frpReg.get(rpPathName)); return getModified.getModified(frpReg.get(rpPathName));

View File

@ -55,10 +55,9 @@ public class ModMenuCompat implements ModMenuApi {
.build() .build()
); );
//Pack config screens //Pack config screens
MetaCache.forEach((dataLocation, conf) -> { MetaCache.forEach((key, state) -> {
String id = MetaCache.getId(dataLocation); ConfigCategory config = builder.getOrCreateCategory(new TranslatableText((state.metadata().version >= 5 ? "rpo." : "respackopts.title.") + state.packId()));
ConfigCategory config = builder.getOrCreateCategory(new TranslatableText((MetaCache.getMeta(dataLocation).version >= 5 ? "rpo." : "respackopts.title.") + id)); Respackopts.GUI_FACTORY.buildCategory(state.configBranch(), state.packId(), config::addEntry, agg, entryBuilder, "");
Respackopts.GUI_FACTORY.buildCategory(conf, id, config::addEntry, agg, entryBuilder, "");
}); });
return builder.build(); return builder.build();
} }

View File

@ -1,6 +1,7 @@
package io.gitlab.jfronny.respackopts.mixin; package io.gitlab.jfronny.respackopts.mixin;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.util.MetaCache;
import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.Respackopts;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
@ -30,7 +31,7 @@ public abstract class ResourcePackEntryMixin {
@Inject(at = @At("TAIL"), method = "render(Lnet/minecraft/client/util/math/MatrixStack;IIIIIIIZF)V") @Inject(at = @At("TAIL"), method = "render(Lnet/minecraft/client/util/math/MatrixStack;IIIIIIIZF)V")
private void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta, CallbackInfo info) { private void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta, CallbackInfo info) {
if (this.isSelectable() && MetaCache.getDataLocationByDisplayName(pack.getDisplayName().asString()) != null) { if (this.isSelectable() && MetaCache.getKeyByDisplayName(pack.getDisplayName().asString()) != null) {
int d = mouseX - x; int d = mouseX - x;
d = widget.getRowWidth() - d; d = widget.getRowWidth() - d;
int e = mouseY - y; int e = mouseY - y;
@ -44,7 +45,7 @@ public abstract class ResourcePackEntryMixin {
if (!info.getReturnValue()) { if (!info.getReturnValue()) {
if (this.isSelectable()) { if (this.isSelectable()) {
String displayName = pack.getDisplayName().asString(); String displayName = pack.getDisplayName().asString();
Path dataLocation = MetaCache.getDataLocationByDisplayName(displayName); CacheKey dataLocation = MetaCache.getKeyByDisplayName(displayName);
if (dataLocation != null && rpo$selected) { if (dataLocation != null && rpo$selected) {
info.setReturnValue(true); info.setReturnValue(true);
MinecraftClient c = MinecraftClient.getInstance(); MinecraftClient c = MinecraftClient.getInstance();

View File

@ -1,5 +1,6 @@
package io.gitlab.jfronny.respackopts.mixin; package io.gitlab.jfronny.respackopts.mixin;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.util.MetaCache;
import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.PackMeta; import io.gitlab.jfronny.respackopts.model.PackMeta;
@ -63,7 +64,8 @@ public class ResourcePackManagerMixin {
} }
}); });
for (Path s : toRemove) { for (Path s : toRemove) {
MetaCache.remove(s); CacheKey k = MetaCache.getKeyByDataLocation(s);
if (k != null) MetaCache.remove(k);
} }
MetaCache.save(); MetaCache.save();
} }

View File

@ -0,0 +1,10 @@
package io.gitlab.jfronny.respackopts.model.cache;
import java.nio.file.Path;
public record CacheKey(String displayName, String packName, Path dataLocation) {
@Override
public String toString() {
return "CacheKey{displayName='" + displayName + "', packName='" + packName + "', dataLocation=" + dataLocation + '}';
}
}

View File

@ -0,0 +1,23 @@
package io.gitlab.jfronny.respackopts.model.cache;
import io.gitlab.jfronny.respackopts.model.DirRpo;
import io.gitlab.jfronny.respackopts.model.FileRpo;
import io.gitlab.jfronny.respackopts.model.PackMeta;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch;
import java.util.HashMap;
import java.util.Map;
public record CachedPackState(
String packId,
String displayName,
String packName,
ConfigBranch configBranch,
PackMeta metadata,
Map<String, FileRpo> cachedFileRPOs,
Map<String, DirRpo> cachedDirRPOs
) {
public CachedPackState(CacheKey key, PackMeta meta, ConfigBranch branch) {
this(meta.id, key.displayName(), key.packName(), branch, meta, new HashMap<>(), new HashMap<>());
}
}

View File

@ -2,6 +2,8 @@ package io.gitlab.jfronny.respackopts.model.condition;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
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.model.cache.CachedPackState;
import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.util.MetaCache;
import io.gitlab.jfronny.respackopts.model.ThrowingBiConsumer; import io.gitlab.jfronny.respackopts.model.ThrowingBiConsumer;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch; import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch;
@ -46,10 +48,10 @@ public record RpoBooleanCondition(String name) implements Condition {
} }
} }
AtomicReference<Boolean> result = new AtomicReference<>(null); AtomicReference<Boolean> result = new AtomicReference<>(null);
MetaCache.forEach((ThrowingBiConsumer<Path, ConfigBranch, ? extends RpoFormatException>) (dataLocation, branch) -> { MetaCache.forEach((ThrowingBiConsumer<CacheKey, CachedPackState, ? extends RpoFormatException>) (key, data) -> {
if (Objects.equals(MetaCache.getId(dataLocation), sourcePack)) { if (Objects.equals(MetaCache.getId(key), sourcePack)) {
try { try {
result.set(branch.getBoolean(finalCondition)); result.set(data.configBranch().getBoolean(finalCondition));
} catch (RpoFormatException ex) { } catch (RpoFormatException ex) {
throw new RpoFormatException("Could not get value", ex); throw new RpoFormatException("Could not get value", ex);
} }

View File

@ -1,10 +1,10 @@
package io.gitlab.jfronny.respackopts.util; package io.gitlab.jfronny.respackopts.util;
import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.DirRpo;
import io.gitlab.jfronny.respackopts.model.FileRpo;
import io.gitlab.jfronny.respackopts.model.PackMeta; import io.gitlab.jfronny.respackopts.model.PackMeta;
import io.gitlab.jfronny.respackopts.model.ThrowingBiConsumer; import io.gitlab.jfronny.respackopts.model.ThrowingBiConsumer;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
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;
@ -20,21 +20,18 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class MetaCache { public class MetaCache {
private static final Map<Path, ConfigBranch> CONFIG_BRANCH = new HashMap<>(); // pack.rpo -> active config branch private static final Map<CacheKey, CachedPackState> PACK_STATES = new HashMap<>();
private static final Map<Path, PackMeta> PACK_METAS = new HashMap<>(); // pack.rpo -> original pack metadata private static final Map<String, CacheKey> KEYS_BY_DISPLAY_NAME = new HashMap<>();
private static final Map<Path, String> PACK_IDS = new HashMap<>(); // pack.rpo -> pack id private static final Map<String, CacheKey> KEYS_BY_PACK_NAME = new HashMap<>();
private static final Map<String, Path> DISPLAY_NAME_LOOKUP = new HashMap<>(); // display name -> pack.rpo private static final Map<Path, CacheKey> KEYS_BY_DATA_LOCATION = new HashMap<>();
private static final Map<String, Path> PACK_NAME_LOOKUP = new HashMap<>(); // pack name -> pack.rpo public static void remove(CacheKey key) {
public static final Map<Path, Map<String, DirRpo>> DIR_RPOS = new HashMap<>(); // pack.rpo -> .rpo path -> parsed .rpo CacheKey k;
public static final Map<Path, Map<String, FileRpo>> FILE_RPOS = new HashMap<>(); // pack.rpo -> .rpo path -> parsed .rpo // Remove the key and ones that share a property
public static void remove(Path packRpo) { // Example: if an old pack has the same data location but a different name, it should still be removed
CONFIG_BRANCH.remove(packRpo); if ((k = KEYS_BY_DATA_LOCATION.remove(key.dataLocation())) != null) remove(k);
PACK_METAS.remove(packRpo); if ((k = KEYS_BY_PACK_NAME.remove(key.packName())) != null) remove(k);
PACK_IDS.remove(packRpo); if ((k = KEYS_BY_DISPLAY_NAME.remove(key.displayName())) != null) remove(k);
//DISPLAY_NAME_LOOKUP PACK_STATES.remove(key);
//PACK_NAME_LOOKUP
DIR_RPOS.remove(packRpo);
FILE_RPOS.remove(packRpo);
} }
public static void addFromScan(String displayName, String packName, PackMeta meta, Path dataLocation) { public static void addFromScan(String displayName, String packName, PackMeta meta, Path dataLocation) {
@ -43,17 +40,23 @@ public class MetaCache {
} }
meta.conf.setVersion(meta.version); meta.conf.setVersion(meta.version);
if (meta.version < 5) meta.capabilities.add(PackCapability.DirFilter); if (meta.version < 5) meta.capabilities.add(PackCapability.DirFilter);
remove(dataLocation); // Reuse the existing branch with a RESPACK_LOAD sync if present
if (CONFIG_BRANCH.containsKey(dataLocation)) ConfigBranch branch;
CONFIG_BRANCH.get(dataLocation).sync(meta.conf, ConfigSyncMode.RESPACK_LOAD); if (KEYS_BY_DATA_LOCATION.containsKey(dataLocation)) {
else branch = getState(KEYS_BY_DATA_LOCATION.get(dataLocation)).configBranch();
CONFIG_BRANCH.put(dataLocation, meta.conf.clone()); branch.sync(meta.conf, ConfigSyncMode.RESPACK_LOAD);
DISPLAY_NAME_LOOKUP.put(displayName, dataLocation); } else {
PACK_NAME_LOOKUP.put(packName, dataLocation); branch = meta.conf.clone();
PACK_METAS.put(dataLocation, meta); }
DIR_RPOS.put(dataLocation, new HashMap<>()); // Register the key and state in the relevant maps
FILE_RPOS.put(dataLocation, new HashMap<>()); CacheKey key = new CacheKey(displayName, packName, dataLocation);
PACK_IDS.put(dataLocation, meta.id); CachedPackState state = new CachedPackState(key, meta, branch);
remove(key);
PACK_STATES.put(key, state);
KEYS_BY_DISPLAY_NAME.put(key.displayName(), key);
KEYS_BY_PACK_NAME.put(key.packName(), key);
KEYS_BY_DATA_LOCATION.put(key.dataLocation(), key);
// Move old configs to the new location
if (!dataLocation.startsWith(Respackopts.FALLBACK_CONF_DIR)) { if (!dataLocation.startsWith(Respackopts.FALLBACK_CONF_DIR)) {
Path legacyLocation = Respackopts.FALLBACK_CONF_DIR.resolve(meta.id + ".json"); Path legacyLocation = Respackopts.FALLBACK_CONF_DIR.resolve(meta.id + ".json");
if (Files.exists(legacyLocation) && !Files.exists(dataLocation)) { if (Files.exists(legacyLocation) && !Files.exists(dataLocation)) {
@ -64,15 +67,15 @@ public class MetaCache {
} }
} }
} }
load(dataLocation); load(key);
save(dataLocation, meta.conf); save(dataLocation, meta.conf);
} }
public static void save() { public static void save() {
if (Respackopts.CONFIG.debugLogs) if (Respackopts.CONFIG.debugLogs)
Respackopts.LOGGER.info("Saving configs"); Respackopts.LOGGER.info("Saving configs");
for (Map.Entry<Path, ConfigBranch> e : CONFIG_BRANCH.entrySet()) { for (Map.Entry<CacheKey, CachedPackState> e : PACK_STATES.entrySet()) {
save(e.getKey(), e.getValue()); save(e.getKey().dataLocation(), e.getValue().configBranch());
} }
for (Runnable action : Respackopts.SAVE_ACTIONS) { for (Runnable action : Respackopts.SAVE_ACTIONS) {
action.run(); action.run();
@ -88,59 +91,66 @@ public class MetaCache {
} }
} }
public static void load(Path dataLocation) { public static void load(CacheKey key) {
if (Files.exists(dataLocation)) { if (Files.exists(key.dataLocation())) {
if (Respackopts.CONFIG.debugLogs) if (Respackopts.CONFIG.debugLogs)
Respackopts.LOGGER.info("Loading configs for: " + dataLocation); Respackopts.LOGGER.info("Loading configs for: " + key);
try (Reader reader = Files.newBufferedReader(dataLocation)) { try (Reader reader = Files.newBufferedReader(key.dataLocation())) {
ConfigBranch b = Respackopts.GSON.fromJson(reader, ConfigBranch.class); ConfigBranch b = Respackopts.GSON.fromJson(reader, ConfigBranch.class);
if (CONFIG_BRANCH.containsKey(dataLocation)) if (PACK_STATES.containsKey(key))
CONFIG_BRANCH.get(dataLocation).sync(b, ConfigSyncMode.CONF_LOAD); getBranch(key).sync(b, ConfigSyncMode.CONF_LOAD);
Respackopts.STAR_SCRIPT.set(Respackopts.sanitizeString(getId(dataLocation)), b::buildStarScript); Respackopts.STAR_SCRIPT.set(Respackopts.sanitizeString(getId(key)), b::buildStarScript);
} catch (IOException e) { } catch (IOException e) {
Respackopts.LOGGER.error("Failed to load " + dataLocation, e); Respackopts.LOGGER.error("Failed to load " + key, e);
} }
} }
} }
public static Path getDataLocation(ResourcePack pack) { public static PackMeta getMeta(CacheKey key) {
return PACK_NAME_LOOKUP.get(pack.getName()); return getState(key).metadata();
} }
public static PackMeta getMeta(Path dataLocation) { public static @Nullable CacheKey getKeyByPack(ResourcePack pack) {
return PACK_METAS.get(dataLocation); return KEYS_BY_PACK_NAME.get(pack.getName());
} }
public static @Nullable Path getDataLocationByDisplayName(String displayName) { public static @Nullable CacheKey getKeyByDisplayName(String displayName) {
if (!DISPLAY_NAME_LOOKUP.containsKey(displayName)) return null; return KEYS_BY_DISPLAY_NAME.get(displayName);
return DISPLAY_NAME_LOOKUP.get(displayName);
} }
public static ConfigBranch getBranch(Path dataLocation) { public static @Nullable CacheKey getKeyByDataLocation(Path dataLocation) {
return CONFIG_BRANCH.get(dataLocation); return KEYS_BY_DATA_LOCATION.get(dataLocation);
} }
public static String getId(Path dataLocation) { public static ConfigBranch getBranch(CacheKey key) {
return PACK_IDS.get(dataLocation); return getState(key).configBranch();
}
public static String getId(CacheKey key) {
return getState(key).packId();
}
public static CachedPackState getState(CacheKey key) {
return PACK_STATES.get(key);
} }
public static boolean hasCapability(ResourcePack pack, PackCapability capability) { public static boolean hasCapability(ResourcePack pack, PackCapability capability) {
Path dataLocation = getDataLocation(pack); CacheKey key = getKeyByPack(pack);
if (dataLocation == null) return false; if (key == null) return false;
if (!PACK_METAS.containsKey(dataLocation)) { if (!PACK_STATES.containsKey(key)) {
StringBuilder sb = new StringBuilder("Could not get pack with \""); StringBuilder sb = new StringBuilder("Could not get pack with \"");
sb.append(dataLocation); sb.append(key);
sb.append("\" (available: "); sb.append("\" (available: ");
for (Path path : PACK_METAS.keySet()) { for (CacheKey path : PACK_STATES.keySet()) {
sb.append(path).append(", "); sb.append(path).append(", ");
} }
throw new NullPointerException(sb.substring(0, sb.length() - 2) + ')'); throw new NullPointerException(sb.substring(0, sb.length() - 2) + ')');
} }
return PACK_METAS.get(dataLocation).capabilities.contains(capability); return getMeta(key).capabilities.contains(capability);
} }
public static <TEx extends Exception> void forEach(ThrowingBiConsumer<Path, ConfigBranch, TEx> idAndBranchConsumer) throws TEx { public static <TEx extends Exception> void forEach(ThrowingBiConsumer<CacheKey, CachedPackState, TEx> idAndBranchConsumer) throws TEx {
for (Map.Entry<Path, ConfigBranch> entry : CONFIG_BRANCH.entrySet()) { for (Map.Entry<CacheKey, CachedPackState> entry : PACK_STATES.entrySet()) {
idAndBranchConsumer.accept(entry.getKey(), entry.getValue()); idAndBranchConsumer.accept(entry.getKey(), entry.getValue());
} }
} }