Exemple #1
0
        /// <summary>
        /// Called when [activated].
        /// </summary>
        /// <param name="disposables">The disposables.</param>
        protected override void OnActivated(CompositeDisposable disposables)
        {
            ShowAdvancedFeatures = (gameService.GetSelected()?.AdvancedFeaturesSupported).GetValueOrDefault();

            var allowModSelectionEnabled = this.WhenAnyValue(v => v.AllowModSelection);

            RenameCommand = ReactiveCommand.Create(() =>
            {
                return(new CommandResult <ModifyAction>(ModifyAction.Rename, CommandState.Success));
            }, allowModSelectionEnabled).DisposeWith(disposables);

            DuplicateCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                if (ActiveCollection != null)
                {
                    var copy = CopyCollection(ActiveCollection.Name);
                    if (modCollectionService.Save(copy))
                    {
                        var id = idGenerator.GetNextId();
                        await TriggerOverlayAsync(id, true, localizationManager.GetResource(LocalizationResources.Collection_Mods.Overlay_Duplicate_Message));
                        await Task.Run(async() =>
                        {
                            await modPatchCollectionService.CopyPatchCollectionAsync(ActiveCollection.Name, copy.Name).ConfigureAwait(false);
                        }).ConfigureAwait(false);
                        await TriggerOverlayAsync(id, false);
                        return(new CommandResult <ModifyAction>(ModifyAction.Duplicate, CommandState.Success));
                    }
                    else
                    {
                        return(new CommandResult <ModifyAction>(ModifyAction.Duplicate, CommandState.Failed));
                    }
                }
                return(new CommandResult <ModifyAction>(ModifyAction.Duplicate, CommandState.NotExecuted));
            }, allowModSelectionEnabled).DisposeWith(disposables);

            MergeOpenCommand = ReactiveCommand.Create(() =>
            {
                IsMergeOpen = true;
            }, allowModSelectionEnabled).DisposeWith(disposables);

            MergeCloseCommand = ReactiveCommand.Create(() =>
            {
                IsMergeOpen = false;
            }).DisposeWith(disposables);

            MergeAdvancedCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                if (ActiveCollection != null && ActiveCollection.Mods?.Count() > 0)
                {
                    var copy = await GetMergedCollectionAsync();

                    var id = idGenerator.GetNextId();
                    await TriggerOverlayAsync(id, true, localizationManager.GetResource(LocalizationResources.App.WaitBackgroundOperationMessage));
                    await shutDownState.WaitUntilFreeAsync();

                    var savedCollection = modCollectionService.GetAll().FirstOrDefault(p => p.IsSelected);
                    while (savedCollection == null)
                    {
                        await Task.Delay(25);
                        savedCollection = modCollectionService.GetAll().FirstOrDefault(p => p.IsSelected);
                    }

                    SubscribeToProgressReports(id, disposables, MergeType.Advanced);

                    var mode = await modPatchCollectionService.GetPatchStateModeAsync(ActiveCollection.Name);
                    if (mode == PatchStateMode.None)
                    {
                        // fallback to default mod if no patch collection specified
                        mode = PatchStateMode.Default;
                    }

                    var overlayProgress = Smart.Format(localizationManager.GetResource(LocalizationResources.Collection_Mods.MergeCollection.Overlay_Progress), new
                    {
                        PercentDone = 0.ToLocalizedPercentage(),
                        Count       = 1,
                        TotalCount  = 4
                    });
                    var message = localizationManager.GetResource(LocalizationResources.Collection_Mods.MergeCollection.Advanced.Overlay_Loading_Definitions);
                    await TriggerOverlayAsync(id, true, message, overlayProgress);

                    modPatchCollectionService.ResetPatchStateCache();
                    var definitions = await Task.Run(async() =>
                    {
                        return(await modPatchCollectionService.GetModObjectsAsync(gameService.GetSelected(), SelectedMods, copy.Name).ConfigureAwait(false));
                    }).ConfigureAwait(false);

                    var conflicts = await Task.Run(() =>
                    {
                        if (definitions != null)
                        {
                            return(modPatchCollectionService.FindConflicts(definitions, SelectedMods.Select(p => p.Name).ToList(), mode));
                        }
                        return(null);
                    }).ConfigureAwait(false);

                    await modPatchCollectionService.CleanPatchCollectionAsync(copy.Name);

                    var mergeMod = await Task.Run(async() =>
                    {
                        return(await modMergeService.MergeCollectionByDefinitionsAsync(conflicts, SelectedMods.Select(p => p.Name).ToList(), copy.Name).ConfigureAwait(false));
                    }).ConfigureAwait(false);
                    copy.Mods = new List <string>()
                    {
                        mergeMod.DescriptorFile
                    };

                    await TriggerOverlayAsync(id, false);

                    definitionAnalyzeLoadHandler?.Dispose();
                    definitionLoadHandler?.Dispose();
                    definitionMergeProgressHandler?.Dispose();

                    modCollectionService.Delete(copy.Name);
                    modPatchCollectionService.InvalidatePatchModState(copy.Name);
                    if (modCollectionService.Save(copy))
                    {
                        return(new CommandResult <ModifyAction>(ModifyAction.Merge, CommandState.Success));
                    }
                    else
                    {
                        return(new CommandResult <ModifyAction>(ModifyAction.Merge, CommandState.Failed));
                    }
                }
                return(new CommandResult <ModifyAction>(ModifyAction.Merge, CommandState.NotExecuted));
            }, allowModSelectionEnabled).DisposeWith(disposables);

            MergeBasicCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                if (ActiveCollection != null && ActiveCollection.Mods?.Count() > 0)
                {
                    var copy = await GetMergedCollectionAsync();
                    var id   = idGenerator.GetNextId();

                    await TriggerOverlayAsync(id, true, localizationManager.GetResource(LocalizationResources.App.WaitBackgroundOperationMessage));
                    await shutDownState.WaitUntilFreeAsync();

                    var savedCollection = modCollectionService.GetAll().FirstOrDefault(p => p.IsSelected);
                    while (savedCollection == null)
                    {
                        await Task.Delay(25);
                        savedCollection = modCollectionService.GetAll().FirstOrDefault(p => p.IsSelected);
                    }

                    SubscribeToProgressReports(id, disposables, MergeType.Basic);

                    var overlayProgress = Smart.Format(localizationManager.GetResource(LocalizationResources.Collection_Mods.MergeCollection.Overlay_Progress), new
                    {
                        PercentDone = 0.ToLocalizedPercentage(),
                        Count       = 1,
                        TotalCount  = 2
                    });
                    var message = localizationManager.GetResource(LocalizationResources.Collection_Mods.MergeCollection.Basic.Overlay_Gathering_Mod_Info);
                    await TriggerOverlayAsync(id, true, message, overlayProgress);

                    await modPatchCollectionService.CleanPatchCollectionAsync(copy.Name);

                    var mergeMod = await Task.Run(async() =>
                    {
                        return(await modMergeService.MergeCollectionByFilesAsync(copy.Name));
                    }).ConfigureAwait(false);
                    copy.Mods = new List <string>()
                    {
                        mergeMod.DescriptorFile
                    };

                    await TriggerOverlayAsync(id, false);
                    fileMergeProgressHandler?.Dispose();

                    modCollectionService.Delete(copy.Name);
                    modPatchCollectionService.InvalidatePatchModState(copy.Name);
                    if (modCollectionService.Save(copy))
                    {
                        return(new CommandResult <ModifyAction>(ModifyAction.Merge, CommandState.Success));
                    }
                    else
                    {
                        return(new CommandResult <ModifyAction>(ModifyAction.Merge, CommandState.Failed));
                    }
                }
                return(new CommandResult <ModifyAction>(ModifyAction.Merge, CommandState.NotExecuted));
            }, allowModSelectionEnabled).DisposeWith(disposables);

            MergeCompressCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                if (ActiveCollection != null && ActiveCollection.Mods?.Count() > 0)
                {
                    var copy = await GetMergedCollectionAsync();
                    var id   = idGenerator.GetNextId();

                    await TriggerOverlayAsync(id, true, localizationManager.GetResource(LocalizationResources.App.WaitBackgroundOperationMessage));
                    await shutDownState.WaitUntilFreeAsync();

                    var savedCollection = modCollectionService.GetAll().FirstOrDefault(p => p.IsSelected);
                    while (savedCollection == null)
                    {
                        await Task.Delay(25);
                        savedCollection = modCollectionService.GetAll().FirstOrDefault(p => p.IsSelected);
                    }

                    SubscribeToProgressReports(id, disposables, MergeType.Compress);

                    var overlayProgress = Smart.Format(localizationManager.GetResource(LocalizationResources.Collection_Mods.MergeCollection.Overlay_Progress), new
                    {
                        PercentDone = 0.ToLocalizedPercentage(),
                        Count       = 1,
                        TotalCount  = 2
                    });
                    var message = localizationManager.GetResource(LocalizationResources.Collection_Mods.MergeCollection.Compress.Overlay_Gathering_Mod_Info);
                    await TriggerOverlayAsync(id, true, message, overlayProgress);

                    await modPatchCollectionService.CleanPatchCollectionAsync(copy.Name);

                    var mergeMods = await Task.Run(async() =>
                    {
                        return(await modMergeService.MergeCompressCollectionAsync(copy.Name, Smart.Format(localizationManager.GetResource(LocalizationResources.Collection_Mods.MergeCollection.MergeCompressModPrefix), new
                        {
                            Name = copy.Name.Replace($"{localizationManager.GetResource(LocalizationResources.Collection_Mods.MergeCollection.MergedCollectionPrefix)} ", string.Empty)
                        })));
                    }).ConfigureAwait(false);
                    copy.Mods = mergeMods.Select(p => p.DescriptorFile).ToList();

                    await TriggerOverlayAsync(id, false);
                    fileMergeProgressHandler?.Dispose();

                    modCollectionService.Delete(copy.Name);
                    modPatchCollectionService.InvalidatePatchModState(copy.Name);
                    await modService.InstallModsAsync(null);
                    if (modCollectionService.Save(copy))
                    {
                        return(new CommandResult <ModifyAction>(ModifyAction.Merge, CommandState.Success));
                    }
                    else
                    {
                        return(new CommandResult <ModifyAction>(ModifyAction.Merge, CommandState.Failed));
                    }
                }
                return(new CommandResult <ModifyAction>(ModifyAction.Merge, CommandState.NotExecuted));
            }, allowModSelectionEnabled).DisposeWith(disposables);

            base.OnActivated(disposables);
        }
        /// <summary>
        /// Called when [activated].
        /// </summary>
        /// <param name="disposables">The disposables.</param>
        protected override void OnActivated(CompositeDisposable disposables)
        {
            Task.Run(() => EvalResumeAvailabilityLoopAsync().ConfigureAwait(false));

            ShowAdvancedFeatures = (gameService.GetSelected()?.AdvancedFeaturesSupported).GetValueOrDefault();
            AnalyzeClass         = string.Empty;

            var allowModSelectionEnabled = this.WhenAnyValue(v => v.AllowModSelection);
            var applyEnabled             = Observable.Merge(this.WhenAnyValue(v => v.ApplyingCollection, v => !v), allowModSelectionEnabled);

            this.WhenAnyValue(v => v.CollectionMods.SelectedModCollection).Subscribe(s =>
            {
                if (s != null)
                {
                    AllowModSelection = true;
                    InstalledMods.AllowModSelection  = true;
                    CollectionMods.AllowModSelection = true;
                }
                else
                {
                    AllowModSelection = false;
                    InstalledMods.AllowModSelection  = false;
                    CollectionMods.AllowModSelection = false;
                }
                InstallModsAsync().ConfigureAwait(true);
            }).DisposeWith(disposables);

            this.WhenAnyValue(v => v.InstalledMods.Mods).Subscribe(v =>
            {
                CollectionMods.SetMods(v, InstalledMods.ActiveGame);
            });

            this.WhenAnyValue(v => v.InstalledMods.RefreshingMods).Subscribe(s =>
            {
                CollectionMods.HandleModRefresh(s, InstalledMods.Mods, InstalledMods.ActiveGame);
            }).DisposeWith(disposables);

            this.WhenAnyValue(v => v.CollectionMods.NeedsModListRefresh).Where(x => x).Subscribe(s =>
            {
                InstalledMods.RefreshMods();
            }).DisposeWith(disposables);

            this.WhenAnyValue(p => p.InstalledMods.PerformingEnableAll).Subscribe(s =>
            {
                CollectionMods.HandleEnableAllToggled(s, InstalledMods.AllModsEnabled, InstalledMods.FilteredMods);
            }).DisposeWith(disposables);

            ApplyCommand = ReactiveCommand.Create(() =>
            {
                ApplyCollectionAsync(idGenerator.GetNextId()).ConfigureAwait(true);
            }, applyEnabled).DisposeWith(disposables);

            AnalyzeCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                var game = gameService.GetSelected();
                if (game != null && CollectionMods.SelectedMods?.Count > 0 && CollectionMods.SelectedModCollection != null)
                {
                    var id = idGenerator.GetNextId();
                    await TriggerOverlayAsync(id, true, localizationManager.GetResource(LocalizationResources.App.WaitBackgroundOperationMessage));
                    await shutDownState.WaitUntilFreeAsync();
                    modPatchCollectionService.ResetPatchStateCache();
                    var mode = await modPatchCollectionService.GetPatchStateModeAsync(CollectionMods.SelectedModCollection.Name);
                    if (mode == PatchStateMode.None)
                    {
                        await TriggerOverlayAsync(id, false);
                        await Task.Delay(50);
                        IsModeOpen = true;
                    }
                    else
                    {
                        await AnalyzeModsAsync(id, mode);
                    }
                }
            }, allowModSelectionEnabled).DisposeWith(disposables);

            async Task <bool> ensureSteamIsRunning(IGameSettings args)
            {
                if (gameService.IsSteamGame(args))
                {
                    // Check if process is running
                    var processes = Process.GetProcesses();
                    if (!processes.Any(p => p.ProcessName.Equals(SteamProcess, StringComparison.OrdinalIgnoreCase)))
                    {
                        await appAction.OpenAsync(SteamLaunch);

                        var attempts = 0;
                        while (!processes.Any(p => p.ProcessName.Equals(SteamProcess, StringComparison.OrdinalIgnoreCase)))
                        {
                            if (attempts > 3)
                            {
                                break;
                            }
                            await Task.Delay(3000);

                            processes = Process.GetProcesses();
                            attempts++;
                        }
                    }
                }
                return(true);
            }

            async Task launchGame(bool continueGame)
            {
                var game = gameService.GetSelected();

                if (game != null)
                {
                    var args = gameService.GetLaunchSettings(game, continueGame);
                    if (!string.IsNullOrWhiteSpace(args.ExecutableLocation))
                    {
                        var id = idGenerator.GetNextId();
                        await TriggerOverlayAsync(id, true, localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.Overlay));

                        if (game.RefreshDescriptors)
                        {
                            await modService.DeleteDescriptorsAsync(InstalledMods.Mods);

                            await modService.InstallModsAsync(InstalledMods.Mods);
                        }
                        await ApplyCollectionAsync(id, false);

                        await MessageBus.PublishAsync(new LaunchingGameEvent(game.Type));

                        if (gameService.IsSteamLaunchPath(args))
                        {
                            if (await appAction.OpenAsync(args.ExecutableLocation))
                            {
                                if (game.CloseAppAfterGameLaunch)
                                {
                                    await appAction.ExitAppAsync();
                                }
                            }
                            else
                            {
                                notificationAction.ShowNotification(localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.LaunchError.Title),
                                                                    localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.LaunchError.Message), NotificationType.Error, 10);
                                await TriggerOverlayAsync(id, false);
                            }
                        }
                        else
                        {
                            await ensureSteamIsRunning(args);

                            if (await appAction.RunAsync(args.ExecutableLocation, args.LaunchArguments))
                            {
                                if (game.CloseAppAfterGameLaunch)
                                {
                                    await appAction.ExitAppAsync();
                                }
                                else
                                {
                                    await TriggerOverlayAsync(id, false);
                                }
                            }
                            else
                            {
                                notificationAction.ShowNotification(localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.LaunchError.Title),
                                                                    localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.LaunchError.Message), NotificationType.Error, 10);
                                await TriggerOverlayAsync(id, false);
                            }
                        }
                    }
                    else
                    {
                        notificationAction.ShowNotification(localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.NotSet.Title),
                                                            localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.NotSet.Message), NotificationType.Warning, 10);
                    }
                }
            }

            LaunchGameCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                await launchGame(false);
            }, allowModSelectionEnabled).DisposeWith(disposables);

            ResumeGameCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                await launchGame(true);
            }, allowModSelectionEnabled).DisposeWith(disposables);

            AdvancedModeCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                await AnalyzeModsAsync(idGenerator.GetNextId(), PatchStateMode.Advanced);
            }).DisposeWith(disposables);

            DefaultModeCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                await AnalyzeModsAsync(idGenerator.GetNextId(), PatchStateMode.Default);
            }).DisposeWith(disposables);

            CloseModeCommand = ReactiveCommand.Create(() =>
            {
                ForceClosePopups();
            }).DisposeWith(disposables);

            var previousCollectionNotification = string.Empty;

            CollectionMods.ConflictSolverStateChanged += (collectionName, state) =>
            {
                AnalyzeClass = !state ? InvalidConflictSolverClass : string.Empty;
                if (!state && previousCollectionNotification != collectionName)
                {
                    notificationAction.ShowNotification(localizationManager.GetResource(LocalizationResources.Notifications.ConflictSolverUpdate.Title),
                                                        localizationManager.GetResource(LocalizationResources.Notifications.ConflictSolverUpdate.Message), NotificationType.Warning, 30);
                    previousCollectionNotification = collectionName;
                }
            };

            gameDirectoryChangedHandler.Message.Subscribe(s =>
            {
                InstalledMods.RefreshMods();
                EvalResumeAvailability(s.Game);
            }).DisposeWith(disposables);

            this.WhenAnyValue(v => v.InstalledMods.ModFilePopulationInCompleted).Subscribe(s =>
            {
                CollectionMods.CanExportModHashReport = s;
            }).DisposeWith(disposables);

            base.OnActivated(disposables);
        }