package io.gitlab.jfronny.modsmod; import com.google.gson.Gson; import io.gitlab.jfronny.libjf.config.impl.ConfigHolder; import io.gitlab.jfronny.libjf.unsafe.UltraEarlyInit; import io.gitlab.jfronny.modsmod.builder.JsonBuilder; import io.gitlab.jfronny.modsmod.builder.ModMeta; import io.gitlab.jfronny.modsmod.util.IOUtil; import net.fabricmc.loader.impl.FabricLoaderImpl; import net.fabricmc.loader.impl.metadata.LoaderModMetadata; import net.fabricmc.loader.impl.metadata.ModMetadataParser; import net.fabricmc.loader.impl.metadata.ParseMetadataException; import net.fabricmc.loader.impl.util.FileSystemUtil; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.IOException; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.HashSet; public class ModsMod implements UltraEarlyInit { public static final Logger LOGGER = LogManager.getLogger(ModsMod.MOD_ID); static final HashSet MODS = new HashSet<>(); static final FabricLoaderImpl LOADER = FabricLoaderImpl.INSTANCE; public static final Gson GSON = new Gson(); public static final String MOD_ID = "modsmod"; private static final String CACHE_NAME = MOD_ID + "cache"; @Override public void init() { try { //Load config Path configDir = LOADER.getConfigDir(); Path modsmodCfgFile = ConfigHolder.getConfigs().get(MOD_ID).path; //make sure the modsmodcache dir is ok Path path = configDir.resolve(CACHE_NAME); if (!Files.isDirectory(path)) { if (Files.exists(path)) Files.delete(path); Files.createDirectories(path); } //remove modsmodcache if the cache is outdated try { Path cfgCache = path.resolve("_basecfg"); if (Files.exists(cfgCache)) { if (Files.isRegularFile(cfgCache)) { if (!IOUtil.contentEquals(modsmodCfgFile, cfgCache)) { IOUtil.clearDirectory(path); } } else { IOUtil.clearDirectory(path); } } Files.copy(modsmodCfgFile, cfgCache, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { System.err.println("Failed to validate modsmod config cache, caching will not be available"); e.printStackTrace(); } MODS.clear(); //Generate mods for (int i = 0; i < ModsModConfig.modsCount; i++) { Path f = path.resolve("f" + (i + 1) + ".jar"); boolean exists = Files.exists(f); //Do not load if cached if (exists) { if (ModsModConfig.cache) { MODS.add(new ModMeta(f)); continue; } else Files.delete(f); } try (FileSystem fs = FileSystemUtil.getJarFileSystem(f, true).get()) { Path inf = fs.getPath("META-INF"); Files.createDirectory(inf); Files.writeString(inf.resolve("MANIFEST.MF"), "Manifest-Version: 1.0\n"); JsonBuilder.build(i + 1, ModMeta.getFmj(fs), ModsModConfig.parent); } MODS.add(new ModMeta(f)); System.gc(); } FabricLoaderInterface.synchronize(LOADER); } catch (IOException e) { e.printStackTrace(); } } public static void loadMods() { for (ModMeta meta : MODS) { try { LoaderModMetadata info = ModMetadataParser.parseMetadata(Files.newInputStream(meta.fmj), meta.url.toString(), new ArrayList<>()); FabricLoaderInterface.addMod(LOADER, FabricLoaderInterface.createPlain(meta.rootPath, info, false, new HashSet<>())); } catch (IOException | ParseMetadataException e) { throw new IllegalStateException(e); } } } }