using System; using System.Collections.Generic; using System.Linq; using StardewModdingAPI.Internal.ConsoleWriting; namespace StardewModdingAPI.Framework.Models { /// The SMAPI configuration settings. internal class SConfig { /******** ** Fields ********/ /// The default config values, for fields that should be logged if different. private static readonly IDictionary DefaultValues = new Dictionary { [nameof(CheckForUpdates)] = true, [nameof(ParanoidWarnings)] = Constants.IsDebugBuild, [nameof(UseBetaChannel)] = Constants.ApiVersion.IsPrerelease(), [nameof(GitHubProjectName)] = "Pathoschild/SMAPI", [nameof(WebApiBaseUrl)] = "https://smapi.io/api/", [nameof(VerboseLogging)] = false, [nameof(LogNetworkTraffic)] = false, [nameof(RewriteMods)] = true, [nameof(AggressiveMemoryOptimizations)] = false }; /// The default values for , to log changes if different. private static readonly HashSet DefaultSuppressUpdateChecks = new(StringComparer.OrdinalIgnoreCase) { "SMAPI.ConsoleCommands", "SMAPI.ErrorHandler", "SMAPI.SaveBackup" }; /******** ** Accessors ********/ /// Whether to enable development features. public bool DeveloperMode { get; private set; } /// Whether to check for newer versions of SMAPI and mods on startup. public bool CheckForUpdates { get; } /// Whether to add a section to the 'mod issues' list for mods which which directly use potentially sensitive .NET APIs like file or shell access. public bool ParanoidWarnings { get; } /// Whether to show beta versions as valid updates. public bool UseBetaChannel { get; } /// SMAPI's GitHub project name, used to perform update checks. public string GitHubProjectName { get; } /// The base URL for SMAPI's web API, used to perform update checks. public string WebApiBaseUrl { get; } /// Whether SMAPI should log more information about the game context. public bool VerboseLogging { get; } /// Whether SMAPI should rewrite mods for compatibility. public bool RewriteMods { get; } /// Whether to enable more aggressive memory optimizations. public bool AggressiveMemoryOptimizations { get; } /// Whether SMAPI should log network traffic. Best combined with , which includes network metadata. public bool LogNetworkTraffic { get; } /// The colors to use for text written to the SMAPI console. public ColorSchemeConfig ConsoleColors { get; } /// The mod IDs SMAPI should ignore when performing update checks or validating update keys. public string[] SuppressUpdateChecks { get; } /******** ** Public methods ********/ /// Construct an instance. /// Whether to enable development features. /// Whether to check for newer versions of SMAPI and mods on startup. /// Whether to add a section to the 'mod issues' list for mods which which directly use potentially sensitive .NET APIs like file or shell access. /// Whether to show beta versions as valid updates. /// SMAPI's GitHub project name, used to perform update checks. /// The base URL for SMAPI's web API, used to perform update checks. /// Whether SMAPI should log more information about the game context. /// Whether SMAPI should rewrite mods for compatibility. /// Whether to enable more aggressive memory optimizations. /// Whether SMAPI should log network traffic. /// The colors to use for text written to the SMAPI console. /// The mod IDs SMAPI should ignore when performing update checks or validating update keys. public SConfig(bool developerMode, bool checkForUpdates, bool? paranoidWarnings, bool? useBetaChannel, string gitHubProjectName, string webApiBaseUrl, bool verboseLogging, bool? rewriteMods, bool? aggressiveMemoryOptimizations, bool logNetworkTraffic, ColorSchemeConfig consoleColors, string[]? suppressUpdateChecks) { this.DeveloperMode = developerMode; this.CheckForUpdates = checkForUpdates; this.ParanoidWarnings = paranoidWarnings ?? (bool)SConfig.DefaultValues[nameof(SConfig.ParanoidWarnings)]; this.UseBetaChannel = useBetaChannel ?? (bool)SConfig.DefaultValues[nameof(SConfig.UseBetaChannel)]; this.GitHubProjectName = gitHubProjectName; this.WebApiBaseUrl = webApiBaseUrl; this.VerboseLogging = verboseLogging; this.RewriteMods = rewriteMods ?? (bool)SConfig.DefaultValues[nameof(SConfig.RewriteMods)]; this.AggressiveMemoryOptimizations = aggressiveMemoryOptimizations ?? (bool)SConfig.DefaultValues[nameof(SConfig.AggressiveMemoryOptimizations)]; this.LogNetworkTraffic = logNetworkTraffic; this.ConsoleColors = consoleColors; this.SuppressUpdateChecks = suppressUpdateChecks ?? Array.Empty(); } /// Override the value of . /// The value to set. public void OverrideDeveloperMode(bool value) { this.DeveloperMode = value; } /// Get the settings which have been customized by the player. public IDictionary GetCustomSettings() { Dictionary custom = new(); foreach ((string? name, object defaultValue) in SConfig.DefaultValues) { object? value = typeof(SConfig).GetProperty(name)?.GetValue(this); if (!defaultValue.Equals(value)) custom[name] = value; } HashSet curSuppressUpdateChecks = new(this.SuppressUpdateChecks, StringComparer.OrdinalIgnoreCase); if (SConfig.DefaultSuppressUpdateChecks.Count != curSuppressUpdateChecks.Count || SConfig.DefaultSuppressUpdateChecks.Any(p => !curSuppressUpdateChecks.Contains(p))) custom[nameof(this.SuppressUpdateChecks)] = "[" + string.Join(", ", this.SuppressUpdateChecks) + "]"; return custom; } } }