/// <summary> /// Create a new OMOD as a <see cref="MemoryStream"/>. /// </summary> /// <param name="options">Creation options to use.</param> /// <returns></returns> public static MemoryStream CreateOMOD(OMODCreationOptions options) { var ms = new MemoryStream(); using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true, Encoding.UTF8)) { void WriteStringToArchive(string name, string content) { var entry = archive.CreateEntry(name, options.OMODCompressionLevel); using var entryStream = entry.Open(); using var bw = new BinaryWriter(entryStream); bw.Write(content); } if (options.Readme != null) { WriteStringToArchive("readme", options.Readme); } if (options.Script != null) { WriteStringToArchive("script", $"{(char) options.ScriptType}{options.Script}"); } if (options.Image != null) { var entry = archive.CreateEntry("image", options.OMODCompressionLevel); using var entryStream = entry.Open(); options.Image.Save(entryStream, options.Image.RawFormat); } { var config = archive.CreateEntry("config", options.OMODCompressionLevel); using var configStream = config.Open(); using var bw = new BinaryWriter(configStream); bw.Write((byte)4); bw.Write(options.Name); bw.Write(options.Version.Major); bw.Write(options.Version.Minor); bw.Write(options.Author); bw.Write(options.Email); bw.Write(options.Website); bw.Write(options.Description); bw.Write(DateTime.Now.ToBinary()); bw.Write((byte)options.CompressionType); bw.Write(options.Version.Build); } void WriteFilesToArchive(string name, IEnumerable <OMODCreationFile> files) { CompressionHandler.CompressFiles(files, options.CompressionType, options.SevenZipCompressionLevel, options.ZipCompressionLevel, out var crcStream, out var compressedStream); //Entries cannot be created while previously created entries are still open { var crcEntry = archive.CreateEntry($"{name}.crc", options.OMODCompressionLevel); using var crcEntryStream = crcEntry.Open(); crcStream.CopyTo(crcEntryStream); crcStream.Dispose(); } { var dataEntry = archive.CreateEntry(name, CompressionLevel.NoCompression); using var dataEntryStream = dataEntry.Open(); compressedStream.CopyTo(dataEntryStream); compressedStream.Dispose(); } } if (options.DataFiles != null) { WriteFilesToArchive("data", options.DataFiles); } if (options.PluginFiles != null) { WriteFilesToArchive("plugins", options.PluginFiles); } } ms.Position = 0; return(ms); }
public static void CreateOMOD(OMODCreationOptions ops, string omodFileName) { Utils.Info($"Creating OMOD to {omodFileName}"); if (File.Exists(omodFileName)) { throw new OMODFrameworkException($"The provided omodFileName {omodFileName} already exists!"); } using (var zipStream = new ZipOutputStream(File.Open(omodFileName, FileMode.CreateNew))) using (var omodStream = new BinaryWriter(zipStream)) { ZipEntry ze; zipStream.SetLevel(ZipHandler.GetCompressionLevel(ops.OMODCompressionLevel)); if (!string.IsNullOrWhiteSpace(ops.Readme)) { Utils.Debug("Writing readme to OMOD"); ze = new ZipEntry("readme"); zipStream.PutNextEntry(ze); omodStream.Write(ops.Readme); omodStream.Flush(); } if (!string.IsNullOrWhiteSpace(ops.Script)) { Utils.Debug("Writing script to OMOD"); ze = new ZipEntry("script"); zipStream.PutNextEntry(ze); omodStream.Write(ops.Script); omodStream.Flush(); } if (!string.IsNullOrWhiteSpace(ops.Image)) { Utils.Debug("Writing image to OMOD"); ze = new ZipEntry("image"); zipStream.PutNextEntry(ze); try { using (var fs = File.OpenRead(ops.Image)) { CompressionHandler.WriteStreamToZip(omodStream, fs); omodStream.Flush(); } } catch (Exception e) { throw new OMODFrameworkException($"There was an exception while trying to read the image at {ops.Image}!\n{e}"); } } Utils.Debug("Writing config to OMOD"); ze = new ZipEntry("config"); zipStream.PutNextEntry(ze); omodStream.Write(Framework.Settings.CurrentOMODVersion); omodStream.Write(ops.Name); omodStream.Write(ops.MajorVersion); omodStream.Write(ops.MinorVersion); omodStream.Write(ops.Author); omodStream.Write(ops.Email); omodStream.Write(ops.Website); omodStream.Write(ops.Description); omodStream.Write(DateTime.Now.ToBinary()); omodStream.Write((byte)ops.CompressionType); omodStream.Write(ops.BuildVersion); omodStream.Flush(); FileStream dataCompressed; Stream dataInfo; if (ops.ESPs.Count > 0) { Utils.Debug("Writing plugins.crc to OMOD"); //TODO: find out why OBMM calls GC.Collect here ze = new ZipEntry("plugins.crc"); zipStream.PutNextEntry(ze); CompressionHandler.CompressFiles(ops.ESPs, ops.ESPPaths, out dataCompressed, out dataInfo, ops.CompressionType, ops.DataFileCompressionLevel); CompressionHandler.WriteStreamToZip(omodStream, dataInfo); omodStream.Flush(); zipStream.SetLevel(0); Utils.Debug("Writing plugins to OMOD"); ze = new ZipEntry("plugins"); zipStream.PutNextEntry(ze); CompressionHandler.WriteStreamToZip(omodStream, dataCompressed); omodStream.Flush(); zipStream.SetLevel(ZipHandler.GetCompressionLevel(ops.OMODCompressionLevel)); dataCompressed.Close(); dataInfo.Close(); } if (ops.DataFiles.Count > 0) { Utils.Debug("Writing data.crc to OMOD"); //TODO: find out why OBMM calls GC.Collect here ze = new ZipEntry("data.crc"); zipStream.PutNextEntry(ze); CompressionHandler.CompressFiles(ops.DataFiles, ops.DataFilePaths, out dataCompressed, out dataInfo, ops.CompressionType, ops.DataFileCompressionLevel); CompressionHandler.WriteStreamToZip(omodStream, dataInfo); omodStream.Flush(); zipStream.SetLevel(0); Utils.Debug("Writing data to OMOD"); ze = new ZipEntry("data"); zipStream.PutNextEntry(ze); CompressionHandler.WriteStreamToZip(omodStream, dataCompressed); omodStream.Flush(); zipStream.SetLevel(ZipHandler.GetCompressionLevel(ops.OMODCompressionLevel)); dataCompressed.Close(); dataInfo.Close(); } zipStream.Finish(); } Utils.Info("Finished OMOD creation"); }
/// <summary> /// Create a new OMOD and write to disk. /// </summary> /// <param name="options">Creation options to use.</param> /// <param name="output">Output path.</param> public static void CreateOMOD(OMODCreationOptions options, string output) { using var ms = CreateOMOD(options); using var fs = File.Open(output, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); ms.CopyTo(fs); }