/// <summary> /// Load a mod from a directory at runtime. /// </summary> /// <param name="dir">The path to the mod directory.</param> public static void LoadDir(string dir) { if (!Flags.SupportRuntimeMods) { Logger.Log(LogLevel.Warn, "loader", "Loader disabled!"); return; } if (!Directory.Exists(dir)) // Relative path? { dir = Path.Combine(PathMods, dir); } if (!Directory.Exists(dir)) // It just doesn't exist. { return; } Logger.Log(LogLevel.Verbose, "loader", $"Loading mod directory: {dir}"); EverestModuleMetadata meta = null; EverestModuleMetadata[] multimetas = null; string metaPath = Path.Combine(dir, "metadata.yaml"); if (File.Exists(metaPath)) { using (StreamReader reader = new StreamReader(metaPath)) { try { meta = YamlHelper.Deserializer.Deserialize <EverestModuleMetadata>(reader); meta.PathDirectory = dir; meta.PostParse(); } catch (Exception e) { Logger.Log(LogLevel.Warn, "loader", $"Failed parsing metadata.yaml in {dir}: {e}"); FilesWithMetadataLoadFailures.Add(dir); } } } metaPath = Path.Combine(dir, "multimetadata.yaml"); if (!File.Exists(metaPath)) { metaPath = Path.Combine(dir, "everest.yaml"); } if (!File.Exists(metaPath)) { metaPath = Path.Combine(dir, "everest.yml"); } if (File.Exists(metaPath)) { using (StreamReader reader = new StreamReader(metaPath)) { try { if (!reader.EndOfStream) { multimetas = YamlHelper.Deserializer.Deserialize <EverestModuleMetadata[]>(reader); foreach (EverestModuleMetadata multimeta in multimetas) { multimeta.PathDirectory = dir; multimeta.PostParse(); } } } catch (Exception e) { Logger.Log(LogLevel.Warn, "loader", $"Failed parsing everest.yaml in {dir}: {e}"); FilesWithMetadataLoadFailures.Add(dir); } } } FileSystemModContent contentMeta = new FileSystemModContent(dir); EverestModuleMetadata contentMetaParent = null; Action contentCrawl = () => { if (contentMeta == null) { return; } if (contentMetaParent != null) { contentMeta.Mod = contentMetaParent; contentMeta.Name = contentMetaParent.Name; } OnCrawlMod?.Invoke(dir, contentMetaParent); Content.Crawl(contentMeta); contentMeta = null; }; if (multimetas != null) { foreach (EverestModuleMetadata multimeta in multimetas) { multimeta.Multimeta = multimetas; if (contentMetaParent == null) { contentMetaParent = multimeta; } LoadModDelayed(multimeta, contentCrawl); } } else { if (meta == null) { meta = new EverestModuleMetadata() { Name = "_dir_" + Path.GetFileName(dir), VersionString = "0.0.0-dummy", PathDirectory = dir }; meta.PostParse(); } contentMetaParent = meta; LoadModDelayed(meta, contentCrawl); } }
/// <summary> /// Load a mod from a .zip archive at runtime. /// </summary> /// <param name="archive">The path to the mod .zip archive.</param> public static void LoadZip(string archive) { if (!Flags.SupportRuntimeMods) { Logger.Log(LogLevel.Warn, "loader", "Loader disabled!"); return; } if (!File.Exists(archive)) // Relative path? Let's just make it absolute. { archive = Path.Combine(PathMods, archive); } if (!File.Exists(archive)) // It just doesn't exist. { return; } Logger.Log(LogLevel.Verbose, "loader", $"Loading mod .zip: {archive}"); EverestModuleMetadata meta = null; EverestModuleMetadata[] multimetas = null; using (ZipFile zip = new ZipFile(archive)) { foreach (ZipEntry entry in zip.Entries) { if (entry.FileName == "metadata.yaml") { using (MemoryStream stream = entry.ExtractStream()) using (StreamReader reader = new StreamReader(stream)) { try { meta = YamlHelper.Deserializer.Deserialize <EverestModuleMetadata>(reader); meta.PathArchive = archive; meta.PostParse(); } catch (Exception e) { Logger.Log(LogLevel.Warn, "loader", $"Failed parsing metadata.yaml in {archive}: {e}"); FilesWithMetadataLoadFailures.Add(archive); } } continue; } if (entry.FileName == "multimetadata.yaml" || entry.FileName == "everest.yaml" || entry.FileName == "everest.yml") { using (MemoryStream stream = entry.ExtractStream()) using (StreamReader reader = new StreamReader(stream)) { try { if (!reader.EndOfStream) { multimetas = YamlHelper.Deserializer.Deserialize <EverestModuleMetadata[]>(reader); foreach (EverestModuleMetadata multimeta in multimetas) { multimeta.PathArchive = archive; multimeta.PostParse(); } } } catch (Exception e) { Logger.Log(LogLevel.Warn, "loader", $"Failed parsing everest.yaml in {archive}: {e}"); FilesWithMetadataLoadFailures.Add(archive); } } continue; } } } ZipModContent contentMeta = new ZipModContent(archive); EverestModuleMetadata contentMetaParent = null; Action contentCrawl = () => { if (contentMeta == null) { return; } if (contentMetaParent != null) { contentMeta.Mod = contentMetaParent; contentMeta.Name = contentMetaParent.Name; } OnCrawlMod?.Invoke(archive, contentMetaParent); Content.Crawl(contentMeta); contentMeta = null; }; if (multimetas != null) { foreach (EverestModuleMetadata multimeta in multimetas) { multimeta.Multimeta = multimetas; if (contentMetaParent == null) { contentMetaParent = multimeta; } LoadModDelayed(multimeta, contentCrawl); } } else { if (meta == null) { meta = new EverestModuleMetadata() { Name = "_zip_" + Path.GetFileNameWithoutExtension(archive), VersionString = "0.0.0-dummy", PathArchive = archive }; meta.PostParse(); } contentMetaParent = meta; LoadModDelayed(meta, contentCrawl); } }