public ResolverManagerModResultPair(IModResolver resolver, IUpdateManager manager, CheckForUpdatesResult result, PathTuple <ModConfig> modTuple)
 {
     Resolver = resolver;
     Manager  = manager;
     Result   = result;
     ModTuple = modTuple;
 }
    /// <summary>
    /// Applies an individual application item to a given application configuration.
    /// </summary>
    /// <param name="indexApp">Index entry for the application.</param>
    /// <param name="pathTuple">The mod to apply the config to.</param>
    public static void ApplyIndexEntry(AppItem indexApp, PathTuple <ApplicationConfig> pathTuple)
    {
        using var fileStream = new FileStream(ApplicationConfig.GetAbsoluteAppLocation(pathTuple), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 524288);
        var hash = Hashing.ToString(xxHash64.ComputeHash(fileStream));

        ApplyIndexEntry(indexApp, pathTuple, hash);
    }
Exemplo n.º 3
0
    /// <summary>
    /// Converts the relative or absolute application location to a full path.
    /// </summary>
    /// <returns>The full path to the app location.</returns>
    public static string GetAbsoluteAppLocation(PathTuple <ApplicationConfig> config)
    {
        var    location = config.Config.AppLocation;
        var    basePath = Path.GetDirectoryName(config.Path) !;
        string finalPath;

        // Specific for windows paths starting on \ - they need the drive added to them.
        // I constructed this piece like this for possible Mono support.
        if (!Path.IsPathRooted(location) || "\\".Equals(Path.GetPathRoot(location)))
        {
            if (location.StartsWith(Path.DirectorySeparatorChar))
            {
                finalPath = Path.Combine(Path.GetPathRoot(basePath) !, location.TrimStart(Path.DirectorySeparatorChar));
            }
            else
            {
                finalPath = Path.Combine(basePath, location);
            }
        }
        else
        {
            finalPath = location;
        }

        // Resolves any internal "..\" to get the true full path.
        return(Path.GetFullPath(finalPath));
    }
        public bool IsCompatible(PathTuple <ModConfig> mod)
        {
            var modDirectory = Path.GetDirectoryName(mod.Path);

            ConfigPath = GameBananaConfig.GetFilePath(modDirectory);
            return(File.Exists(ConfigPath));
        }
Exemplo n.º 5
0
        /// <summary>
        /// Builds the initial set of mods to display in the list.
        /// </summary>
        private List <ModEntry> GetInitialModSet(ApplicationViewModel model, PathTuple <ApplicationConfig> applicationTuple)
        {
            // Note: Must put items in top to bottom load order.
            var enabledModIds  = applicationTuple.Config.EnabledMods;
            var modsForThisApp = model.ModsForThisApp.ToArray();

            // Get dictionary of mods for this app by Mod ID
            var modDictionary = new Dictionary <string, PathTuple <ModConfig> >();

            foreach (var mod in modsForThisApp)
            {
                modDictionary[mod.Config.ModId] = mod;
            }

            // Add enabled mods.
            var totalModList = new List <ModEntry>(modsForThisApp.Length);

            foreach (var enabledModId in enabledModIds)
            {
                if (modDictionary.ContainsKey(enabledModId))
                {
                    totalModList.Add(MakeSaveSubscribedModEntry(true, modDictionary[enabledModId]));
                }
            }

            // Add disabled mods.
            var enabledModIdSet = applicationTuple.Config.EnabledMods.ToHashSet();
            var disabledMods    = modsForThisApp.Where(x => !enabledModIdSet.Contains(x.Config.ModId));

            totalModList.AddRange(disabledMods.Select(x => MakeSaveSubscribedModEntry(false, x)));
            return(totalModList);
        }
        public SetDependenciesDialogViewmodel(ModConfigService configService, PathTuple <ModConfig> modConfig)
        {
            ConfigService = configService;
            CurrentMod    = modConfig;

            PopulateDependencies();
        }
    /// <summary>
    /// Returns the first appropriate provider that can handle fetching packages for a game.
    /// </summary>
    /// <param name="application">The application in question.</param>
    /// <param name="nugetRepositories">[Optional] NuGet repositories to use.</param>
    /// <returns>A resolver that can handle the mod, else null.</returns>
    public static AggregatePackageProvider?GetProvider(PathTuple <ApplicationConfig> application, IEnumerable <INugetRepository>?nugetRepositories = null)
    {
        // Create resolvers.
        var providers = new List <IDownloadablePackageProvider>();

        foreach (var factory in All)
        {
            var provider = factory.GetProvider(application);
            if (provider != null)
            {
                providers.Add(provider);
            }
        }

        // Add NuGets.
        if (nugetRepositories != null)
        {
            foreach (var nugetRepo in nugetRepositories)
            {
                providers.Add(new IndexedNuGetPackageProvider(nugetRepo, application.Config.AppId));
            }
        }

        return(providers.Count > 0 ? new AggregatePackageProvider(providers.ToArray(), application.Config.AppName) : null);
    }
Exemplo n.º 8
0
        /* Mod Loading */

        /// <summary>
        /// Obtains an instance of an individual ready to load mod.
        /// To start an instance, call <see cref="StartMod"/>
        /// </summary>
        /// <exception cref="ArgumentException">Mod with specified ID is already loaded.</exception>
        /// <param name="tuple">A tuple of mod config and path to config.</param>
        private ModInstance GetModInstance(PathTuple <ModConfig> tuple)
        {
            // Check if mod with ID already loaded.
            if (IsModLoaded(tuple.Config.ModId))
            {
                throw new ReloadedException(Errors.ModAlreadyLoaded(tuple.Config.ModId));
            }

            // Load DLL or non-dll mod.
            if (tuple.Config.HasDllPath())
            {
                var dllPath = tuple.Config.GetDllPath(tuple.Path);
                if (File.Exists(dllPath))
                {
                    return(tuple.Config.IsNativeMod(tuple.Path) ? PrepareNativeMod(tuple) : PrepareDllMod(tuple));
                }
                else
                {
                    _loader?.Logger?.WriteLineAsync(AddLogPrefix($"DLL Not Found! {Path.GetFileName(dllPath)}\n" +
                                                                 $"Mod Name: {tuple.Config.ModName}, Mod ID: {tuple.Config.ModId}\n" +
                                                                 $"Please re-download the mod. It is either corrupt or you may have downloaded the source code by accident."), _loader.Logger.ColorRed);
                }
            }

            return(PrepareNonDllMod(tuple));
        }
    /// <summary>
    /// Returns the first appropriate resolver that can handle updating a mod.
    /// </summary>
    /// <param name="mod">The mod in question.</param>
    /// <param name="userConfig">Contains user configuration for this mod in question.</param>
    /// <param name="data">All data passed to the updater.</param>
    /// <returns>A resolver that can handle the mod, else null.</returns>
    public static AggregatePackageResolverEx?GetResolver(PathTuple <ModConfig> mod, PathTuple <ModUserConfig>?userConfig, UpdaterData data)
    {
        // Migrate first
        foreach (var factory in All)
        {
            factory.Migrate(mod, userConfig);
        }

        // Clone data preferences.
        data = data.DeepClone();
        if (userConfig?.Config.AllowPrereleases != null)
        {
            data.CommonPackageResolverSettings.AllowPrereleases = userConfig.Config.AllowPrereleases.Value;
        }

        data.CommonPackageResolverSettings.MetadataFileName = mod.Config.ReleaseMetadataFileName;

        // Create resolvers.
        var resolvers  = new List <IPackageResolver>();
        var extractors = new Dictionary <IPackageResolver, IPackageExtractor>();

        foreach (var factory in All)
        {
            var resolver = factory.GetResolver(mod, userConfig, data);
            if (resolver != null)
            {
                resolvers.Add(resolver);
                extractors[resolver] = factory.Extractor;
            }
        }

        return(resolvers.Count > 0 ? new AggregatePackageResolverEx(resolvers, extractors) : null);
    }
    /// <summary>
    /// Applies an individual application item to a given application configuration.
    /// </summary>
    /// <param name="indexApp">Index entry for the application.</param>
    /// <param name="pathTuple">The mod to apply the config to.</param>
    /// <param name="hash">Hash of the application's main executable.</param>
    public static void ApplyIndexEntry(AppItem indexApp, PathTuple <ApplicationConfig> pathTuple, string hash)
    {
        var hashMatches = hash.Equals(indexApp.Hash, StringComparison.OrdinalIgnoreCase);

        if (indexApp.AppStatus == Status.WrongExecutable && hashMatches)
        {
            Actions.DisplayMessagebox(Resources.AddAppRepoBadExecutable.Get(), indexApp.BadStatusDescription !);
        }

        pathTuple.Config.AppName = indexApp.AppName;
        // Apply GB Configurations
        Singleton <GameBananaPackageProviderFactory> .Instance.SetConfiguration(pathTuple,
                                                                                new GameBananaPackageProviderFactory.GameBananaProviderConfig()
        {
            GameId = (int)indexApp.GameBananaId
        });

        if (!hashMatches)
        {
            var viewModel = new AddAppHashMismatchDialogViewModel(indexApp.BadHashDescription !);
            Actions.ShowAddAppHashMismatchDialog(viewModel);
        }

        var appLocation = ApplicationConfig.GetAbsoluteAppLocation(pathTuple);

        if (indexApp.TryGetError(Path.GetDirectoryName(appLocation) !, out var errors))
        {
            var viewModel = new AddApplicationWarningDialogViewModel(errors);
            Actions.ShowApplicationWarningDialog(viewModel);
        }
    }
Exemplo n.º 11
0
    /// <inheritdoc />
    public bool TryGetConfigurationOrDefault(PathTuple <ApplicationConfig> mod, out object configuration)
    {
        var result = this.TryGetConfiguration <GameBananaProviderConfig>(mod, out var config);

        configuration = config ?? new GameBananaProviderConfig();
        return(result);
    }
 private void RemoveItem(PathTuple <TConfigType> itemTuple)
 {
     ItemsByPath.Remove(itemTuple.Path);
     ItemsByFolder.Remove(Path.GetDirectoryName(itemTuple.Path));
     Items.Remove(itemTuple);
     OnRemoveItem?.Invoke(itemTuple);
 }
    /// <summary>
    /// Obtains an image to represent a given application.
    /// The image is either a custom one or the icon of the application.
    /// </summary>
    private ImageSource GetImageForAppConfig(PathTuple <ApplicationConfig> applicationConfig)
    {
        // Check if custom icon exists.
        if (!string.IsNullOrEmpty(applicationConfig.Config.AppIcon))
        {
            if (ApplicationConfig.TryGetApplicationIcon(applicationConfig.Path, applicationConfig.Config, out var applicationIcon))
            {
                return(Misc.Imaging.BitmapFromUri(new Uri(applicationIcon, UriKind.Absolute)));
            }
        }

        // Otherwise extract new icon from executable.
        var appLocation = ApplicationConfig.GetAbsoluteAppLocation(applicationConfig);

        if (File.Exists(appLocation))
        {
            // Else make new from icon.
            using Icon? ico = Icon.ExtractAssociatedIcon(appLocation);
            if (ico != null)
            {
                // Extract to config set location.
                BitmapSource bitmapImage = Imaging.CreateBitmapSourceFromHIcon(ico.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                bitmapImage.Freeze();
                return(bitmapImage);
            }
        }

        return(Misc.Imaging.GetPlaceholderIcon());
    }
    private DateTime GetApproximateDateForMod(PathTuple <ModConfig> mod)
    {
        try
        {
            // Check date on the DLL
            if (mod.Config.HasDllPath())
            {
                var dllPath = mod.Config.GetDllPath(mod.Path);
                if (!File.Exists(dllPath))
                {
                    goto checkIcon;
                }

                return(File.GetLastWriteTimeUtc(dllPath));
            }

            // Otherwise fallback to icon, if possible.
checkIcon:
            return(!mod.Config.TryGetIconPath(mod.Path, out var iconPath) ? DateTime.UtcNow : File.GetLastWriteTimeUtc(iconPath));
        }
        catch (Exception)
        {
            return(DateTime.UtcNow);
        }
    }
    /// <inheritdoc />
    public bool TryGetConfigurationOrDefault(PathTuple <ModConfig> mod, out object configuration)
    {
        var result = this.TryGetConfiguration <NuGetConfig>(mod, out var config);

        configuration = config ?? new NuGetConfig();
        return(result);
    }
Exemplo n.º 16
0
        private ModEntry MakeSaveSubscribedModEntry(bool?isEnabled, PathTuple <ModConfig> item)
        {
            // Make BooleanGenericTuple that saves application on Enabled change.
            var tuple = new ModEntry(isEnabled, item);

            tuple.PropertyChanged += SaveOnEnabledPropertyChanged;
            return(tuple);
        }
Exemplo n.º 17
0
        private ModInstance PrepareNativeMod(PathTuple <ModConfig> tuple)
        {
            var modId   = tuple.Config.ModId;
            var dllPath = tuple.Config.GetNativeDllPath(tuple.Path);

            _modIdToFolder[modId] = Path.GetFullPath(Path.GetDirectoryName(tuple.Path));
            return(new ModInstance(new NativeMod(dllPath), tuple.Config));
        }
Exemplo n.º 18
0
    /// <inheritdoc />
    public IDownloadablePackageProvider?GetProvider(PathTuple <ApplicationConfig> mod)
    {
        if (!this.TryGetConfiguration <GameBananaProviderConfig>(mod, out var gbConfig))
        {
            return(null);
        }

        return(new IndexedGameBananaPackageProvider(gbConfig !.GameId));
    }
        public void Construct(PathTuple <ModConfig> mod)
        {
            _modTuple = mod;
            string path = GitHubConfig.GetFilePath(GetModDirectory(mod));

            _githubConfig = IConfig <GitHubConfig> .FromPath(path);

            _githubUserConfig = IConfig <GitHubUserConfig> .FromPath(path);
        }
Exemplo n.º 20
0
    /// <summary>
    /// Saves a given mod tuple to the hard disk.
    /// </summary>
    public void SaveMod(PathTuple <ModConfig>?oldModTuple)
    {
        if (oldModTuple == null)
        {
            return;
        }

        oldModTuple.Config.SupportedAppId = EnabledAppIds.Where(x => x.Enabled).Select(x => x.Generic.AppId).ToArray();
        oldModTuple.SaveAsync();
    }
    /// <inheritdoc/>
    public IPackageResolver?GetResolver(PathTuple <ModConfig> mod, PathTuple <ModUserConfig>?userConfig, UpdaterData data)
    {
        var resolvers = new List <IPackageResolver>();
        var urls      = new HashSet <string>();

        // Get all URLs
        if (this.TryGetConfiguration <NuGetConfig>(mod, out var nugetConfig))
        {
            foreach (var url in nugetConfig !.DefaultRepositoryUrls)
            {
                urls.Add(url);
            }

            if (nugetConfig.AllowUpdateFromAnyRepository)
            {
                foreach (var url in data.NuGetFeeds)
                {
                    urls.Add(url);
                }
            }
        }
        else
        {
            // Allow package to be updated before cutoff date for new security policy,
            // or if package is older than the cutoff date.
            if (Now < MigrationDate || GetApproximateDateForMod(mod) < MigrationDate)
            {
                foreach (var url in data.NuGetFeeds)
                {
                    urls.Add(url);
                }
            }
        }

        // Add all resolvers
        foreach (var url in urls)
        {
            resolvers.Add(new NuGetUpdateResolver(
                              new NuGetUpdateResolverSettings()
            {
                AllowUnlisted   = true,
                NugetRepository = new NuGetRepository(url),
                PackageId       = mod.Config.ModId
            },
                              data.CommonPackageResolverSettings
                              ));
        }

        if (resolvers.Count > 0)
        {
            return(new AggregatePackageResolver(resolvers));
        }

        return(null);
    }
Exemplo n.º 22
0
        public bool IsCompatible(PathTuple <ModConfig> mod)
        {
            var package = Task.Run(() => _nugetRepository.GetLatestPackageDetails(mod.Config.ModId, false, true)).Result;

            if (package == null)
            {
                return(false);
            }

            _metadata = package;
            return(true);
        }
    private void CreateUserConfigOnNewConfigCreated(PathTuple <ModConfig> tuple)
    {
        var filePath = ModUserConfig.GetUserConfigPathForMod(tuple.Config.ModId, ConfigDirectory);

        if (!File.Exists(filePath))
        {
            IConfig <ModUserConfig> .ToPath(new ModUserConfig()
            {
                ModId = tuple.Config.ModId
            }, filePath);
        }
    }
    /// <inheritdoc/>
    public IPackageResolver?GetResolver(PathTuple <ModConfig> mod, PathTuple <ModUserConfig>?userConfig, UpdaterData data)
    {
        if (!this.TryGetConfiguration <GameBananaConfig>(mod, out var gbConfig))
        {
            return(null);
        }

        return(new GameBananaUpdateResolver(new GameBananaResolverConfiguration()
        {
            ItemId = (int)gbConfig !.ItemId,
            ModType = gbConfig.ItemType
        }, data.CommonPackageResolverSettings));
    /// <summary>
    /// Returns true if any resolver is configured to save updates for this mod.
    /// </summary>
    /// <param name="mod">The mod to be served updates for.</param>
    /// <returns>Resolver configuration.</returns>
    public static bool HasAnyConfiguredResolver(PathTuple <ModConfig> mod)
    {
        foreach (var factory in All)
        {
            if (factory.TryGetConfigurationOrDefault(mod, out _))
            {
                return(true);
            }
        }

        return(false);
    }
Exemplo n.º 26
0
        /// <summary>
        /// Returns the first appropriate resolver that can handle updating a mod.
        /// </summary>
        /// <param name="mod">The mod in question.</param>
        /// <param name="data">All data passed to the updater.</param>
        /// <returns>A resolver that can handle the mod, else null.</returns>
        public static IModResolver GetResolver(PathTuple <ModConfig> mod, Structures.UpdaterData data)
        {
            foreach (var resolver in new Resolvers(data).All)
            {
                if (resolver.IsCompatible(mod))
                {
                    return(resolver);
                }
            }

            return(null);
        }
Exemplo n.º 27
0
    private void RefreshCommands()
    {
        if (_lastApplication != null)
        {
            _lastApplication.Config.PropertyChanged -= OnAppLocationChanged;
        }

        DeployAsiLoaderCommand     = new DeployAsiLoaderCommand(Application);
        SetApplicationImageCommand = new SetApplicationImageCommand(Application);
        _lastApplication           = Application;
        _lastApplication.Config.PropertyChanged += OnAppLocationChanged;
    }
        public SetDependenciesDialog(ModConfigService modConfigService, PathTuple <ModConfig> config)
        {
            InitializeComponent();
            ViewModel = new SetDependenciesDialogViewmodel(modConfigService, config);

            var manipulator = new DictionaryResourceManipulator(this.Contents.Resources);

            _dependenciesViewSource         = manipulator.Get <CollectionViewSource>("SortedDependencies");
            _dependenciesViewSource.Filter += DependenciesViewSourceOnFilter;

            this.Closed += OnClosed;
        }
Exemplo n.º 29
0
 private static GameBananaProviderConfig TryGetGameBananaUpdateConfig(PathTuple <ApplicationConfig> appById)
 {
     try
     {
         appById.Config.PluginData.TryGetValue("GBPackageProvider", out GameBananaProviderConfig config);
         config ??= new GameBananaProviderConfig();
         return(config);
     }
     catch (Exception)
     {
         return(new GameBananaProviderConfig());
     }
 }
    /// <inheritdoc/>
    public IPackageResolver?GetResolver(PathTuple <ModConfig> mod, PathTuple <ModUserConfig>?userConfig, UpdaterData data)
    {
        if (!this.TryGetConfiguration <GitHubConfig>(mod, out var githubConfig))
        {
            return(null);
        }

        return(new GitHubReleaseResolver(new GitHubResolverConfiguration()
        {
            RepositoryName = githubConfig !.RepositoryName,
            UserName = githubConfig.UserName,
            LegacyFallbackPattern = githubConfig.AssetFileName,
            InheritVersionFromTag = githubConfig.UseReleaseTag
        }, data.CommonPackageResolverSettings));