Example #1
0
 public void Setup()
 {
     ksp_dir  = TestData.NewTempDir();
     nullUser = new NullUser();
     CKAN.Utilities.CopyDirectory(TestData.good_ksp_dir(), ksp_dir, true);
     ksp = new CKAN.GameInstance(new KerbalSpaceProgram(), ksp_dir, "test", nullUser);
 }
Example #2
0
        public void FakeInstance_ValidArgumentsWithDLCs_ManagerHasValidInstance()
        {
            string      name      = "testname";
            GameVersion mhVersion = GameVersion.Parse("1.1.0");
            GameVersion bgVersion = GameVersion.Parse("1.0.0");
            string      tempdir   = TestData.NewTempDir();
            GameVersion version   = GameVersion.Parse("1.7.1");

            Dictionary <CKAN.DLC.IDlcDetector, GameVersion> dlcs = new Dictionary <CKAN.DLC.IDlcDetector, GameVersion>()
            {
                { new CKAN.DLC.MakingHistoryDlcDetector(), mhVersion },
                { new CKAN.DLC.BreakingGroundDlcDetector(), bgVersion }
            };

            manager.FakeInstance(new KerbalSpaceProgram(), name, tempdir, version, dlcs);
            CKAN.GameInstance newKSP = new CKAN.GameInstance(new KerbalSpaceProgram(), tempdir, name, new NullUser());
            CKAN.DLC.MakingHistoryDlcDetector  mhDetector = new CKAN.DLC.MakingHistoryDlcDetector();
            CKAN.DLC.BreakingGroundDlcDetector bgDetector = new CKAN.DLC.BreakingGroundDlcDetector();

            Assert.IsTrue(manager.HasInstance(name));
            Assert.IsTrue(mhDetector.IsInstalled(newKSP, out string _, out UnmanagedModuleVersion detectedMhVersion));
            Assert.IsTrue(bgDetector.IsInstalled(newKSP, out string _, out UnmanagedModuleVersion detectedBgVersion));
            Assert.IsTrue(detectedMhVersion == new UnmanagedModuleVersion(mhVersion.ToString()));
            Assert.IsTrue(detectedBgVersion == new UnmanagedModuleVersion(bgVersion.ToString()));

            // Tidy up.
            CKAN.RegistryManager.Instance(newKSP).ReleaseLock();
            System.IO.Directory.Delete(tempdir, true);
        }
Example #3
0
        public void Constructor_NullMainCompatVer_NoCrash()
        {
            // Arrange
            string       gamedir  = TestData.NewTempDir();
            string       ckandir  = Path.Combine(gamedir, "CKAN");
            string       buildid  = Path.Combine(gamedir, "buildID.txt");
            string       readme   = Path.Combine(gamedir, "readme.txt");
            string       jsonpath = Path.Combine(ckandir, "compatible_ksp_versions.json");
            const string compatible_ksp_versions_json = @"{
                ""VersionOfKspWhenWritten"": null,
                ""CompatibleGameVersions"":   [""1.4""]
            }";

            // Generate a valid game dir except for missing buildID.txt and readme.txt
            CKAN.Utilities.CopyDirectory(TestData.good_ksp_dir(), gamedir, true);
            File.Delete(buildid);
            File.Delete(readme);

            // Save GameDir/CKAN/compatible_ksp_versions.json
            Directory.CreateDirectory(ckandir);
            File.WriteAllText(jsonpath, compatible_ksp_versions_json);

            // Act & Assert
            Assert.DoesNotThrow(() =>
            {
                CKAN.GameInstance my_ksp = new CKAN.GameInstance(new KerbalSpaceProgram(), gamedir, "null-compat-ver-test", nullUser);
            });

            Directory.Delete(gamedir, true);
        }
Example #4
0
        public void CloneInstance_BadInstance_ThrowsNotKSPDirKraken()
        {
            string badName = "badInstance";
            string tempdir = TestData.NewTempDir();

            CKAN.GameInstance badKSP = new CKAN.GameInstance(new KerbalSpaceProgram(), TestData.bad_ksp_dirs().First(), "badDir", new NullUser());

            Assert.Throws <NotKSPDirKraken>(() =>
                                            manager.CloneInstance(badKSP, badName, tempdir));
            Assert.IsFalse(manager.HasInstance(badName));

            // Tidy up
            System.IO.Directory.Delete(tempdir, true);
        }
Example #5
0
        // We require our constructor to be private so we can
        // enforce this being an instance (via Instance() above)
        private RegistryManager(string path, GameInstance ksp)
        {
            this.ksp = ksp;

            this.path    = Path.Combine(path, "registry.json");
            lockfilePath = Path.Combine(path, "registry.locked");

            // Create a lock for this registry, so we cannot touch it again.
            if (!GetLock())
            {
                log.DebugFormat("Unable to acquire registry lock: {0}", lockfilePath);
                throw new RegistryInUseKraken(lockfilePath);
            }

            try
            {
                LoadOrCreate();
            }
            catch
            {
                // Clean up the lock file
                Dispose(false);
                throw;
            }

            // We don't cause an inconsistency error to stop the registry from being loaded,
            // because then the user can't do anything to correct it. However we're
            // sure as hell going to complain if we spot one!
            try
            {
                registry.CheckSanity();
            }
            catch (InconsistentKraken kraken)
            {
                log.ErrorFormat("Loaded registry with inconsistencies:\r\n\r\n{0}", kraken.InconsistenciesPretty);
            }
        }
        /// <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);
        }
Example #7
0
 /// <summary>
 /// Initialize the row
 /// </summary>
 public PlayTimeRow(string name, GameInstance instance)
 {
     Name     = name;
     PlayTime = instance.playTime;
     path     = TimeLog.GetPath(instance.CkanDir());
 }
Example #8
0
        /// <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>
        /// Create a new fake KSP instance
        /// </summary>
        /// <param name="game">The game of the new instance.</param>
        /// <param name="newName">The name for the new instance.</param>
        /// <param name="newPath">The location of the new instance.</param>
        /// <param name="version">The version of the new instance. Should have a build number.</param>
        /// <param name="dlcs">The IDlcDetector implementations for the DLCs that should be faked and the requested dlc version as a dictionary.</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 a write operation didn't complete for whatever reason.</exception>
        public void FakeInstance(IGame game, string newName, string newPath, GameVersion version, Dictionary <DLC.IDlcDetector, GameVersion> dlcs = null)
        {
            TxFileManager fileMgr = new TxFileManager();

            using (TransactionScope transaction = CkanTransaction.CreateTransactionScope())
            {
                if (HasInstance(newName))
                {
                    throw new InstanceNameTakenKraken(newName);
                }


                if (!version.InBuildMap(game))
                {
                    throw new BadGameVersionKraken(String.Format("The specified KSP version is not a known version: {0}", version.ToString()));
                }
                if (Directory.Exists(newPath) && (Directory.GetFiles(newPath).Length != 0 || Directory.GetDirectories(newPath).Length != 0))
                {
                    throw new BadInstallLocationKraken("The specified folder already exists and is not empty.");
                }

                log.DebugFormat("Creating folder structure and text files at {0} for KSP version {1}", Path.GetFullPath(newPath), version.ToString());

                // Create a KSP root directory, containing a GameData folder, a buildID.txt/buildID64.txt and a readme.txt
                fileMgr.CreateDirectory(newPath);
                fileMgr.CreateDirectory(Path.Combine(newPath, "GameData"));
                fileMgr.CreateDirectory(Path.Combine(newPath, "Ships"));
                fileMgr.CreateDirectory(Path.Combine(newPath, "Ships", "VAB"));
                fileMgr.CreateDirectory(Path.Combine(newPath, "Ships", "SPH"));
                fileMgr.CreateDirectory(Path.Combine(newPath, "Ships", "@thumbs"));
                fileMgr.CreateDirectory(Path.Combine(newPath, "Ships", "@thumbs", "VAB"));
                fileMgr.CreateDirectory(Path.Combine(newPath, "Ships", "@thumbs", "SPH"));
                fileMgr.CreateDirectory(Path.Combine(newPath, "saves"));
                fileMgr.CreateDirectory(Path.Combine(newPath, "saves", "scenarios"));
                fileMgr.CreateDirectory(Path.Combine(newPath, "saves", "training"));

                // Don't write the buildID.txts if we have no build, otherwise it would be -1.
                if (version.IsBuildDefined)
                {
                    fileMgr.WriteAllText(Path.Combine(newPath, "buildID.txt"), String.Format("build id = {0}", version.Build));
                    fileMgr.WriteAllText(Path.Combine(newPath, "buildID64.txt"), String.Format("build id = {0}", version.Build));
                }

                // Create the readme.txt WITHOUT build number.
                fileMgr.WriteAllText(Path.Combine(newPath, "readme.txt"), String.Format("Version {0}", new GameVersion(version.Major, version.Minor, version.Patch).ToString()));

                // Create the needed folder structure and the readme.txt for DLCs that should be simulated.
                if (dlcs != null)
                {
                    foreach (KeyValuePair <DLC.IDlcDetector, GameVersion> dlc in dlcs)
                    {
                        DLC.IDlcDetector dlcDetector = dlc.Key;
                        GameVersion      dlcVersion  = dlc.Value;

                        if (!dlcDetector.AllowedOnBaseVersion(version))
                        {
                            throw new WrongGameVersionKraken(
                                      version,
                                      String.Format("KSP version {0} or above is needed for {1} DLC.",
                                                    dlcDetector.ReleaseGameVersion,
                                                    dlcDetector.IdentifierBaseName
                                                    ));
                        }

                        string dlcDir = Path.Combine(newPath, dlcDetector.InstallPath());
                        fileMgr.CreateDirectory(dlcDir);
                        fileMgr.WriteAllText(
                            Path.Combine(dlcDir, "readme.txt"),
                            String.Format("Version {0}", dlcVersion));
                    }
                }

                // Add the new instance to the config
                GameInstance new_instance = new GameInstance(game, newPath, newName, User, false);
                AddInstance(new_instance);
                transaction.Complete();
            }
        }
Example #10
0
        /// <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);
        }
Example #11
0
        /// <summary>
        /// Download and update the local CKAN meta-info.
        /// Optionally takes a URL to the zipfile repo to download.
        /// </summary>
        public static RepoUpdateResult UpdateAllRepositories(RegistryManager registry_manager, GameInstance ksp, NetModuleCache cache, IUser user)
        {
            SortedDictionary <string, Repository> sortedRepositories = registry_manager.registry.Repositories;

            user.RaiseProgress("Checking for updates", 0);
            if (sortedRepositories.Values.All(repo => !string.IsNullOrEmpty(repo.last_server_etag) && repo.last_server_etag == Net.CurrentETag(repo.uri)))
            {
                user.RaiseProgress("Already up to date", 100);
                user.RaiseMessage("No changes since last update");
                return(RepoUpdateResult.NoChanges);
            }
            List <CkanModule> allAvail = new List <CkanModule>();
            int index = 0;

            foreach (KeyValuePair <string, Repository> repository in sortedRepositories)
            {
                user.RaiseProgress($"Updating {repository.Value.name}",
                                   10 + 80 * index / sortedRepositories.Count);
                SortedDictionary <string, int> downloadCounts;
                string            newETag;
                List <CkanModule> avail = UpdateRegistry(repository.Value.uri, ksp, user, out downloadCounts, out newETag);
                registry_manager.registry.SetDownloadCounts(downloadCounts);
                if (avail == null)
                {
                    // Report failure if any repo fails, rather than losing half the list.
                    // UpdateRegistry will have alerted the user to specific errors already.
                    return(RepoUpdateResult.Failed);
                }
                else
                {
                    // Merge all the lists
                    allAvail.AddRange(avail);
                    repository.Value.last_server_etag = newETag;
                    user.RaiseMessage("Updated {0} ({1} modules)",
                                      repository.Value.name, avail.Count);
                }
                ++index;
            }
            // Save allAvail to the registry if we found anything
            if (allAvail.Count > 0)
            {
                user.RaiseProgress("Saving modules to registry", 90);
                using (var transaction = CkanTransaction.CreateTransactionScope())
                {
                    // Save our changes.
                    registry_manager.registry.SetAllAvailable(allAvail);
                    registry_manager.Save(enforce_consistency: false);
                    transaction.Complete();
                }

                ShowUserInconsistencies(registry_manager.registry, user);

                List <CkanModule> metadataChanges = GetChangedInstalledModules(registry_manager.registry);
                if (metadataChanges.Count > 0)
                {
                    HandleModuleChanges(metadataChanges, user, ksp, cache, registry_manager);
                }

                // Registry.CompatibleModules is slow, just return success,
                // caller can check it if it's really needed
                user.RaiseProgress("Registry saved", 100);
                user.RaiseMessage("Repositories updated");
                return(RepoUpdateResult.Updated);
            }
            else
            {
                // Return failure
                user.RaiseMessage("No modules found!");
                return(RepoUpdateResult.Failed);
            }
        }
Example #12
0
        /// <summary>
        /// Resolve differences between installed and available metadata for given ModuleInstaller
        /// </summary>
        /// <param name="metadataChanges">List of modules that changed</param>
        /// <param name="user">Object for user interaction callbacks</param>
        /// <param name="ksp">Game instance</param>
        /// <param name="cache">Cacne object for mod downloads</param>
        /// <param name="registry_manager">Manager that holds our game instances</param>
        private static void HandleModuleChanges(List <CkanModule> metadataChanges, IUser user, GameInstance ksp, NetModuleCache cache, RegistryManager registry_manager)
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < metadataChanges.Count; i++)
            {
                CkanModule module = metadataChanges[i];
                sb.AppendLine(string.Format("- {0} {1}", module.identifier, module.version));
            }

            if (user.RaiseYesNoDialog(string.Format(@"The following mods have had their metadata changed since last update:

{0}
You should reinstall them in order to preserve consistency with the repository.

Do you wish to reinstall now?", sb)))
            {
                ModuleInstaller installer = ModuleInstaller.GetInstance(ksp, cache, new NullUser());
                // New upstream metadata may break the consistency of already installed modules
                // e.g. if user installs modules A and B and then later up A is made to conflict with B
                // This is perfectly normal and shouldn't produce an error, therefore we skip enforcing
                // consistency. However, we will show the user any inconsistencies later on.

                // Do each changed module one at a time so a failure of one doesn't cause all the others to fail
                foreach (CkanModule mod in metadataChanges)
                {
                    try
                    {
                        HashSet <string> possibleConfigOnlyDirs = null;
                        installer.Upgrade(
                            new CkanModule[] { mod },
                            new NetAsyncModulesDownloader(new NullUser(), cache),
                            ref possibleConfigOnlyDirs,
                            registry_manager,
                            enforceConsistency: false,
                            resolveRelationships: true
                            );
                    }
                    // Thrown when a dependency couldn't be satisfied
                    catch (ModuleNotFoundKraken)
                    {
                        log.WarnFormat("Skipping installation of {0} due to relationship error.", mod.identifier);
                        user.RaiseMessage("Skipping installation of {0} due to relationship error.", mod.identifier);
                    }
                    // Thrown when a conflicts relationship is violated
                    catch (InconsistentKraken)
                    {
                        log.WarnFormat("Skipping installation of {0} due to relationship error.", mod.identifier);
                        user.RaiseMessage("Skipping installation of {0} due to relationship error.", mod.identifier);
                    }
                }
            }
        }
Example #13
0
        public InstalledModuleFile(string path, GameInstance ksp)
        {
            string absolute_path = ksp.ToAbsoluteGameDir(path);

            sha1_sum = Sha1Sum(absolute_path);
        }
Example #14
0
        /// <summary>
        /// Resolve differences between installed and available metadata for given ModuleInstaller
        /// </summary>
        /// <param name="metadataChanges">List of modules that changed</param>
        /// <param name="user">Object for user interaction callbacks</param>
        /// <param name="ksp">Game instance</param>
        /// <param name="cache">Cacne object for mod downloads</param>
        /// <param name="registry_manager">Manager that holds our game instances</param>
        private static void HandleModuleChanges(List <CkanModule> metadataChanges, IUser user, GameInstance ksp, NetModuleCache cache, RegistryManager registry_manager)
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < metadataChanges.Count; i++)
            {
                CkanModule module = metadataChanges[i];
                sb.AppendLine(string.Format("- {0} {1}", module.identifier, module.version));
            }

            if (user.RaiseYesNoDialog(string.Format(@"The following mods have had their metadata changed since last update:

{0}
You should reinstall them in order to preserve consistency with the repository.

Do you wish to reinstall now?", sb)))
            {
                throw new ReinstallModuleKraken(metadataChanges);
            }
        }
Example #15
0
 public InstallFiltersDialog(IConfiguration globalConfig, GameInstance instance)
 {
     InitializeComponent();
     this.globalConfig = globalConfig;
     this.instance     = instance;
 }
Example #16
0
 private void GameExit(GameInstance inst)
 {
     inst.playTime.Stop(inst.CkanDir());
     UpdateStatusBar();
 }
Example #17
0
        public void LaunchGame()
        {
            var split = configuration.CommandLineArguments.Split(' ');

            if (split.Length == 0)
            {
                return;
            }

            var registry = RegistryManager.Instance(CurrentInstance).registry;

            var suppressedIdentifiers = CurrentInstance.GetSuppressedCompatWarningIdentifiers;
            var incomp = registry.IncompatibleInstalled(CurrentInstance.VersionCriteria())
                         .Where(m => !m.Module.IsDLC && !suppressedIdentifiers.Contains(m.identifier))
                         .ToList();

            if (incomp.Any())
            {
                // Warn that it might not be safe to run Game with incompatible modules installed
                string incompatDescrip = incomp
                                         .Select(m => $"{m.Module} ({registry.CompatibleGameVersions(CurrentInstance.game, m.Module)})")
                                         .Aggregate((a, b) => $"{a}{Environment.NewLine}{b}");
                var ver    = CurrentInstance.Version();
                var result = SuppressableYesNoDialog(
                    string.Format(Properties.Resources.MainLaunchWithIncompatible, incompatDescrip),
                    string.Format(Properties.Resources.MainLaunchDontShow,
                                  CurrentInstance.game.ShortName,
                                  new GameVersion(ver.Major, ver.Minor, ver.Patch)),
                    Properties.Resources.MainLaunch,
                    Properties.Resources.MainGoBack
                    );
                if (result.Item1 != DialogResult.Yes)
                {
                    return;
                }
                else if (result.Item2)
                {
                    CurrentInstance.AddSuppressedCompatWarningIdentifiers(
                        incomp.Select(m => m.identifier).ToHashSet()
                        );
                }
            }

            split = CurrentInstance.game.AdjustCommandLine(split,
                                                           Main.Instance.CurrentInstance.Version());
            var binary = split[0];
            var args   = string.Join(" ", split.Skip(1));

            try
            {
                Directory.SetCurrentDirectory(CurrentInstance.GameDir());

                Process p = new Process()
                {
                    StartInfo = new ProcessStartInfo()
                    {
                        FileName  = binary,
                        Arguments = args
                    },
                    EnableRaisingEvents = true
                };

                GameInstance inst = CurrentInstance;
                p.Exited += (sender, e) => GameExit(inst);

                p.Start();
                CurrentInstance.playTime.Start();
            }
            catch (Exception exception)
            {
                currentUser.RaiseError(Properties.Resources.MainLaunchFailed, exception.Message);
            }
        }