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); }
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); }
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); }
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); }
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); }
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)); } } }
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> >())); }
public void TryFactory_ImproperSuffix() { Assert.False(ModKey.TryFromNameAndExtension("Obliv.ion.esn", out var modKey)); }
public void TryFactory_InvalidChars() { Assert.False(ModKey.TryFromNameAndExtension("Obliv>ion.esm", out var modKey)); }
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); }
public ModKey ParseModKey() { ModKey.TryFromNameAndExtension(OblivionMaster, out var modKey); return(modKey); }