public void SetCurrentInstanceByPath(string path) { var matchingGames = knownGames .Where(g => g.GameInFolder(new DirectoryInfo(path))) .ToList(); switch (matchingGames.Count) { case 0: throw new NotKSPDirKraken(path); case 1: GameInstance ksp = new GameInstance( matchingGames.First(), path, "custom", User); if (ksp.Valid) { CurrentInstance = ksp; } else { throw new NotKSPDirKraken(ksp.GameDir()); } break; default: // TODO: Prompt user to choose break; } }
private string[] rowItems(GameInstance instance, bool includeGame, bool includePlayTime) { var list = new List <string> { !instance.Valid ? string.Format(Properties.Resources.ManageGameInstancesNameColumnInvalid, instance.Name) : !(_manager.CurrentInstance?.Equals(instance) ?? false) && instance.IsMaybeLocked ? string.Format(Properties.Resources.ManageGameInstancesNameColumnLocked, instance.Name) : instance.Name }; if (includeGame) { list.Add(instance.game.ShortName); } list.Add(FormatVersion(instance.Version())); if (includePlayTime) { list.Add(instance.playTime?.ToString() ?? ""); } list.Add(instance.GameDir().Replace('/', Path.DirectorySeparatorChar)); return(list.ToArray()); }
/// <summary> /// Clones an existing KSP installation. /// </summary> /// <param name="existingInstance">The KSP instance to clone.</param> /// <param name="newName">The name for the new instance.</param> /// <param name="newPath">The path where the new instance should be located.</param> /// <exception cref="InstanceNameTakenKraken">Thrown if the instance name is already in use.</exception> /// <exception cref="NotKSPDirKraken">Thrown by AddInstance() if created instance is not valid, e.g. if something went wrong with copying.</exception> /// <exception cref="DirectoryNotFoundKraken">Thrown by CopyDirectory() if directory doesn't exist. Should never be thrown here.</exception> /// <exception cref="PathErrorKraken">Thrown by CopyDirectory() if the target folder already exists and is not empty.</exception> /// <exception cref="IOException">Thrown by CopyDirectory() if something goes wrong during the process.</exception> public void CloneInstance(GameInstance existingInstance, string newName, string newPath) { if (HasInstance(newName)) { throw new InstanceNameTakenKraken(newName); } if (!existingInstance.Valid) { throw new NotKSPDirKraken(existingInstance.GameDir(), "The specified instance is not a valid KSP instance."); } log.Debug("Copying directory."); Utilities.CopyDirectory(existingInstance.GameDir(), newPath, true); // Add the new instance to the config GameInstance new_instance = new GameInstance(existingInstance.game, newPath, newName, User); AddInstance(new_instance); }
private static string FindDownloadsPath(GameInstance gameInst) { foreach (string p in downloadPaths) { if (!string.IsNullOrEmpty(p) && Directory.Exists(p)) { return(p); } } return(gameInst.GameDir()); }
/// <summary> /// Adds a KSP instance to config. /// Returns the resulting KSP object. /// </summary> public GameInstance AddInstance(GameInstance ksp_instance) { if (ksp_instance.Valid) { string name = ksp_instance.Name; instances.Add(name, ksp_instance); Configuration.SetRegistryToInstances(instances); } else { throw new NotKSPDirKraken(ksp_instance.GameDir()); } return(ksp_instance); }
public void IsGameDir() { var game = new KerbalSpaceProgram(); // Our test data directory should be good. Assert.IsTrue(game.GameInFolder(new DirectoryInfo(TestData.good_ksp_dir()))); // As should our copied folder. Assert.IsTrue(game.GameInFolder(new DirectoryInfo(ksp_dir))); // And the one from our KSP instance. Assert.IsTrue(game.GameInFolder(new DirectoryInfo(ksp.GameDir()))); // All these ones should be bad. foreach (string dir in TestData.bad_ksp_dirs()) { Assert.IsFalse(game.GameInFolder(new DirectoryInfo(dir))); } }
/// <summary> /// Initialize the compatible game versions dialog /// </summary> /// <param name="inst">Game instance</param> /// <param name="centerScreen">true to center the dialog on the screen, false to center on the parent</param> public CompatibleGameVersionsDialog(GameInstance inst, bool centerScreen) { this._inst = inst; InitializeComponent(); if (centerScreen) { StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; } List <GameVersion> compatibleVersions = inst.GetCompatibleVersions(); GameVersionLabel.Text = inst.Version()?.ToString() ?? Properties.Resources.CompatibleGameVersionsDialogNone; GameLocationLabel.Text = inst.GameDir().Replace('/', Path.DirectorySeparatorChar); List <GameVersion> knownVersions = inst.game.KnownVersions; List <GameVersion> majorVersionsList = CreateMajorVersionsList(knownVersions); List <GameVersion> compatibleVersionsLeftOthers = new List <GameVersion>(compatibleVersions); compatibleVersionsLeftOthers.RemoveAll((el) => knownVersions.Contains(el) || majorVersionsList.Contains(el)); SortAndAddVersionsToList(compatibleVersionsLeftOthers, compatibleVersions); SortAndAddVersionsToList(majorVersionsList, compatibleVersions); SortAndAddVersionsToList(knownVersions, compatibleVersions); }
/// <summary> /// User is done. Start cloning or faking, depending on the clicked radio button. /// Close the window if everything went right. /// </summary> private async void buttonOK_Click(object sender, EventArgs e) { string newName = textBoxNewName.Text; string newPath = textBoxNewPath.Text; // Do some basic checks. if (String.IsNullOrWhiteSpace(newName)) { user.RaiseError(Properties.Resources.CloneFakeKspDialogEnterName); return; } if (String.IsNullOrWhiteSpace(newPath)) { user.RaiseError(Properties.Resources.CloneFakeKspDialogEnterPath); return; } // Show progress bar and deactivate controls. progressBar.Style = ProgressBarStyle.Marquee; progressBar.Show(); foreach (Control ctrl in this.Controls) { ctrl.Enabled = false; } // Clone the specified instance. // Done in a new task to not block the GUI thread. if (radioButtonClone.Checked) { user.RaiseMessage(Properties.Resources.CloneFakeKspDialogCloningInstance); try { await Task.Run(() => { GameInstance sourceInstance = manager.Instances.Values .FirstOrDefault(i => i.GameDir() == textBoxClonePath.Text); GameInstance instanceToClone = new GameInstance( sourceInstance.game, textBoxClonePath.Text, "irrelevant", user ); if (instanceToClone.Valid) { manager.CloneInstance(instanceToClone, newName, newPath); } else { throw new NotKSPDirKraken(instanceToClone.GameDir()); } }); } catch (InstanceNameTakenKraken) { user.RaiseError(Properties.Resources.CloneFakeKspDialogNameAlreadyUsed); reactivateDialog(); return; } catch (NotKSPDirKraken kraken) { user.RaiseError(string.Format(Properties.Resources.CloneFakeKspDialogInstanceNotValid, kraken.path)); reactivateDialog(); return; } catch (PathErrorKraken kraken) { user.RaiseError(string.Format(Properties.Resources.CloneFakeKspDialogDestinationNotEmpty, kraken.path)); reactivateDialog(); return; } catch (IOException ex) { user.RaiseError(string.Format(Properties.Resources.CloneFakeKspDialogCloneFailed, ex.Message)); reactivateDialog(); return; } catch (Exception ex) { user.RaiseError(string.Format(Properties.Resources.CloneFakeKspDialogCloneFailed, ex.Message)); reactivateDialog(); return; } if (checkBoxSetAsDefault.Checked) { manager.SetAutoStart(newName); } if (checkBoxSwitchInstance.Checked) { manager.SetCurrentInstance(newName); } user.RaiseMessage(Properties.Resources.CloneFakeKspDialogSuccessfulClone); DialogResult = DialogResult.OK; this.Close(); } // Create a new dummy instance. // Also in a separate task. else if (radioButtonFake.Checked) { GameVersion GameVersion = GameVersion.Parse(comboBoxGameVersion.Text); Dictionary <DLC.IDlcDetector, GameVersion> dlcs = new Dictionary <DLC.IDlcDetector, GameVersion>(); if (!String.IsNullOrWhiteSpace(textBoxMHDlcVersion.Text) && textBoxMHDlcVersion.Text.ToLower() != "none") { if (GameVersion.TryParse(textBoxMHDlcVersion.Text, out GameVersion ver)) { dlcs.Add(new DLC.MakingHistoryDlcDetector(), ver); } else { user.RaiseError(Properties.Resources.CloneFakeKspDialogDlcVersionMalformatted, "Making History"); reactivateDialog(); return; } } if (!String.IsNullOrWhiteSpace(textBoxBGDlcVersion.Text) && textBoxBGDlcVersion.Text.ToLower() != "none") { if (GameVersion.TryParse(textBoxBGDlcVersion.Text, out GameVersion ver)) { dlcs.Add(new DLC.BreakingGroundDlcDetector(), ver); } else { user.RaiseError(Properties.Resources.CloneFakeKspDialogDlcVersionMalformatted, "Breaking Ground"); reactivateDialog(); return; } } user.RaiseMessage(Properties.Resources.CloneFakeKspDialogCreatingInstance); try { await Task.Run(() => { manager.FakeInstance(new KerbalSpaceProgram(), newName, newPath, GameVersion, dlcs); }); } catch (InstanceNameTakenKraken) { user.RaiseError(Properties.Resources.CloneFakeKspDialogNameAlreadyUsed); reactivateDialog(); return; } catch (BadInstallLocationKraken) { user.RaiseError(Properties.Resources.CloneFakeKspDialogDestinationNotEmpty, newPath); reactivateDialog(); return; } catch (Exception ex) { user.RaiseError(string.Format(Properties.Resources.CloneFakeKspDialogFakeFailed, ex.Message)); reactivateDialog(); return; } if (checkBoxSetAsDefault.Checked) { manager.SetAutoStart(newName); } if (checkBoxSwitchInstance.Checked) { manager.SetCurrentInstance(newName); } user.RaiseMessage(Properties.Resources.CloneFakeKspDialogSuccessfulCreate); DialogResult = DialogResult.OK; this.Close(); } }
/// <summary> /// Given an open zipfile, returns all files that would be installed /// for this stanza. /// /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null. /// /// Throws a BadInstallLocationKraken if the install stanza targets an /// unknown install location (eg: not GameData, Ships, etc) /// /// Throws a BadMetadataKraken if the stanza resulted in no files being returned. /// </summary> /// <exception cref="BadInstallLocationKraken">Thrown when the installation path is not valid according to the spec.</exception> public List <InstallableFile> FindInstallableFiles(ZipFile zipfile, GameInstance ksp) { string installDir; var files = new List <InstallableFile>(); // Normalize the path before doing everything else string install_to = CKANPathUtils.NormalizePath(this.install_to); // The installation path cannot contain updirs if (install_to.Contains("/../") || install_to.EndsWith("/..")) { throw new BadInstallLocationKraken("Invalid installation path: " + install_to); } if (ksp == null) { installDir = null; } else if (install_to == ksp.game.PrimaryModDirectoryRelative || install_to.StartsWith($"{ksp.game.PrimaryModDirectoryRelative}/")) { // The installation path can be either "GameData" or a sub-directory of "GameData" string subDir = install_to.Substring(ksp.game.PrimaryModDirectoryRelative.Length); // remove "GameData" subDir = subDir.StartsWith("/") ? subDir.Substring(1) : subDir; // remove a "/" at the beginning, if present // Add the extracted subdirectory to the path of KSP's GameData installDir = CKANPathUtils.NormalizePath(ksp.game.PrimaryModDirectory(ksp) + "/" + subDir); } else { switch (install_to) { case "GameRoot": installDir = ksp.GameDir(); break; default: if (ksp.game.AllowInstallationIn(install_to, out string path)) { installDir = ksp.ToAbsoluteGameDir(path); } else { throw new BadInstallLocationKraken("Unknown install_to " + install_to); } break; } } EnsurePattern(); // `find` is supposed to match the "topmost" folder. Find it. var shortestMatch = find == null ? (int?)null : zipfile.Cast <ZipEntry>() .Select(entry => inst_pattern.Match(entry.Name.Replace('\\', '/'))) .Where(match => match.Success) .DefaultIfEmpty() .Min(match => match?.Index); // O(N^2) solution, as we're walking the zipfile for each stanza. // Surely there's a better way, although this is fast enough we may not care. foreach (ZipEntry entry in zipfile) { // Skips dirs and things not prescribed by our install stanza. if (!IsWanted(entry.Name, shortestMatch)) { continue; } // Prepare our file info. InstallableFile file_info = new InstallableFile { source = entry, makedir = false, destination = null }; // If we have a place to install it, fill that in... if (installDir != null) { // Get the full name of the file. // Update our file info with the install location file_info.destination = TransformOutputName( ksp.game, entry.Name, installDir, @as); file_info.makedir = AllowDirectoryCreation( ksp.game, ksp?.ToRelativeGameDir(file_info.destination) ?? file_info.destination); } files.Add(file_info); } // If we have no files, then something is wrong! (KSP-CKAN/CKAN#93) if (files.Count == 0) { // We have null as the first argument here, because we don't know which module we're installing throw new BadMetadataKraken(null, String.Format("No files found matching {0} to install!", DescribeMatch())); } return(files); }