package io.gitlab.jfronny.modsmod; import me.sargunvohra.mcmods.autoconfig1u.AutoConfig; import me.sargunvohra.mcmods.autoconfig1u.serializer.JanksonConfigSerializer; import net.fabricmc.loader.FabricLoader; import net.fabricmc.loader.discovery.ModCandidate; import net.fabricmc.loader.discovery.ModResolver; import net.fabricmc.loader.discovery.RuntimeModRemapper; import net.fabricmc.loader.launch.common.FabricLauncherBase; import net.fabricmc.loader.metadata.LoaderModMetadata; import net.fabricmc.loader.metadata.ModMetadataParser; import net.fabricmc.loader.metadata.ParseMetadataException; import net.fabricmc.loader.util.FileSystemUtil; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.Collections; import java.util.HashSet; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class PreLaunch { static HashSet m; static FabricLoader loader; public static void prepare() { loader = FabricLoader.INSTANCE; //Load config AutoConfig.register(Cfg.class, JanksonConfigSerializer::new); Cfg cfg = AutoConfig.getConfigHolder(Cfg.class).getConfig(); Path configDir = loader.getConfigDir(); String modsmodCfgFileName = "ModsMod.json5"; //make sure the modsmodcache dir is ok File path = new File(configDir.toFile(), "modsmodcache"); if (!path.isDirectory()) { if (path.exists()) path.delete(); path.mkdir(); } //remove modsmodcache if the cache is outdated try { File cfgCache = new File(path, "_basecfg"); if (cfgCache.exists()) { if (cfgCache.isFile()) { if (!FileUtils.contentEquals(new File(configDir.toFile(), modsmodCfgFileName), cfgCache)) { FileUtils.deleteDirectory(path); path.mkdir(); } } else { FileUtils.deleteDirectory(path); path.mkdir(); } } Files.copy(Paths.get(configDir.toString(), modsmodCfgFileName), cfgCache.toPath(), StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { System.err.println("Failed to validate modsmod config cache, caching will not be available"); e.printStackTrace(); } m = new HashSet<>(); //Generate mods for (int i = 0; i < cfg.modsCount; i++) { File f = new File(path, "f" + (i + 1) + ".jar"); m.add(f); //Do not load if cached if (f.exists()) { if (cfg.cache) continue; else f.delete(); } //Generate jar ZipOutputStream out; try { out = new ZipOutputStream(new FileOutputStream(f)); //META-INF/MANIFEST.MF (java jar file spec) ZipEntry e = new ZipEntry("META-INF/MANIFEST.MF"); out.putNextEntry(e); StringBuilder sb = new StringBuilder(); sb.append("Manifest-Version: 1.0\n"); out.write(sb.toString().getBytes()); out.closeEntry(); //fabric.mod.json (fabric mod metadata) e = new ZipEntry("fabric.mod.json"); out.putNextEntry(e); sb = new StringBuilder(); sb.append("{"); sb.append("\"schemaVersion\": 1,"); sb.append("\"id\": \"modmod_").append(i + 1).append("\","); sb.append("\"version\": \"1.0\","); sb.append("\"name\": \"ModsMod ").append(i + 1).append("\","); //sb.append("\"icon\": \"assets/modsmod/icon_1.png\","); sb.append("\"entrypoints\": {},"); sb.append("\"custom\": {"); if (cfg.parent) { sb.append("\"modmenu:parent\": \"modsmod\""); } sb.append("}"); sb.append("}"); out.write(sb.toString().getBytes()); out.closeEntry(); //Make file available out.close(); } catch (IOException e) { System.err.println("Failed to generate mod!"); e.printStackTrace(); } System.gc(); } FabricLoaderInterface.synchronize(loader); } public static void init() { for (File f : m) { loadMod(loader, f.toPath()); } } private static void loadMod(FabricLoader loader, Path modPath) { ModCandidate candidate = parseMod(modPath); if (loader.isDevelopmentEnvironment()) { candidate = RuntimeModRemapper.remap(Collections.singletonList(candidate), ModResolver.getInMemoryFs()).stream().findFirst().get(); } FabricLoaderInterface.addMod(loader, candidate); FabricLauncherBase.getLauncher().propose(candidate.getOriginUrl()); } private static ModCandidate parseMod(Path modPath) { try { FileSystemUtil.FileSystemDelegate jarFs = FileSystemUtil.getJarFileSystem(modPath, false); Path modJson = jarFs.get().getPath("fabric.mod.json"); LoaderModMetadata info = ModMetadataParser.parseMetadata(FabricLoaderInterface.logger, modJson); return new ModCandidate(info, modPath.toUri().toURL(), 0, true); } catch (IOException | ParseMetadataException e) { throw new IllegalStateException(e); } } }