Пример #1
0
        public void TryFactory_TypicalBothDuplicates()
        {
            Assert.True(ModKey.TryFromNameAndExtension("Oblivion.esm", out var masterKey));
            Assert.Equal("Oblivion", masterKey.Name);
            Assert.Equal("Oblivion.esm", masterKey.FileName);
            Assert.Equal(ModType.Master, masterKey.Type);

            Assert.True(ModKey.TryFromNameAndExtension("Oblivion.esp", out var modKey));
            Assert.Equal("Oblivion", modKey.Name);
            Assert.Equal("Oblivion.esp", modKey.FileName);
            Assert.Equal(ModType.Plugin, modKey.Type);

            Assert.True(ModKey.TryFromNameAndExtension("Oblivion.esm", out var masterKey2));
            Assert.Equal("Oblivion", masterKey2.Name);
            Assert.Equal("Oblivion.esm", masterKey2.FileName);
            Assert.Equal(ModType.Master, masterKey2.Type);

            Assert.True(ModKey.TryFromNameAndExtension("Oblivion.esp", out var modKey2));
            Assert.Equal("Oblivion", modKey2.Name);
            Assert.Equal("Oblivion.esp", modKey2.FileName);
            Assert.Equal(ModType.Plugin, modKey2.Type);

            Assert.Same(masterKey.Name, masterKey2.Name);
            Assert.Same(modKey.Name, modKey2.Name);
        }
Пример #2
0
 public void TryFactory_TypicalMod()
 {
     Assert.True(ModKey.TryFromNameAndExtension("Knights.esp", out var modKey));
     Assert.Equal("Knights", modKey.Name);
     Assert.Equal("Knights.esp", modKey.FileName);
     Assert.Equal(ModType.Plugin, modKey.Type);
 }
Пример #3
0
 public void TryFactory_ExtraPeriod()
 {
     Assert.True(ModKey.TryFromNameAndExtension("Obliv.ion.esm", out var modKey));
     Assert.Equal("Obliv.ion", modKey.Name);
     Assert.Equal("Obliv.ion.esm", modKey.FileName);
     Assert.Equal(ModType.Master, modKey.Type);
 }
Пример #4
0
 public void TryFactory_TypicalLightMaster()
 {
     Assert.True(ModKey.TryFromNameAndExtension("Oblivion.esl", out var modKey));
     Assert.Equal("Oblivion", modKey.Name);
     Assert.Equal("Oblivion.esl", modKey.FileName);
     Assert.Equal(ModType.LightMaster, modKey.Type);
 }
Пример #5
0
        public static IObservable <IChangeSet <IModListingGetter> > GetLiveLoadOrder(
            FilePath cccFilePath,
            DirectoryPath dataFolderPath,
            out IObservable <ErrorResponse> state,
            bool orderListings = true)
        {
            var raw = ObservableExt.WatchFile(cccFilePath.Path)
                      .StartWith(Unit.Default)
                      .Select(_ =>
            {
                try
                {
                    return(GetResponse <IObservable <IChangeSet <ModKey> > > .Succeed(
                               File.ReadAllLines(cccFilePath.Path)
                               .Select(x => ModKey.FromNameAndExtension(x))
                               .AsObservableChangeSet()));
                }
                catch (Exception ex)
                {
                    return(GetResponse <IObservable <IChangeSet <ModKey> > > .Fail(ex));
                }
            })
                      .Replay(1)
                      .RefCount();

            state = raw
                    .Select(r => (ErrorResponse)r);
            var ret = ObservableListEx.And(
                raw
                .Select(r =>
            {
                return(r.Value ?? Observable.Empty <IChangeSet <ModKey> >());
            })
                .Switch(),
                ObservableExt.WatchFolderContents(dataFolderPath.Path)
                .Transform(x =>
            {
                if (ModKey.TryFromNameAndExtension(Path.GetFileName(x), out var modKey))
                {
                    return(TryGet <ModKey> .Succeed(modKey));
                }
                return(TryGet <ModKey> .Failure);
            })
                .Filter(x => x.Succeeded)
                .Transform(x => x.Value)
                .RemoveKey())
                      .Transform <ModKey, IModListingGetter>(x => new ModListing(x, true));

            if (orderListings)
            {
                ret = ret.OrderListings();
            }
            return(ret);
        }
Пример #6
0
 public override void Import(JsonElement property, Action <string> logger)
 {
     Values.Clear();
     foreach (var elem in property.EnumerateArray())
     {
         if (ModKey.TryFromNameAndExtension(elem.GetString(), out var modKey))
         {
             Values.Add(new ModKeyItemViewModel(modKey));
         }
         else
         {
             Values.Add(new ModKeyItemViewModel(ModKey.Null));
         }
     }
 }
Пример #7
0
 public MissingMods(
     IProfileLoadOrder loadOrder,
     IPatcherConfigurationWatcher configurationWatcher)
 {
     Missing = configurationWatcher.Customization
               .Select(conf =>
     {
         if (conf == null)
         {
             return(Enumerable.Empty <ModKey>());
         }
         return(conf.RequiredMods
                .SelectWhere(x => TryGet <ModKey> .Create(ModKey.TryFromNameAndExtension(x, out var modKey), modKey)));
     })
               .Select(x => x.AsObservableChangeSet())
               .Switch()
               .Except(loadOrder.LoadOrder.Connect()
                       .Transform(x => x.ModKey))
               .RefCount();
 }
        private static void CanRunPatch(IRunnabilityState state)
        {
            switch (state.Settings.GameRelease.ToCategory())
            {
            case GameCategory.Skyrim:
                if (File.Exists(Path.Combine(state.Settings.DataFolderPath, "Scripts\\ANDR_FollowerFavorCarryLimitScript.pex")) == false)
                {
                    throw new Exception("Cannot find Scripts\\ANDR_FollowerFavorCarryLimitScript.pex. Make sure you have Andrealphus' Gameplay Tweaks - ANDR Tweaks 01 - Follower Favor Carry Limit installed.");
                }

                ModKey.TryFromNameAndExtension("Follower Favor Carry Limit.esp", out var origModKey);
                if (state.LoadOrder.Any(lol => lol.ModKey == origModKey))
                {
                    throw new Exception("Follower Favor Carry Limit.esp must be removed from your load order before running this patcher.");
                }
                break;

            default:
                throw new NotImplementedException();
            }
        }
        public IObservable <IChangeSet <ModKey, ModKey> > Get()
        {
            if (!_fileSystem.Directory.Exists(DataDirectory.Path))
            {
                return(Observable.Empty <IChangeSet <ModKey, ModKey> >());
            }
            return(ObservableExt
                   .WatchFolderContents(DataDirectory.Path, fileSystem: _fileSystem)
                   .Transform(x =>
            {
                if (ModKey.TryFromNameAndExtension(Path.GetFileName(x), out var modKey))
                {
                    return TryGet <ModKey> .Succeed(modKey);
                }

                return TryGet <ModKey> .Failure;
            })
                   .Filter(x => x.Succeeded)
                   .Transform(x => x.Value)
                   .ChangeKey(x => x)
                   .Catch <IChangeSet <ModKey, ModKey>, DirectoryNotFoundException>(_ => Observable.Empty <IChangeSet <ModKey, ModKey> >()));
        }
Пример #10
0
 public void TryFactory_ImproperSuffix()
 {
     Assert.False(ModKey.TryFromNameAndExtension("Obliv.ion.esn", out var modKey));
 }
Пример #11
0
 public void TryFactory_InvalidChars()
 {
     Assert.False(ModKey.TryFromNameAndExtension("Obliv>ion.esm", out var modKey));
 }
Пример #12
0
        public SolutionPatcherVM(ProfileVM parent, SolutionPatcherSettings?settings = null)
            : base(parent, settings)
        {
            CopyInSettings(settings);
            SolutionPath.Filters.Add(new CommonFileDialogFilter("Solution", ".sln"));
            SelectedProjectPath.Filters.Add(new CommonFileDialogFilter("Project", ".csproj"));

            _DisplayName = Observable.CombineLatest(
                this.WhenAnyValue(x => x.Nickname),
                this.WhenAnyValue(x => x.SelectedProjectPath.TargetPath)
                .StartWith(settings?.ProjectSubpath ?? string.Empty),
                (nickname, path) =>
            {
                if (!string.IsNullOrWhiteSpace(nickname))
                {
                    return(nickname);
                }
                try
                {
                    var name = Path.GetFileName(Path.GetDirectoryName(path));
                    if (string.IsNullOrWhiteSpace(name))
                    {
                        return(string.Empty);
                    }
                    return(name);
                }
                catch (Exception)
                {
                    return(string.Empty);
                }
            })
                           .ToProperty(this, nameof(DisplayName), Nickname);

            AvailableProjects = SolutionPatcherConfigLogic.AvailableProject(
                this.WhenAnyValue(x => x.SolutionPath.TargetPath))
                                .ObserveOnGui()
                                .ToObservableCollection(this);

            var projPath = SolutionPatcherConfigLogic.ProjectPath(
                solutionPath: this.WhenAnyValue(x => x.SolutionPath.TargetPath),
                projectSubpath: this.WhenAnyValue(x => x.ProjectSubpath));

            projPath
            .Subscribe(p => SelectedProjectPath.TargetPath = p)
            .DisposeWith(this);

            _State = Observable.CombineLatest(
                this.WhenAnyValue(x => x.SolutionPath.ErrorState),
                this.WhenAnyValue(x => x.SelectedProjectPath.ErrorState),
                this.WhenAnyValue(x => x.Profile.Config.MainVM)
                .Select(x => x.DotNetSdkInstalled)
                .Switch(),
                (sln, proj, dotnet) =>
            {
                if (sln.Failed)
                {
                    return(new ConfigurationState(sln));
                }
                if (!dotnet.Acceptable)
                {
                    return(new ConfigurationState(ErrorResponse.Fail("No dotnet SDK installed")));
                }
                return(new ConfigurationState(proj));
            })
                     .ToGuiProperty <ConfigurationState>(this, nameof(State), new ConfigurationState(ErrorResponse.Fail("Evaluating"))
            {
                IsHaltingError = false
            });

            OpenSolutionCommand = ReactiveCommand.Create(
                canExecute: this.WhenAnyValue(x => x.SolutionPath.InError)
                .Select(x => !x),
                execute: () =>
            {
                try
                {
                    Process.Start(new ProcessStartInfo(SolutionPath.TargetPath)
                    {
                        UseShellExecute = true,
                    });
                }
                catch (Exception ex)
                {
                    Log.Logger.Error(ex, $"Error opening solution: {SolutionPath.TargetPath}");
                }
            });

            var metaPath = this.WhenAnyValue(x => x.SelectedProjectPath.TargetPath)
                           .Select(projPath =>
            {
                try
                {
                    return(Path.Combine(Path.GetDirectoryName(projPath) !, Constants.MetaFileName));
                }
                catch (Exception)
                {
                    return(string.Empty);
                }
            })
                           .Replay(1)
                           .RefCount();

            // Set up meta file sync
            metaPath
            .Select(path =>
            {
                return(Noggog.ObservableExt.WatchFile(path)
                       .StartWith(Unit.Default)
                       .Throttle(TimeSpan.FromMilliseconds(500), RxApp.MainThreadScheduler)
                       .Select(_ =>
                {
                    if (!File.Exists(path))
                    {
                        return default;
                    }
                    try
                    {
                        return JsonConvert.DeserializeObject <PatcherCustomization>(
                            File.ReadAllText(path),
                            Execution.Constants.JsonSettings);
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex, "Error reading in meta");
                    }
                    return default(PatcherCustomization?);
                }));
            })
            .Switch()
            .DistinctUntilChanged()
            .ObserveOnGui()
            .Subscribe(info =>
            {
                if (info == null)
                {
                    return;
                }
                if (info.Nickname != null)
                {
                    this.Nickname = info.Nickname;
                }
                this.LongDescription  = info.LongDescription ?? string.Empty;
                this.ShortDescription = info.OneLineDescription ?? string.Empty;
                this.Visibility       = info.Visibility;
                this.Versioning       = info.PreferredAutoVersioning;
                this.RequiredMods.SetTo(info.RequiredMods
                                        .SelectWhere(x => TryGet <ModKey> .Create(ModKey.TryFromNameAndExtension(x, out var modKey), modKey))
                                        .Select(m => new ModKeyItemViewModel(m)));
            })
            .DisposeWith(this);

            Observable.CombineLatest(
                this.WhenAnyValue(x => x.DisplayName),
                this.WhenAnyValue(x => x.ShortDescription),
                this.WhenAnyValue(x => x.LongDescription),
                this.WhenAnyValue(x => x.Visibility),
                this.WhenAnyValue(x => x.Versioning),
                this.RequiredMods
                .ToObservableChangeSet()
                .Transform(x => x.ModKey)
                .AddKey(x => x)
                .Sort(ModKey.Alphabetical, SortOptimisations.ComparesImmutableValuesOnly, resetThreshold: 0)
                .QueryWhenChanged()
                .Select(x => x.Items)
                .StartWith(Enumerable.Empty <ModKey>()),
                metaPath,
                (nickname, shortDesc, desc, visibility, versioning, reqMods, meta) => (nickname, shortDesc, desc, visibility, versioning, reqMods: reqMods.Select(x => x.FileName).OrderBy(x => x).ToArray(), meta))
            .DistinctUntilChanged()
            .Throttle(TimeSpan.FromMilliseconds(200), RxApp.MainThreadScheduler)
            .Skip(1)
            .Subscribe(x =>
            {
                try
                {
                    if (string.IsNullOrWhiteSpace(x.meta))
                    {
                        return;
                    }
                    File.WriteAllText(x.meta,
                                      JsonConvert.SerializeObject(
                                          new PatcherCustomization()
                    {
                        OneLineDescription      = x.shortDesc,
                        LongDescription         = x.desc,
                        Visibility              = x.visibility,
                        Nickname                = x.nickname,
                        PreferredAutoVersioning = x.versioning,
                        RequiredMods            = x.reqMods
                    },
                                          Formatting.Indented,
                                          Execution.Constants.JsonSettings));
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "Error writing out meta");
                }
            })
            .DisposeWith(this);

            ReloadAutogeneratedSettingsCommand = ReactiveCommand.Create(() => { });
            PatcherSettings = new PatcherSettingsVM(
                Logger,
                this,
                projPath
                .Merge(ReloadAutogeneratedSettingsCommand.EndingExecution()
                       .WithLatestFrom(projPath, (_, p) => p))
                .Select(p => (GetResponse <string> .Succeed(p), default(string?))),
                needBuild: true)
                              .DisposeWith(this);
        }
Пример #13
0
 public ModKey ParseModKey()
 {
     ModKey.TryFromNameAndExtension(OblivionMaster, out var modKey);
     return(modKey);
 }