private void InstallMod(ExtendedMod mod) { DebugWrite($"[INSTALL] {mod.ModName}"); var extractionDirectory = System.IO.Path.Combine(_installBase.DownloadsDirectory, Path.GetFileNameWithoutExtension(mod.FileName)); var archivePath = mod.FilePath; var installPath = System.IO.Path.Combine(_installBase.InstallDirectory, _installBase.ModpackHeader.Name, "mods", mod.ModName); if (mod.InstallParameters != null) { var selections = mod.InstallParameters .GroupBy(e => e.SourceLocation) .ToDictionary(e => e.Key); _archiveContents.ExtractAll(archivePath, e => selections.ContainsKey(e) ? Path.Combine(installPath, selections[e].First().TargetLocation.Substring(1)) : null); // Some mods write the same file to two locations and the extractor // doesn't support this, so we'll copy the file around a bit. foreach (var selection in selections.Where(s => s.Value.Count() > 1)) { var from = Path.Combine(installPath, selection.Value.First().TargetLocation.Substring(1)); foreach (var e in selection.Value.Skip(1)) { var to = Path.Combine(installPath, e.TargetLocation.Substring(1)); if (!Directory.Exists(Path.GetDirectoryName(to))) { Directory.CreateDirectory(Path.GetDirectoryName(to)); } if (to != from) { File.Copy(from, to, true); } } } } // Write the meta.ini var metaPath = Path.Combine(installPath, "meta.ini"); File.WriteAllText(metaPath, "[General]\n" + $"gameName={mod.TargetGame}\n" + $"version={mod.Version}\n" + $"installationFile={mod.FilePath.Replace(@"\", @"\\")}\n" + $"repository={mod.Repository}\n" + $"modId={mod.ModId}\n\n" + "[installedFiles]\n" + $"1\\modId={mod.ModId}\n" + $"1\\fileId={mod.FileId}"); return; }