package io.gitlab.jfronny.resclone; import com.google.gson.Gson; import io.gitlab.jfronny.resclone.data.PackMetaLoaded; import io.gitlab.jfronny.resclone.api.RescloneApi; import io.gitlab.jfronny.resclone.api.RescloneEntry; import io.gitlab.jfronny.resclone.data.PackMetaUnloaded; import io.gitlab.jfronny.resclone.data.RescloneException; import io.gitlab.jfronny.resclone.fetchers.PackFetcher; import io.gitlab.jfronny.resclone.processors.PackProcessor; import io.gitlab.jfronny.resclone.processors.RemoveEmptyProcessor; import io.gitlab.jfronny.resclone.processors.RootPathProcessor; import net.fabricmc.api.ModInitializer; import net.fabricmc.loader.api.FabricLoader; import java.io.IOException; import java.net.URI; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; public class Resclone implements ModInitializer, RescloneApi { public static final Set conf = new LinkedHashSet<>(); public static final Map fetcherInstances = new LinkedHashMap<>(); public static final Set processors = new LinkedHashSet<>(); public static final Set downloadedPacks = new LinkedHashSet<>(); public static final Gson gson = new Gson(); public static final String MOD_ID = "resclone"; public static PackUrlCache urlCache; @Override public void onInitialize() { System.out.println("[resclone] Beginning init, will download packs"); urlCache = new PackUrlCache(getConfigPath().resolve("urlCache.properties")); conf.clear(); fetcherInstances.clear(); processors.clear(); downloadedPacks.clear(); addProcessor(new RootPathProcessor()); //This should be run before any other processor to make sure the path is valid for (RescloneEntry entry : FabricLoader.getInstance().getEntrypoints(MOD_ID, RescloneEntry.class)) { try { entry.init(this); } catch (RescloneException e) { e.printStackTrace(); } } addProcessor(new RemoveEmptyProcessor()); reload(); System.out.println("[resclone] Completed"); } @Override public void addFetcher(PackFetcher fetcher) { fetcherInstances.put(fetcher.getSourceTypeName(), fetcher); } @Override public void addProcessor(PackProcessor processor) { processors.add(processor); } @Override public void addPack(String fetcher, String pack, String name) { addPack(fetcher, pack, name, false); } @Override public void addPack(String fetcher, String pack, String name, boolean forceRedownload) { conf.add(new PackMetaUnloaded(fetcher, pack, name, forceRedownload)); } @Override public void reload() { //Get paths from patchers. Downloading is implemented in PackFetcher to allow for unconsidered sources Set metas = new LinkedHashSet<>(); //Download for (PackMetaUnloaded s : conf) { try { if (!fetcherInstances.containsKey(s.fetcher)) throw new RescloneException("Invalid fetcher: " + s.fetcher); Path cacheDir = getConfigPath().resolve("cache"); PackMetaLoaded p; try { //Download PackFetcher.Result fr = fetcherInstances.get(s.fetcher).get(s.source, cacheDir, s.forceDownload); p = new PackMetaLoaded(fr.downloadPath, s.name); metas.add(p); if (fr.freshDownload) { //Process Map props = new HashMap<>(); props.put("create", "false"); URI zipfile = URI.create("jar:" + p.zipPath.toUri().toString()); try (FileSystem zipfs = FileSystems.newFileSystem(zipfile, props)) { for (PackProcessor processor : processors) { processor.process(zipfs); } } catch (Throwable e) { e.printStackTrace(); } } } catch (Throwable e) { throw new RescloneException("Failed to download pack", e); } } catch (Throwable e) { System.err.println("Encountered issue while preparing " + s.name); e.printStackTrace(); } } //Set variable urlCache.save(); downloadedPacks.clear(); downloadedPacks.addAll(metas); } @Override public Path getConfigPath() { Path configPath = FabricLoader.getInstance().getConfigDir().resolve("resclone"); if (!Files.isDirectory(configPath.resolve("cache"))) { try { Files.createDirectories(configPath.resolve("cache")); } catch (IOException e) { e.printStackTrace(); } } return configPath; } }