Exemplo n.º 1
0
        private static bool IsConflicting(IModelRepositoryMod origin, IModelRepositoryMod otherMod,
                                          IModelStorageMod selected)
        {
            if (origin.State == LoadingState.Loading || otherMod.State == LoadingState.Loading ||
                selected.GetState() == StorageModStateEnum.Loading)
            {
                return(false);
            }

            if (otherMod.GetVersionHash().IsMatch(origin.GetVersionHash()))
            {
                return(false); // that's fine, won't break anything
            }
            if (!otherMod.GetMatchHash().IsMatch(selected.GetMatchHash()))
            {
                return(false); // unrelated mod, we don't care
            }
            var actionType = GetModAction(origin, selected);

            if (actionType == ModActionEnum.Use)
            {
                return(false);                                 // not our problem. only show conflict when we're trying to change something
            }
            return(true);
        }
Exemplo n.º 2
0
 private void AddRepositoryMod(IModelRepositoryMod mod)
 {
     _logger.Trace($"Added repository mod {mod.ParentRepository.Name}/{mod.Identifier}");
     mod.StateChanged += _ => OnAnyChange();
     mod.SelectionChanged += _ => OnAnyChange();
     mod.DownloadIdentifierChanged += _ => OnAnyChange();
     OnAnyChange();
 }
Exemplo n.º 3
0
 internal static ModAction Create(ModSelection selection, IModelRepositoryMod parent)
 {
     return(selection switch
     {
         ModSelectionNone => new SelectNone(),
         ModSelectionLoading => new SelectLoading(),
         ModSelectionDisabled => new SelectDisabled(),
         ModSelectionDownload download => new SelectStorage(download.DownloadStorage),
         ModSelectionStorageMod actionStorageMod => new SelectMod(actionStorageMod.StorageMod,
                                                                  CoreCalculation.GetModAction(parent, actionStorageMod.StorageMod)),
         _ => throw new ArgumentException()
     });
Exemplo n.º 4
0
        private ModSelection GetSelection(IModelRepositoryMod mod)
        {
            _logger.Trace($"Checking auto-selection for mod {mod.Identifier}");

            var storageMods = _model.GetStorageMods().ToList();

            var previouslySelectedMod =
                storageMods.SingleOrDefault(m => m.GetStorageModIdentifiers().Equals(mod.GetPreviousSelection()));

            if (previouslySelectedMod != null)
            {
                return(new ModSelectionStorageMod(previouslySelectedMod));
            }

            // TODO: check previously selected storage for download?

            // wait for everything to load.
            if (_model.GetStorages().Any(s => s.State == LoadingState.Loading))
            {
                return(new ModSelectionLoading());
            }
            if (_model.GetRepositories().Any(s => s.State == LoadingState.Loading))
            {
                return(new ModSelectionLoading());
            }
            if (_model.GetRepositoryMods().Any(s => s.State == LoadingState.Loading))
            {
                return(new ModSelectionLoading());
            }
            if (_model.GetStorageMods().Any(s => s.GetState() == StorageModStateEnum.Loading))
            {
                return(new ModSelectionLoading());
            }

            var selectedMod = CoreCalculation.AutoSelect(mod, storageMods, _model.GetRepositoryMods());

            if (selectedMod != null)
            {
                return(new ModSelectionStorageMod(selectedMod));
            }

            var storage = _model.GetStorages().FirstOrDefault(s => s.CanWrite && s.IsAvailable());

            if (storage != null)
            {
                mod.DownloadIdentifier = CoreCalculation.GetAvailableDownloadIdentifier(storage, mod.Identifier);
                return(new ModSelectionDownload(storage));
            }

            return(new ModSelectionNone());
        }
Exemplo n.º 5
0
        public static string?GetErrorForSelection(IModelRepositoryMod mod, IEnumerable <IModelRepositoryMod> allRepositoryMods)
        {
            var selection = mod.GetCurrentSelection();

            switch (selection)
            {
            case ModSelectionDisabled:
                return(null);

            case ModSelectionDownload when string.IsNullOrWhiteSpace(mod.DownloadIdentifier):
                return("Name must be a valid folder name");

            case ModSelectionDownload when mod.DownloadIdentifier.IndexOfAny(Path.GetInvalidPathChars()) >= 0 || mod.DownloadIdentifier.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0:
                return("Invalid characters in name");

            case ModSelectionDownload selectStorage:
            {
                if (selectStorage.DownloadStorage.State == LoadingState.Loading)
                {
                    return(null);
                }
                var folderExists = selectStorage.DownloadStorage.HasMod(mod.DownloadIdentifier);
                return(folderExists ? "Name in use" : null);
            }

            case ModSelectionStorageMod selectMod when GetModAction(mod, selectMod.StorageMod) == ModActionEnum.AbortActiveAndUpdate:
                return("This mod is currently being updated");

            case ModSelectionStorageMod selectMod:
            {
                var conflicts = GetConflictsUsingMod(mod, selectMod.StorageMod, allRepositoryMods);
                if (!conflicts.Any())
                {
                    return(null);
                }

                var conflictNames = conflicts.Select(c => $"{c}");
                return("In conflict with: " + string.Join(", ", conflictNames));
            }

            default:
                return(null);
            }
        }
Exemplo n.º 6
0
        internal static IModelStorageMod?AutoSelect(IModelRepositoryMod repoMod, IEnumerable <IModelStorageMod> storageMods, List <IModelRepositoryMod> allRepoMods)
        {
            var byActionType = new Dictionary <ModActionEnum, List <IModelStorageMod> >();

            foreach (var storageMod in storageMods)
            {
                if (GetConflictsUsingMod(repoMod, storageMod, allRepoMods).Any())
                {
                    continue;
                }
                var action = GetModAction(repoMod, storageMod);
                byActionType.AddInBin(action, storageMod);
            }

            // Order of precedence
            var precedence = new[]
            { ModActionEnum.Use, ModActionEnum.Await, ModActionEnum.ContinueUpdate, ModActionEnum.Update };

            foreach (var actionType in precedence)
            {
                if (!byActionType.TryGetValue(actionType, out var candidates))
                {
                    continue;
                }

                // no steam
                var foundMod = candidates.FirstOrDefault(mod => mod.CanWrite);
                if (foundMod != null)
                {
                    return(foundMod);
                }

                // steam
                foundMod = candidates.FirstOrDefault(mod => !mod.CanWrite);
                if (foundMod != null)
                {
                    return(foundMod);
                }
            }

            return(null);
        }
Exemplo n.º 7
0
        private static List <IModelRepositoryMod> GetConflictsUsingMod(IModelRepositoryMod repoMod, IModelStorageMod storageMod, IEnumerable <IModelRepositoryMod> allRepoMods)
        {
            var result = new List <IModelRepositoryMod>();

            foreach (var mod in allRepoMods)
            {
                if (mod == repoMod)
                {
                    continue;
                }
                if (mod.GetCurrentSelection() is not ModSelectionStorageMod otherMod || otherMod.StorageMod != storageMod)
                {
                    continue;
                }
                if (IsConflicting(repoMod, mod, storageMod))
                {
                    result.Add(mod);
                }
            }

            return(result);
        }
Exemplo n.º 8
0
 private IModelStorageMod?AutoSelect(IModelRepositoryMod repoMod, IEnumerable <IModelRepositoryMod>?allRepoMods = null,
                                     params IModelStorageMod[] storageMods)
 {
     return(CoreCalculation.AutoSelect(repoMod, storageMods.ToList(), allRepoMods?.ToList() ?? new List <IModelRepositoryMod>()));
 }
Exemplo n.º 9
0
        // TODO: create more tests. especially for loading/error handling
        // TODO: split up. need to figure out how tho..

        internal static ModActionEnum GetModAction(IModelRepositoryMod repoMod,
                                                   IModelStorageMod storageMod)
        {
            if (repoMod.State == LoadingState.Loading || storageMod.GetState() == StorageModStateEnum.Loading)
            {
                return(ModActionEnum.Loading);
            }

            if (repoMod.State == LoadingState.Error || storageMod.GetState() == StorageModStateEnum.Error)
            {
                return(ModActionEnum.Unusable);
            }

            bool CheckMatch() => repoMod.GetMatchHash().IsMatch(storageMod.GetMatchHash());
            bool CheckVersion() => repoMod.GetVersionHash().IsMatch(storageMod.GetVersionHash());

            switch (storageMod.GetState())
            {
            case StorageModStateEnum.CreatedWithUpdateTarget:
            {
                if (CheckVersion())
                {
                    return(ModActionEnum.ContinueUpdate);
                }
                if (CheckMatch())
                {
                    return(ModActionEnum.AbortAndUpdate);
                }
                return(ModActionEnum.Unusable);
            }

            case StorageModStateEnum.Created:
            {
                if (!CheckMatch())
                {
                    return(ModActionEnum.Unusable);
                }
                if (CheckVersion())
                {
                    return(ModActionEnum.Use);
                }
                return(storageMod.CanWrite ? ModActionEnum.Update : ModActionEnum.UnusableSteam);
            }

            case StorageModStateEnum.Updating:
            {
                if (CheckVersion())
                {
                    return(ModActionEnum.Await);
                }
                if (CheckMatch())
                {
                    return(ModActionEnum.AbortActiveAndUpdate);
                }
                return(ModActionEnum.Unusable);
            }

            default:
                throw new ArgumentOutOfRangeException();
            }
        }