/// <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 (!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; string metaPath = Path.Combine(dir, "metadata.yaml"); if (File.Exists(metaPath)) { using (StreamReader reader = new StreamReader(metaPath)) meta = EverestModuleMetadata.Parse("", dir, reader); } LoadModDelayed(meta, () => { Content.Crawl(new ContentModMetadata() { PathDirectory = dir }); }); }
/// <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 (!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; // In case the icon appears before the metadata in the .zip, store it temporarily, set it later. Texture2D icon = 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)) meta = EverestModuleMetadata.Parse(archive, "", reader); continue; } if (entry.FileName == "icon.png") { using (Stream stream = entry.ExtractStream()) icon = Texture2D.FromStream(Celeste.Instance.GraphicsDevice, stream); continue; } } } if (meta != null) { if (icon != null) { meta.Icon = icon; } } LoadModDelayed(meta, () => { Content.Crawl(new ContentModMetadata() { PathArchive = archive }); }); }
public static void LoadZip(string archive) { if (!File.Exists(archive)) // Relative path? { archive = Path.Combine(PathMods, archive); } if (!File.Exists(archive)) // It just doesn't exist. { return; } Logger.Log("loader", $"Loading mod .zip: {archive}"); EverestModuleMetadata meta = null; Assembly asm = null; using (ZipFile zip = new ZipFile(archive)) { // In case the icon appears before the metadata in the .zip, store it temporarily. Texture2D icon = null; // First read the metadata, ... foreach (ZipEntry entry in zip.Entries) { if (entry.FileName == "metadata.yaml") { using (MemoryStream stream = entry.ExtractStream()) using (StreamReader reader = new StreamReader(stream)) meta = EverestModuleMetadata.Parse(archive, "", reader); continue; } if (entry.FileName == "icon.png") { using (Stream stream = entry.ExtractStream()) icon = Texture2D.FromStream(Celeste.Instance.GraphicsDevice, stream); continue; } } if (meta != null) { if (icon != null) { meta.Icon = icon; } // ... then check if the dependencies are loaded ... // TODO: Enqueue the mod, reload it on Register of other mods, rechecking if deps loaded. foreach (EverestModuleMetadata dep in meta.Dependencies) { if (!DependencyLoaded(dep)) { Logger.Log("loader", $"Dependency {dep} of mod {meta} not loaded!"); return; } } // ... then add an AssemblyResolve handler for all the .zip-ped libraries AppDomain.CurrentDomain.AssemblyResolve += GenerateModAssemblyResolver(meta); } // ... then handle the assembly ... foreach (ZipEntry entry in zip.Entries) { string entryName = entry.FileName.Replace('\\', '/'); if (meta != null && entryName == meta.DLL) { using (MemoryStream stream = entry.ExtractStream()) { if (meta.Prelinked) { asm = Assembly.Load(stream.GetBuffer()); } else { asm = Relinker.GetRelinkedAssembly(meta, stream); } } } } // ... then tell the Content class to crawl through the zip. // (This also registers the zip for recrawls further down the line.) Content.Crawl(null, archive, zip); } if (meta != null && asm != null) { LoadMod(meta, asm); } }
public static void LoadDir(string dir) { if (!Directory.Exists(dir)) // Relative path? { dir = Path.Combine(PathMods, dir); } if (!Directory.Exists(dir)) // It just doesn't exist. { return; } Logger.Log("loader", $"Loading mod directory: {dir}"); EverestModuleMetadata meta = null; Assembly asm = null; // First read the metadata, ... string metaPath = Path.Combine(dir, "metadata.yaml"); if (File.Exists(metaPath)) { using (StreamReader reader = new StreamReader(metaPath)) meta = EverestModuleMetadata.Parse("", dir, reader); } if (meta != null) { // ... then check if the dependencies are loaded ... foreach (EverestModuleMetadata dep in meta.Dependencies) { if (!DependencyLoaded(dep)) { Logger.Log("loader", $"Dependency {dep} of mod {meta} not loaded!"); return; } } // ... then add an AssemblyResolve handler for all the .zip-ped libraries AppDomain.CurrentDomain.AssemblyResolve += GenerateModAssemblyResolver(meta); } // ... then handle the assembly and all assets. Content.Crawl(null, dir); if (meta == null || !File.Exists(meta.DLL)) { return; } if (meta.Prelinked) { asm = Assembly.LoadFrom(meta.DLL); } else { using (FileStream stream = File.OpenRead(meta.DLL)) asm = Relinker.GetRelinkedAssembly(meta, stream); } if (asm != null) { LoadMod(meta, asm); } }