public override List <CkanModule> LatestAvailableWithProvides(
     IRegistryQuerier registry, GameVersionCriteria crit, IEnumerable <CkanModule> installed = null,
     IEnumerable <CkanModule> toInstall = null
     )
 {
     return(registry.LatestAvailableWithProvides(name, crit, this, installed, toInstall));
 }
Beispiel #2
0
        /// <summary>
        /// Returns true if our mod is compatible with the KSP version specified.
        /// </summary>
        public bool IsCompatibleKSP(GameVersionCriteria version)
        {
            log.DebugFormat("Testing if {0} is compatible with KSP {1}", this, version.ToString());


            return(_comparator.Compatible(version, this));
        }
        /// <summary>
        /// Return the most recent release of a module with a optional ksp version to target and a RelationshipDescriptor to satisfy.
        /// </summary>
        /// <param name="ksp_version">If not null only consider mods which match this ksp version.</param>
        /// <param name="relationship">If not null only consider mods which satisfy the RelationshipDescriptor.</param>
        /// <param name="installed">Modules that are already installed</param>
        /// <param name="toInstall">Modules that are planned to be installed</param>
        /// <returns></returns>
        public CkanModule Latest(
            GameVersionCriteria ksp_version     = null,
            RelationshipDescriptor relationship = null,
            IEnumerable <CkanModule> installed  = null,
            IEnumerable <CkanModule> toInstall  = null
            )
        {
            log.DebugFormat("Our dictionary has {0} keys", module_version.Keys.Count);
            IEnumerable <CkanModule> modules = module_version.Values.Reverse();

            if (relationship != null)
            {
                modules = modules.Where(relationship.WithinBounds);
            }
            if (ksp_version != null)
            {
                modules = modules.Where(m => m.IsCompatibleKSP(ksp_version));
            }
            if (installed != null)
            {
                modules = modules.Where(m => DependsAndConflictsOK(m, installed));
            }
            if (toInstall != null)
            {
                modules = modules.Where(m => DependsAndConflictsOK(m, toInstall));
            }
            return(modules.FirstOrDefault());
        }
Beispiel #4
0
        /// <summary>
        /// Initialize a GUIMod based on just an identifier
        /// </summary>
        /// <param name="identifier">The id of the module to represent</param>
        /// <param name="registry">CKAN registry object for current game instance</param>
        /// <param name="current_game_version">Current game version</param>
        /// <param name="incompatible">If true, mark this module as incompatible</param>
        public GUIMod(string identifier, IRegistryQuerier registry, GameVersionCriteria current_game_version, bool?incompatible = null)
        {
            Identifier     = identifier;
            IsAutodetected = registry.IsAutodetected(identifier);
            DownloadCount  = registry.DownloadCount(identifier);
            if (IsAutodetected)
            {
                IsInstalled = true;
            }

            ModuleVersion latest_version = null;

            try
            {
                LatestCompatibleMod = registry.LatestAvailable(identifier, current_game_version);
                latest_version      = LatestCompatibleMod?.version;
            }
            catch (ModuleNotFoundKraken)
            {
            }

            IsIncompatible = incompatible ?? LatestCompatibleMod == null;

            // Let's try to find the compatibility for this mod. If it's not in the registry at
            // all (because it's a DarkKAN mod) then this might fail.

            CkanModule latest_available_for_any_ksp = null;

            try
            {
                latest_available_for_any_ksp = registry.LatestAvailable(identifier, null);
            }
            catch
            { }

            // If there's known information for this mod in any form, calculate the highest compatible
            // KSP.
            if (latest_available_for_any_ksp != null)
            {
                GameCompatibilityVersion = registry.LatestCompatibleKSP(identifier);
                GameCompatibility        = GameCompatibilityVersion?.ToYalovString()
                                           ?? Properties.Resources.GUIModUnknown;
                GameCompatibilityLong = string.Format(Properties.Resources.GUIModGameCompatibilityLong, GameCompatibility, latest_available_for_any_ksp.version);
            }

            if (latest_version != null)
            {
                LatestVersion = latest_version.ToString();
            }
            else if (latest_available_for_any_ksp != null)
            {
                LatestVersion = latest_available_for_any_ksp.version.ToString();
            }
            else
            {
                LatestVersion = "-";
            }

            SearchableIdentifier = CkanModule.nonAlphaNums.Replace(Identifier, "");
        }
Beispiel #5
0
        public void HasUpdate_WithUpgradeableManuallyInstalledMod_ReturnsTrue()
        {
            // Arrange
            using (var gameInstWrapper = new DisposableKSP())
            {
                CkanModule mod = CkanModule.FromJson(@"{
                    ""spec_version"": ""v1.4"",
                    ""identifier"":   ""AutoDetectedMod"",
                    ""version"":      ""1.0"",
                    ""ksp_version"":  ""1.11.1"",
                    ""download"":     ""https://mymods/AD/1.0""
                }");
                registry.AddAvailable(mod);
                GameInstance gameInst = gameInstWrapper.KSP;
                registry.RegisterDll(gameInst, Path.Combine(
                                         gameInst.GameDir(), "GameData", $"{mod.identifier}.dll"));
                GameVersionCriteria crit = new GameVersionCriteria(mod.ksp_version);

                // Act
                bool has = registry.HasUpdate(mod.identifier, crit);

                // Assert
                Assert.IsTrue(has, "Can't upgrade manually installed DLL");
            }
        }
Beispiel #6
0
        public void CompatibleModules_PastAndFutureCompatibility_ReturnsCurrentOnly()
        {
            // Arrange
            CkanModule modFor161 = CkanModule.FromJson(@"{
                ""identifier"":  ""TypicalMod"",
                ""version"":     ""0.9.0"",
                ""download"":    ""https://kerbalstuff.com/mod/269/Dogecoin%20Flag/download/1.01"",
                ""ksp_version"": ""1.6.1""
            }");
            CkanModule modFor173 = CkanModule.FromJson(@"{
                ""identifier"":  ""TypicalMod"",
                ""version"":     ""1.0.0"",
                ""download"":    ""https://kerbalstuff.com/mod/269/Dogecoin%20Flag/download/1.01"",
                ""ksp_version"": ""1.7.3""
            }");
            CkanModule modFor181 = CkanModule.FromJson(@"{
                ""identifier"":  ""TypicalMod"",
                ""version"":     ""1.1.0"",
                ""download"":    ""https://kerbalstuff.com/mod/269/Dogecoin%20Flag/download/1.01"",
                ""ksp_version"": ""1.8.1""
            }");

            registry.AddAvailable(modFor161);
            registry.AddAvailable(modFor173);
            registry.AddAvailable(modFor181);

            // Act
            GameVersionCriteria v173   = new GameVersionCriteria(GameVersion.Parse("1.7.3"));
            List <CkanModule>   compat = registry.CompatibleModules(v173).ToList();

            // Assert
            Assert.IsFalse(compat.Contains(modFor161));
            Assert.IsTrue(compat.Contains(modFor173));
            Assert.IsFalse(compat.Contains(modFor181));
        }
 public override List <CkanModule> LatestAvailableWithProvides(
     IRegistryQuerier registry, GameVersionCriteria crit, IEnumerable <CkanModule> installed = null,
     IEnumerable <CkanModule> toInstall = null
     )
 {
     return(any_of?.SelectMany(r => r.LatestAvailableWithProvides(registry, crit, installed, toInstall)).ToList());
 }
Beispiel #8
0
        public void EnforceSizeLimit(long bytes, Registry registry)
        {
            int  numFiles;
            long curBytes;

            GetSizeInfo(out numFiles, out curBytes);
            if (curBytes > bytes)
            {
                // This object will let us determine whether a module is compatible with any of our instances
                GameVersionCriteria aggregateCriteria = manager?.Instances.Values
                                                        .Where(ksp => ksp.Valid)
                                                        .Select(ksp => ksp.VersionCriteria())
                                                        .Aggregate(
                    manager?.CurrentInstance?.VersionCriteria()
                    ?? new GameVersionCriteria(null),
                    (combinedCrit, nextCrit) => combinedCrit.Union(nextCrit)
                    );

                // This object lets us find the modules associated with a cached file
                Dictionary <string, List <CkanModule> > hashMap = registry.GetDownloadHashIndex();

                // Prune the module lists to only those that are compatible
                foreach (var kvp in hashMap)
                {
                    kvp.Value.RemoveAll(mod => !mod.IsCompatibleKSP(aggregateCriteria));
                }

                // Now get all the files in all the caches...
                List <FileInfo> files = allFiles();
                // ... and sort them by compatibilty and timestamp...
                files.Sort((a, b) => compareFiles(
                               hashMap, aggregateCriteria, a, b
                               ));

                // ... and delete them till we're under the limit
                foreach (FileInfo fi in files)
                {
                    curBytes -= fi.Length;
                    fi.Delete();
                    File.Delete($"{fi.Name}.sha1");
                    File.Delete($"{fi.Name}.sha256");
                    if (curBytes <= bytes)
                    {
                        // Limit met, all done!
                        break;
                    }
                }
                OnCacheChanged();
                sha1Cache.Clear();
                sha256Cache.Clear();
            }
        }
Beispiel #9
0
 /// <summary>
 /// Creates a new resolver that will find a way to install all the modules specified.
 /// </summary>
 /// <param name="modulesToInstall">Modules to install</param>
 /// <param name="modulesToRemove">Modules to remove</param>
 /// <param name="options">Options for the RelationshipResolver</param>
 /// <param name="registry">CKAN registry object for current game instance</param>
 /// <param name="GameVersion">The current KSP version criteria to consider</param>
 public RelationshipResolver(IEnumerable <CkanModule> modulesToInstall, IEnumerable <CkanModule> modulesToRemove, RelationshipResolverOptions options, IRegistryQuerier registry,
                             GameVersionCriteria GameVersion)
     : this(options, registry, GameVersion)
 {
     if (modulesToRemove != null)
     {
         RemoveModsFromInstalledList(modulesToRemove);
     }
     if (modulesToInstall != null)
     {
         AddModulesToInstall(modulesToInstall);
     }
 }
Beispiel #10
0
        /// <summary>
        /// Creates a new Relationship resolver.
        /// </summary>
        /// <param name="options">Options for the RelationshipResolver</param>
        /// <param name="registry">CKAN registry object for current game instance</param>
        /// <param name="GameVersion">The current KSP version criteria to consider</param>
        public RelationshipResolver(RelationshipResolverOptions options, IRegistryQuerier registry, GameVersionCriteria GameVersion)
        {
            this.registry    = registry;
            this.GameVersion = GameVersion;
            this.options     = options;

            installed_modules = new HashSet <CkanModule>(registry.InstalledModules.Select(i_module => i_module.Module));
            var installed_relationship = new SelectionReason.Installed();

            foreach (var module in installed_modules)
            {
                reasons.Add(module, installed_relationship);
            }
        }
Beispiel #11
0
 /// <summary>
 /// Initialize a GUIMod based on an InstalledModule
 /// </summary>
 /// <param name="instMod">The installed module to represent</param>
 /// <param name="registry">CKAN registry object for current game instance</param>
 /// <param name="current_game_version">Current game version</param>
 /// <param name="incompatible">If true, mark this module as incompatible</param>
 public GUIMod(InstalledModule instMod, IRegistryQuerier registry, GameVersionCriteria current_game_version, bool?incompatible = null)
     : this(instMod.Module, registry, current_game_version, incompatible)
 {
     IsInstalled      = true;
     IsInstallChecked = true;
     InstalledMod     = instMod;
     selectedMod      = instMod.Module;
     IsAutoInstalled  = instMod.AutoInstalled;
     InstallDate      = instMod.InstallTime;
     InstalledVersion = instMod.Module.version.ToString();
     if (LatestVersion == null || LatestVersion.Equals("-"))
     {
         LatestVersion = InstalledVersion;
     }
 }
Beispiel #12
0
 /// <summary>
 /// Initialize the sorter and partition the mods.
 /// </summary>
 /// <param name="crit">Versions to be considered compatible</param>
 /// <param name="available">Collection of mods from registry</param>
 /// <param name="providers">Dictionary mapping every identifier to the modules providing it</param>
 /// <param name="dlls">Collection of found dlls</param>
 /// <param name="dlc">Collection of installed DLCs</param>
 public CompatibilitySorter(
     GameVersionCriteria crit,
     Dictionary <string, AvailableModule> available,
     Dictionary <string, HashSet <AvailableModule> > providers,
     Dictionary <string, InstalledModule> installed,
     HashSet <string> dlls,
     IDictionary <string, ModuleVersion> dlc
     )
 {
     CompatibleVersions = crit;
     this.installed     = installed;
     this.dlls          = dlls;
     this.dlc           = dlc;
     PartitionModules(available, CompatibleProviders(crit, providers));
 }
Beispiel #13
0
 public virtual bool Compatible(GameVersionCriteria gameVersionCriteria, CkanModule module)
 {
     if (gameVersionCriteria.Versions.Count == 0)
     {
         return(true);
     }
     foreach (GameVersion gameVersion in gameVersionCriteria.Versions)
     {
         if (SingleVersionsCompatible(gameVersion, module))
         {
             return(true);
         }
     }
     return(false);
 }
Beispiel #14
0
        private void UpdateRepo(object sender, DoWorkEventArgs e)
        {
            try
            {
                AddStatusMessage(Properties.Resources.MainRepoScanning);
                log.Debug("Scanning before repo update");
                bool scanChanged = CurrentInstance.Scan();

                AddStatusMessage(Properties.Resources.MainRepoUpdating);

                // Note the current mods' compatibility for the NewlyCompatible filter
                GameVersionCriteria       versionCriteria = CurrentInstance.VersionCriteria();
                IRegistryQuerier          registry        = RegistryManager.Instance(CurrentInstance).registry;
                Dictionary <string, bool> oldModules      = registry.CompatibleModules(versionCriteria)
                                                            .ToDictionary(m => m.identifier, m => false);
                registry.IncompatibleModules(versionCriteria)
                .Where(m => !oldModules.ContainsKey(m.identifier))
                .ToList()
                .ForEach(m => oldModules.Add(m.identifier, true));

                RepoUpdateResult result = Repo.UpdateAllRepositories(
                    RegistryManager.Instance(CurrentInstance),
                    CurrentInstance, Manager.Cache, currentUser);
                if (result == RepoUpdateResult.NoChanges && scanChanged)
                {
                    result = RepoUpdateResult.Updated;
                }
                e.Result = new KeyValuePair <RepoUpdateResult, Dictionary <string, bool> >(
                    result, oldModules);
            }
            catch (UriFormatException ex)
            {
                errorDialog.ShowErrorDialog(ex.Message);
            }
            catch (MissingCertificateKraken ex)
            {
                errorDialog.ShowErrorDialog(ex.ToString());
            }
            catch (ReinstallModuleKraken)
            {
                // Bypass the generic error dialog so the Post can handle this
                throw;
            }
            catch (Exception ex)
            {
                errorDialog.ShowErrorDialog(string.Format(Properties.Resources.MainRepoFailedToConnect, ex.Message));
            }
        }
Beispiel #15
0
 /// <summary>
 /// Attempts to convert the identifiers to CkanModules and then calls RelationshipResolver.ctor(IEnumerable{CkanModule}, IEnumerable{CkanModule}, Registry, GameVersion)"/>
 /// </summary>
 /// <param name="modulesToInstall">Identifiers of modules to install, will be converted to CkanModules using CkanModule.FromIDandVersion</param>
 /// <param name="modulesToRemove">Identifiers of modules to remove, will be converted to CkanModules using Registry.InstalledModule</param>
 /// <param name="options">Options for the RelationshipResolver</param>
 /// <param name="registry">CKAN registry object for current game instance</param>
 /// <param name="GameVersion">The current KSP version criteria to consider</param>
 public RelationshipResolver(IEnumerable <string> modulesToInstall, IEnumerable <string> modulesToRemove, RelationshipResolverOptions options, IRegistryQuerier registry,
                             GameVersionCriteria GameVersion) :
     this(
         modulesToInstall?.Select(mod => TranslateModule(mod, options, registry, GameVersion)),
         modulesToRemove?
         .Select(mod =>
 {
     var match = CkanModule.idAndVersionMatcher.Match(mod);
     return(match.Success ? match.Groups["mod"].Value : mod);
 })
         .Where(identifier => registry.InstalledModule(identifier) != null)
         .Select(identifier => registry.InstalledModule(identifier).Module),
         options, registry, GameVersion)
 {
     // Does nothing, just calls the other overloaded constructor
 }
Beispiel #16
0
        public void HasUpdate_OtherModDependsOnCurrent_ReturnsFalse()
        {
            // Arrange
            using (var gameInstWrapper = new DisposableKSP())
            {
                CkanModule olderDepMod  = CkanModule.FromJson(@"{
                    ""spec_version"": ""v1.4"",
                    ""identifier"":   ""DependencyMod"",
                    ""version"":      ""1.0"",
                    ""ksp_version"":  ""1.11.1"",
                    ""download"":     ""https://mymods/DM/1.0""
                }");
                CkanModule newerDepMod  = CkanModule.FromJson(@"{
                    ""spec_version"": ""v1.4"",
                    ""identifier"":   ""DependencyMod"",
                    ""version"":      ""2.0"",
                    ""ksp_version"":  ""1.11.1"",
                    ""download"":     ""https://mymods/DM/2.0""
                }");
                CkanModule dependingMod = CkanModule.FromJson(@"{
                    ""spec_version"": ""v1.4"",
                    ""identifier"":   ""DependingMod"",
                    ""version"":      ""1.0"",
                    ""ksp_version"":  ""1.11.1"",
                    ""download"":     ""https://mymods/DM/2.0"",
                    ""depends"": [
                        {
                            ""name"":    ""DependencyMod"",
                            ""version"": ""1.0""
                        }
                    ]
                }");
                registry.AddAvailable(olderDepMod);
                registry.AddAvailable(newerDepMod);
                registry.AddAvailable(dependingMod);
                GameInstance gameInst = gameInstWrapper.KSP;
                registry.RegisterModule(olderDepMod, new string[0], gameInst, false);
                registry.RegisterModule(dependingMod, new string[0], gameInst, false);
                GameVersionCriteria crit = new GameVersionCriteria(olderDepMod.ksp_version);

                // Act
                bool has = registry.HasUpdate(olderDepMod.identifier, crit);

                // Assert
                Assert.IsFalse(has, "Upgrade allowed that would break another mod's dependency");
            }
        }
Beispiel #17
0
 /// <summary>
 /// Initialize a GUIMod based on an InstalledModule
 /// </summary>
 /// <param name="instMod">The installed module to represent</param>
 /// <param name="registry">CKAN registry object for current game instance</param>
 /// <param name="current_game_version">Current game version</param>
 /// <param name="incompatible">If true, mark this module as incompatible</param>
 public GUIMod(InstalledModule instMod, IRegistryQuerier registry, GameVersionCriteria current_game_version, bool?incompatible = null)
     : this(instMod.Module, registry, current_game_version, incompatible)
 {
     IsInstalled      = true;
     IsInstallChecked = true;
     InstalledMod     = instMod;
     selectedMod      = instMod.Module;
     IsAutoInstalled  = instMod.AutoInstalled;
     InstallDate      = instMod.InstallTime;
     InstalledVersion = instMod.Module.version.ToString();
     if (LatestVersion == null || LatestVersion.Equals("-"))
     {
         LatestVersion = InstalledVersion;
     }
     // For mods not known to the registry LatestCompatibleMod is null, however the installed module might be compatible
     IsIncompatible = incompatible ?? LatestCompatibleMod == null && !instMod.Module.IsCompatibleKSP(current_game_version);
 }
Beispiel #18
0
        public override bool Compatible(GameVersionCriteria gameVersionCriteria, CkanModule module)
        {
            // If it's strictly compatible, then it's compatible.
            if (strict.Compatible(gameVersionCriteria, module))
            {
                return(true);
            }

            // If we're in strict mode, and it's not strictly compatible, then it's
            // not compatible.
            if (module.ksp_version_strict)
            {
                return(false);
            }

            return(base.Compatible(gameVersionCriteria, module));
        }
Beispiel #19
0
 public void LoadRecommendations(
     IRegistryQuerier registry, GameVersionCriteria GameVersion, NetModuleCache cache,
     Dictionary <CkanModule, Tuple <bool, List <string> > > recommendations,
     Dictionary <CkanModule, List <string> > suggestions,
     Dictionary <CkanModule, HashSet <string> > supporters
     )
 {
     this.registry    = registry;
     this.GameVersion = GameVersion;
     Util.Invoke(this, () =>
     {
         RecommendedModsToggleCheckbox.Checked = true;
         RecommendedModsListView.Items.Clear();
         RecommendedModsListView.Items.AddRange(
             getRecSugRows(cache, recommendations, suggestions, supporters).ToArray());
         MarkConflicts();
     });
 }
Beispiel #20
0
        /// <summary>
        /// Filter the provides mapping by compatibility
        /// </summary>
        /// <param name="crit">Versions to be considered compatible</param>
        /// <param name="providers">Mapping from identifiers to mods providing those identifiers</param>
        /// <returns>
        /// Mapping from identifiers to compatible mods providing those identifiers
        /// </returns>
        private Dictionary <string, HashSet <AvailableModule> > CompatibleProviders(GameVersionCriteria crit, Dictionary <string, HashSet <AvailableModule> > providers)
        {
            var compat = new Dictionary <string, HashSet <AvailableModule> >();

            foreach (var kvp in providers)
            {
                // Find providing non-DLC modules that are compatible with crit
                var compatAvail = kvp.Value.Where(avm =>
                                                  avm.AllAvailable().Any(ckm =>
                                                                         !ckm.IsDLC &&
                                                                         ckm.ProvidesList.Contains(kvp.Key) && ckm.IsCompatibleKSP(crit))
                                                  ).ToHashSet();
                // Add compatible providers to mapping, if any
                if (compatAvail.Any())
                {
                    compat.Add(kvp.Key, compatAvail);
                }
            }
            return(compat);
        }
Beispiel #21
0
        private int compareFiles(Dictionary <string, List <CkanModule> > hashMap, GameVersionCriteria crit, FileInfo a, FileInfo b)
        {
            // Compatible modules for file A
            List <CkanModule> modulesA;

            hashMap.TryGetValue(a.Name.Substring(0, 8), out modulesA);
            bool compatA = modulesA?.Any() ?? false;

            // Compatible modules for file B
            List <CkanModule> modulesB;

            hashMap.TryGetValue(b.Name.Substring(0, 8), out modulesB);
            bool compatB = modulesB?.Any() ?? false;

            if (modulesA == null && modulesB != null)
            {
                // A isn't indexed but B is, delete A first
                return(-1);
            }
            else if (modulesA != null && modulesB == null)
            {
                // A is indexed but B isn't, delete B first
                return(1);
            }
            else if (!compatA && compatB)
            {
                // A isn't compatible but B is, delete A first
                return(-1);
            }
            else if (compatA && !compatB)
            {
                // A is compatible but B isn't, delete B first
                return(1);
            }
            else
            {
                // Both are either compatible or incompatible
                // Go by file age, oldest first
                return((int)(a.CreationTime - b.CreationTime).TotalSeconds);
            }
        }
Beispiel #22
0
        private void AuditRecommendations(IRegistryQuerier registry, GameVersionCriteria versionCriteria)
        {
            var installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser);

            if (installer.FindRecommendations(
                    registry.InstalledModules.Select(im => im.Module).ToHashSet(),
                    new HashSet <CkanModule>(),
                    registry as Registry,
                    out Dictionary <CkanModule, Tuple <bool, List <string> > > recommendations,
                    out Dictionary <CkanModule, List <string> > suggestions,
                    out Dictionary <CkanModule, HashSet <string> > supporters
                    ))
            {
                tabController.ShowTab("ChooseRecommendedModsTabPage", 3);
                ChooseRecommendedMods.LoadRecommendations(
                    registry, new HashSet <CkanModule>(), new HashSet <CkanModule>(),
                    versionCriteria, Manager.Cache,
                    recommendations, suggestions, supporters);
                var result = ChooseRecommendedMods.Wait();
                tabController.HideTab("ChooseRecommendedModsTabPage");
                if (result != null && result.Any())
                {
                    installWorker.RunWorkerAsync(
                        new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                            result.Select(mod => new ModChange(
                                              mod,
                                              GUIModChangeType.Install,
                                              null
                                              )).ToList(),
                            RelationshipResolver.DependsOnlyOpts()
                            )
                        );
                }
            }
            else
            {
                currentUser.RaiseError(Properties.Resources.MainRecommendationsNoneFound);
            }
        }
Beispiel #23
0
        /// <summary>
        /// Initialize a GUIMod based on a CkanModule
        /// </summary>
        /// <param name="mod">The module to represent</param>
        /// <param name="registry">CKAN registry object for current game instance</param>
        /// <param name="current_game_version">Current game version</param>
        /// <param name="incompatible">If true, mark this module as incompatible</param>
        public GUIMod(CkanModule mod, IRegistryQuerier registry, GameVersionCriteria current_game_version, bool?incompatible = null)
            : this(mod.identifier, registry, current_game_version, incompatible)
        {
            Mod    = mod;
            IsCKAN = mod is CkanModule;

            Name        = mod.name.Trim();
            Abstract    = [email protected]();
            Description = mod.description?.Trim() ?? string.Empty;
            Abbrevation = new string(Name.Split(' ').Where(s => s.Length > 0).Select(s => s[0]).ToArray());
            Authors     = mod.author == null ? Properties.Resources.GUIModNSlashA : String.Join(",", mod.author);

            HasUpdate      = registry.HasUpdate(mod.identifier, current_game_version);
            HasReplacement = registry.GetReplacement(mod, current_game_version) != null;
            DownloadSize   = mod.download_size == 0 ? Properties.Resources.GUIModNSlashA : CkanModule.FmtSize(mod.download_size);

            // Get the Searchables.
            SearchableName        = mod.SearchableName;
            SearchableAbstract    = mod.SearchableAbstract;
            SearchableDescription = mod.SearchableDescription;
            SearchableAuthors     = mod.SearchableAuthors;

            // If not set in GUIMod(identifier, ...) (because the mod is not known to the registry),
            // set based on the the data we have from the CkanModule.
            if (GameCompatibilityVersion == null)
            {
                GameCompatibilityVersion = mod.LatestCompatibleKSP();
                GameCompatibility        = GameCompatibilityVersion?.ToYalovString() ?? Properties.Resources.GUIModUnknown;
                GameCompatibilityLong    = string.Format(
                    Properties.Resources.GUIModGameCompatibilityLong,
                    GameCompatibility,
                    mod.version
                    );
            }

            UpdateIsCached();
        }
Beispiel #24
0
        /// <summary>
        /// This function returns a changeset based on the selections of the user.
        /// Currently returns null if a conflict is detected.
        /// </summary>
        /// <param name="registry"></param>
        /// <param name="changeSet"></param>
        /// <param name="installer">A module installer for the current game instance</param>
        /// <param name="version">The version of the current game instance</param>
        public IEnumerable <ModChange> ComputeChangeSetFromModList(
            IRegistryQuerier registry, HashSet <ModChange> changeSet, ModuleInstaller installer,
            GameVersionCriteria version)
        {
            var modules_to_install = new HashSet <CkanModule>();
            var modules_to_remove  = new HashSet <CkanModule>();

            foreach (var change in changeSet)
            {
                switch (change.ChangeType)
                {
                case GUIModChangeType.None:
                    break;

                case GUIModChangeType.Update:
                case GUIModChangeType.Install:
                    modules_to_install.Add(change.Mod);
                    break;

                case GUIModChangeType.Remove:
                    modules_to_remove.Add(change.Mod);
                    break;

                case GUIModChangeType.Replace:
                    ModuleReplacement repl = registry.GetReplacement(change.Mod, version);
                    if (repl != null)
                    {
                        modules_to_remove.Add(repl.ToReplace);
                        modules_to_install.Add(repl.ReplaceWith);
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            var installed_modules =
                registry.InstalledModules.Select(imod => imod.Module).ToDictionary(mod => mod.identifier, mod => mod);

            foreach (var dependent in registry.FindReverseDependencies(
                         modules_to_remove
                         .Select(mod => mod.identifier)
                         .Except(modules_to_install.Select(m => m.identifier)),
                         modules_to_install
                         ))
            {
                //TODO This would be a good place to have an event that alters the row's graphics to show it will be removed
                CkanModule depMod;
                if (installed_modules.TryGetValue(dependent, out depMod))
                {
                    CkanModule module_by_version = registry.GetModuleByVersion(depMod.identifier,
                                                                               depMod.version)
                                                   ?? registry.InstalledModule(dependent).Module;
                    changeSet.Add(new ModChange(module_by_version, GUIModChangeType.Remove, null));
                    modules_to_remove.Add(module_by_version);
                }
            }
            foreach (var im in registry.FindRemovableAutoInstalled(
                         registry.InstalledModules.Where(im => !modules_to_remove.Any(m => m.identifier == im.identifier) || modules_to_install.Any(m => m.identifier == im.identifier))
                         ))
            {
                changeSet.Add(new ModChange(im.Module, GUIModChangeType.Remove, new SelectionReason.NoLongerUsed()));
                modules_to_remove.Add(im.Module);
            }

            // Get as many dependencies as we can, but leave decisions and prompts for installation time
            RelationshipResolverOptions opts = RelationshipResolver.DependsOnlyOpts();

            opts.without_toomanyprovides_kraken = true;
            opts.without_enforce_consistency    = true;

            var resolver = new RelationshipResolver(
                modules_to_install,
                modules_to_remove,
                opts, registry, version);

            changeSet.UnionWith(
                resolver.ModList()
                .Select(m => new ModChange(m, GUIModChangeType.Install, resolver.ReasonFor(m))));

            return(changeSet);
        }
Beispiel #25
0
        public static Dictionary <GUIMod, string> ComputeConflictsFromModList(IRegistryQuerier registry,
                                                                              IEnumerable <ModChange> change_set, GameVersionCriteria ksp_version)
        {
            var modules_to_install = new HashSet <string>();
            var modules_to_remove  = new HashSet <string>();
            var options            = new RelationshipResolverOptions
            {
                without_toomanyprovides_kraken = true,
                proceed_with_inconsistencies   = true,
                without_enforce_consistency    = true,
                with_recommends = false
            };

            foreach (var change in change_set)
            {
                switch (change.ChangeType)
                {
                case GUIModChangeType.None:
                    break;

                case GUIModChangeType.Install:
                    modules_to_install.Add(change.Mod.identifier);
                    break;

                case GUIModChangeType.Remove:
                    modules_to_remove.Add(change.Mod.identifier);
                    break;

                case GUIModChangeType.Update:
                    break;

                case GUIModChangeType.Replace:
                    ModuleReplacement repl = registry.GetReplacement(change.Mod, ksp_version);
                    if (repl != null)
                    {
                        modules_to_remove.Add(repl.ToReplace.identifier);
                        modules_to_install.Add(repl.ReplaceWith.identifier);
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            // Only check mods that would exist after the changes are made.
            IEnumerable <CkanModule> installed = registry.InstalledModules.Where(
                im => !modules_to_remove.Contains(im.Module.identifier)
                ).Select(im => im.Module);

            // Convert ONLY modules_to_install with CkanModule.FromIDandVersion,
            // because it may not find already-installed modules.
            IEnumerable <CkanModule> mods_to_check = installed.Union(
                modules_to_install.Except(modules_to_remove).Select(
                    name => CkanModule.FromIDandVersion(registry, name, ksp_version)
                    )
                );
            var resolver = new RelationshipResolver(
                mods_to_check,
                change_set.Where(ch => ch.ChangeType == GUIModChangeType.Remove)
                .Select(ch => ch.Mod),
                options, registry, ksp_version
                );

            return(resolver.ConflictList.ToDictionary(item => new GUIMod(item.Key, registry, ksp_version),
                                                      item => item.Value));
        }
Beispiel #26
0
        public static Dictionary <GUIMod, string> ComputeConflictsFromModList(IRegistryQuerier registry,
                                                                              IEnumerable <ModChange> change_set, GameVersionCriteria ksp_version)
        {
            var modules_to_install = new HashSet <CkanModule>();
            var modules_to_remove  = new HashSet <CkanModule>();
            var options            = new RelationshipResolverOptions
            {
                without_toomanyprovides_kraken = true,
                proceed_with_inconsistencies   = true,
                without_enforce_consistency    = true,
                with_recommends = false
            };

            foreach (var change in change_set)
            {
                switch (change.ChangeType)
                {
                case GUIModChangeType.None:
                    break;

                case GUIModChangeType.Install:
                    modules_to_install.Add(change.Mod);
                    break;

                case GUIModChangeType.Remove:
                    modules_to_remove.Add(change.Mod);
                    break;

                case GUIModChangeType.Update:
                    break;

                case GUIModChangeType.Replace:
                    ModuleReplacement repl = registry.GetReplacement(change.Mod, ksp_version);
                    if (repl != null)
                    {
                        modules_to_remove.Add(repl.ToReplace);
                        modules_to_install.Add(repl.ReplaceWith);
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            var resolver = new RelationshipResolver(
                modules_to_install.Except(modules_to_remove),
                modules_to_remove,
                options, registry, ksp_version
                );

            return(resolver.ConflictList.ToDictionary(
                       item => new GUIMod(item.Key, registry, ksp_version),
                       item => item.Value
                       ));
        }
Beispiel #27
0
 /// <summary>
 /// Translate mods from identifiers in its default or identifier=version format into CkanModules,
 /// optionally falling back to incompatible modules if no compatibles could be found.
 /// </summary>
 /// <param name="name">The identifier or identifier=version of the module</param>
 /// <param name="options">If options.allow_incompatible is set, fall back to searching incompatible modules if no compatible has been found</param>
 /// <param name="registry">CKAN registry object for current game instance</param>
 /// <param name="GameVersion">The current KSP version criteria to consider</param>
 /// <returns>A CkanModule</returns>
 private static CkanModule TranslateModule(string name, RelationshipResolverOptions options, IRegistryQuerier registry, GameVersionCriteria GameVersion)
 {
     if (options.allow_incompatible)
     {
         try
         {
             return(CkanModule.FromIDandVersion(registry, name, GameVersion));
         }
         catch (ModuleNotFoundKraken)
         {
             // No versions found matching our game version, so
             // look for incompatible versions.
             return(CkanModule.FromIDandVersion(registry, name, null));
         }
     }
     else
     {
         return(CkanModule.FromIDandVersion(registry, name, GameVersion));
     }
 }
Beispiel #28
0
        /// <summary>
        /// Is the mod installed and does it have a newer version compatible with version
        /// We can't update AD mods
        /// </summary>
        public static bool HasUpdate(this IRegistryQuerier querier, string identifier, GameVersionCriteria version)
        {
            CkanModule newest_version;

            try
            {
                newest_version = querier.LatestAvailable(identifier, version);
            }
            catch (Exception)
            {
                return(false);
            }
            if (newest_version == null ||
                !querier.IsInstalled(identifier, false) ||
                !newest_version.version.IsGreaterThan(querier.InstalledVersion(identifier)))
            {
                return(false);
            }
            // All quick checks pass. Now check the relationships.
            try
            {
                var instMod = querier.InstalledModule(identifier);
                RelationshipResolver resolver = new RelationshipResolver(
                    new CkanModule[] { newest_version },
                    // Remove the old module when installing the new one
                    instMod == null ? null : new CkanModule[] { instMod.Module },
                    new RelationshipResolverOptions()
                {
                    with_recommends = false,
                    without_toomanyprovides_kraken = true,
                },
                    querier,
                    version
                    );
            }
            catch (Exception)
            {
                return(false);
            }
            return(true);
        }
Beispiel #29
0
        /// <summary>
        /// Is the mod installed and does it have a replaced_by relationship with a compatible version
        /// Check latest information on installed version of mod "identifier" and if it has a "replaced_by"
        /// value, check if there is a compatible version of the linked mod
        /// Given a mod identifier, return a ModuleReplacement containing the relevant replacement
        /// if compatibility matches.
        /// </summary>
        public static ModuleReplacement GetReplacement(this IRegistryQuerier querier, string identifier, GameVersionCriteria version)
        {
            // We only care about the installed version
            CkanModule installedVersion;

            try
            {
                installedVersion = querier.GetInstalledVersion(identifier);
            }
            catch (ModuleNotFoundKraken)
            {
                return(null);
            }
            return(querier.GetReplacement(installedVersion, version));
        }
Beispiel #30
0
        public static ModuleReplacement GetReplacement(this IRegistryQuerier querier, CkanModule installedVersion, GameVersionCriteria version)
        {
            // Mod is not installed, so we don't care about replacements
            if (installedVersion == null)
            {
                return(null);
            }
            // No replaced_by relationship
            if (installedVersion.replaced_by == null)
            {
                return(null);
            }

            // Get the identifier from the replaced_by relationship, if it exists
            ModuleRelationshipDescriptor replacedBy = installedVersion.replaced_by;

            // Now we need to see if there is a compatible version of the replacement
            try
            {
                ModuleReplacement replacement = new ModuleReplacement();
                replacement.ToReplace = installedVersion;
                if (installedVersion.replaced_by.version != null)
                {
                    replacement.ReplaceWith = querier.GetModuleByVersion(installedVersion.replaced_by.name, installedVersion.replaced_by.version);
                    if (replacement.ReplaceWith != null)
                    {
                        if (replacement.ReplaceWith.IsCompatibleKSP(version))
                        {
                            return(replacement);
                        }
                    }
                }
                else
                {
                    replacement.ReplaceWith = querier.LatestAvailable(installedVersion.replaced_by.name, version);
                    if (replacement.ReplaceWith != null)
                    {
                        if (installedVersion.replaced_by.min_version != null)
                        {
                            if (!replacement.ReplaceWith.version.IsLessThan(replacedBy.min_version))
                            {
                                return(replacement);
                            }
                        }
                        else
                        {
                            return(replacement);
                        }
                    }
                }
                return(null);
            }
            catch (ModuleNotFoundKraken)
            {
                return(null);
            }
        }