Respackopts/src/main/java/io/gitlab/jfronny/respackopts/util/MetaCache.java

140 lines
5.9 KiB
Java

package io.gitlab.jfronny.respackopts.util;
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.ThrowingBiConsumer;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.model.enums.PackCapability;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch;
import net.minecraft.resource.ResourcePack;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
public class MetaCache {
//TODO use the resource pack path as a key here
private static final Map<String, ConfigBranch> CONFIG_BRANCH = new HashMap<>(); // pack id -> active config branch
private static final Map<String, PackMeta> PACK_METAS = new HashMap<>(); // pack id -> original pack metadata
private static final Map<String, Path> DATA_LOCATIONS = new HashMap<>(); // pack id -> pack.rpo (config save location)
private static final Map<String, String> DISPLAY_NAME_LOOKUP = new HashMap<>(); // display name -> pack id
private static final Map<String, String> PACK_NAME_LOOKUP = new HashMap<>(); // pack name -> pack id
public static final Map<String, Map<String, DirRpo>> DIR_RPOS = new HashMap<>(); // pack id -> .rpo path -> parsed .rpo
public static final Map<String, Map<String, FileRpo>> FILE_RPOS = new HashMap<>(); // pack id -> .rpo path -> parsed .rpo
public static void clear() {
CONFIG_BRANCH.clear();
PACK_METAS.clear();
DATA_LOCATIONS.clear();
DISPLAY_NAME_LOOKUP.clear();
PACK_NAME_LOOKUP.clear();
DIR_RPOS.clear();
FILE_RPOS.clear();
}
public static void addFromScan(String displayName, String packName, PackMeta meta, Path dataLocation) {
if (Respackopts.META_VERSION > meta.version) {
Respackopts.LOGGER.warn(displayName + " uses an outdated RPO format (" + meta.version + "). Although this is supported, using the latest version (" + Respackopts.META_VERSION + ") is recommended");
}
meta.conf.setVersion(meta.version);
if (meta.version < 5) meta.capabilities.add(PackCapability.DirFilter);
if (CONFIG_BRANCH.containsKey(meta.id))
CONFIG_BRANCH.get(meta.id).sync(meta.conf, ConfigSyncMode.RESPACK_LOAD);
else
CONFIG_BRANCH.put(meta.id, meta.conf.clone());
DISPLAY_NAME_LOOKUP.put(displayName, meta.id);
PACK_NAME_LOOKUP.put(packName, meta.id);
PACK_METAS.put(meta.id, meta);
DIR_RPOS.put(meta.id, new HashMap<>());
FILE_RPOS.put(meta.id, new HashMap<>());
DATA_LOCATIONS.put(meta.id, dataLocation);
if (!dataLocation.startsWith(Respackopts.FALLBACK_CONF_DIR)) {
Path legacyLocation = Respackopts.FALLBACK_CONF_DIR.resolve(meta.id + ".json");
if (Files.exists(legacyLocation) && !Files.exists(dataLocation)) {
try {
Files.move(legacyLocation, dataLocation);
} catch (IOException e) {
Respackopts.LOGGER.error("Could not move data to new location", e);
}
}
}
load(meta.id);
save(meta.id, meta.conf);
}
public static void save() {
if (Respackopts.CONFIG.debugLogs)
Respackopts.LOGGER.info("Saving configs");
for (Map.Entry<String, ConfigBranch> e : CONFIG_BRANCH.entrySet()) {
save(e.getKey(), e.getValue());
}
for (Runnable action : Respackopts.SAVE_ACTIONS) {
action.run();
}
}
private static void save(String id, ConfigBranch branch) {
try (Writer writer = Files.newBufferedWriter(getDataLocation(id))) {
Respackopts.GSON.toJson(branch, writer);
writer.flush();
} catch (IOException ex) {
Respackopts.LOGGER.error("Could not save config", ex);
}
}
public static void load(String id) {
Path q = getDataLocation(id);
if (Files.exists(q)) {
if (Respackopts.CONFIG.debugLogs)
Respackopts.LOGGER.info("Loading configs for: " + id);
try (Reader reader = Files.newBufferedReader(q)) {
ConfigBranch b = Respackopts.GSON.fromJson(reader, ConfigBranch.class);
if (CONFIG_BRANCH.containsKey(id))
CONFIG_BRANCH.get(id).sync(b, ConfigSyncMode.CONF_LOAD);
Respackopts.STAR_SCRIPT.set(Respackopts.sanitizeString(id), b::buildStarscript);
} catch (IOException e) {
Respackopts.LOGGER.error("Failed to load " + id, e);
}
}
}
public static String getId(ResourcePack pack) {
return PACK_NAME_LOOKUP.get(pack.getName());
}
public static PackMeta getMeta(String id) {
return PACK_METAS.get(id);
}
public static @Nullable String getPackIdByDisplayName(String displayName) {
if (!DISPLAY_NAME_LOOKUP.containsKey(displayName)) return null;
return DISPLAY_NAME_LOOKUP.get(displayName);
}
public static ConfigBranch getBranch(String id) {
return CONFIG_BRANCH.get(id);
}
public static Path getDataLocation(String id) {
return DATA_LOCATIONS.get(id);
}
public static boolean hasCapability(ResourcePack pack, PackCapability capability) {
String id = getId(pack);
if (id == null) return false;
return PACK_METAS.get(id).capabilities.contains(capability);
}
public static <TEx extends Exception> void forEach(ThrowingBiConsumer<String, ConfigBranch, TEx> idAndBranchConsumer) throws TEx {
for (Map.Entry<String, ConfigBranch> entry : CONFIG_BRANCH.entrySet()) {
idAndBranchConsumer.accept(entry.getKey(), entry.getValue());
}
}
}