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 CONFIG_BRANCH = new HashMap<>(); // pack id -> active config branch private static final Map PACK_METAS = new HashMap<>(); // pack id -> original pack metadata private static final Map DATA_LOCATIONS = new HashMap<>(); // pack id -> pack.rpo (config save location) private static final Map DISPLAY_NAME_LOOKUP = new HashMap<>(); // display name -> pack id private static final Map PACK_NAME_LOOKUP = new HashMap<>(); // pack name -> pack id public static final Map> DIR_RPOS = new HashMap<>(); // pack id -> .rpo path -> parsed .rpo public static final Map> 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 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 void forEach(ThrowingBiConsumer idAndBranchConsumer) throws TEx { for (Map.Entry entry : CONFIG_BRANCH.entrySet()) { idAndBranchConsumer.accept(entry.getKey(), entry.getValue()); } } }