add integration with Generic Mod Config Menu

This commit is contained in:
Jesse Plamondon-Willard
2026-01-25 00:00:01 -05:00
parent a00592e6a6
commit ad9cb482d0
27 changed files with 1566 additions and 87 deletions
+16 -16
View File
@@ -58,22 +58,22 @@ contributing translations.
locale | status
----------- | :----------------
default | ✓ [fully translated](../src/SMAPI/i18n/default.json)
Chinese | ✓ [fully translated](../src/SMAPI/i18n/zh.json)
French | ✓ [fully translated](../src/SMAPI/i18n/fr.json)
German | ✓ [fully translated](../src/SMAPI/i18n/de.json)
Hungarian | ✓ [fully translated](../src/SMAPI/i18n/hu.json)
Indonesian | ✓ [fully translated](../src/SMAPI/i18n/id.json)
Italian | ✓ [fully translated](../src/SMAPI/i18n/it.json)
Japanese | ✓ [fully translated](../src/SMAPI/i18n/ja.json)
Korean | ✓ [fully translated](../src/SMAPI/i18n/ko.json)
[Polish] | ✓ [fully translated](../src/SMAPI/i18n/pl.json)
Portuguese | ✓ [fully translated](../src/SMAPI/i18n/pt.json)
Russian | ✓ [fully translated](../src/SMAPI/i18n/ru.json)
Spanish | ✓ [fully translated](../src/SMAPI/i18n/es.json)
[Thai] | ✓ [fully translated](../src/SMAPI/i18n/th.json)
Turkish | ✓ [fully translated](../src/SMAPI/i18n/tr.json)
[Ukrainian] | ✓ [fully translated](../src/SMAPI/i18n/uk.json)
default | ↻ [partly translated](../src/SMAPI/i18n/default.json)
Chinese | ↻ [partly translated](../src/SMAPI/i18n/zh.json)
French | ↻ [partly translated](../src/SMAPI/i18n/fr.json)
German | ↻ [partly translated](../src/SMAPI/i18n/de.json)
Hungarian | ↻ [partly translated](../src/SMAPI/i18n/hu.json)
Indonesian | ↻ [partly translated](../src/SMAPI/i18n/id.json)
Italian | ↻ [partly translated](../src/SMAPI/i18n/it.json)
Japanese | ↻ [partly translated](../src/SMAPI/i18n/ja.json)
Korean | ↻ [partly translated](../src/SMAPI/i18n/ko.json)
[Polish] | ↻ [partly translated](../src/SMAPI/i18n/pl.json)
Portuguese | ↻ [partly translated](../src/SMAPI/i18n/pt.json)
Russian | ↻ [partly translated](../src/SMAPI/i18n/ru.json)
Spanish | ↻ [partly translated](../src/SMAPI/i18n/es.json)
[Thai] | ↻ [partly translated](../src/SMAPI/i18n/th.json)
Turkish | ↻ [partly translated](../src/SMAPI/i18n/tr.json)
[Ukrainian] | ↻ [partly translated](../src/SMAPI/i18n/uk.json)
[Polish]: https://www.nexusmods.com/stardewvalley/mods/3616
[Thai]: https://www.nexusmods.com/stardewvalley/mods/7052
+1
View File
@@ -3,6 +3,7 @@
# Release notes
## Upcoming release
* For players:
* Added in-game config UI via [Generic Mod Config Menu](<https://www.nexusmods.com/stardewvalley/mods/5098>).
* SMAPI now uses [automated and attested builds](https://www.patreon.com/posts/automated-builds-148417912) (thanks to DecidedlyHuman)!
_This improves the security and transparency of SMAPI builds. Every step to build SMAPI from the public source code is now public and verifiable, with file signatures to let players and tools confirm the build hasn't been tampered with._
* SMAPI can now detect known malicious loose files in the `Mods` folder.
@@ -11,12 +11,15 @@ internal class ColorfulConsoleWriter : IConsoleWriter
/*********
** Fields
*********/
/// <summary>The target platform.</summary>
private readonly Platform Platform;
/// <summary>The console text color for each log level.</summary>
private readonly IDictionary<ConsoleLogLevel, ConsoleColor>? Colors;
private IDictionary<ConsoleLogLevel, ConsoleColor>? Colors;
/// <summary>Whether the current console supports color formatting.</summary>
[MemberNotNullWhen(true, nameof(ColorfulConsoleWriter.Colors))]
private bool SupportsColor { get; }
private bool SupportsColor { get; set; }
/*********
@@ -32,6 +35,16 @@ internal class ColorfulConsoleWriter : IConsoleWriter
/// <param name="colorSchemeId">The color scheme ID in <paramref name="colorConfig"/> to use, or <see cref="MonitorColorScheme.AutoDetect"/> to select one automatically.</param>
/// <param name="colorConfig">The colors to use for text written to the SMAPI console.</param>
public ColorfulConsoleWriter(Platform platform, MonitorColorScheme colorSchemeId, Dictionary<MonitorColorScheme, Dictionary<ConsoleLogLevel, ConsoleColor>> colorConfig)
{
this.Platform = platform;
this.SetColors(colorSchemeId, colorConfig);
}
/// <summary>Set the color scheme to apply.</summary>
/// <param name="colorSchemeId">The color scheme ID in <paramref name="colorSchemes"/> to use, or <see cref="MonitorColorScheme.AutoDetect"/> to select one automatically.</param>
/// <param name="colorSchemes">The colors to use for text written to the SMAPI console.</param>
public void SetColors(MonitorColorScheme colorSchemeId, Dictionary<MonitorColorScheme, Dictionary<ConsoleLogLevel, ConsoleColor>> colorSchemes)
{
if (colorSchemeId == MonitorColorScheme.None)
{
@@ -41,7 +54,7 @@ internal class ColorfulConsoleWriter : IConsoleWriter
else
{
this.SupportsColor = this.TestColorSupport();
this.Colors = this.GetConsoleColorScheme(platform, colorSchemeId, colorConfig);
this.Colors = ColorfulConsoleWriter.GetConsoleColorScheme(this.Platform, colorSchemeId, colorSchemes);
}
}
@@ -123,7 +136,7 @@ internal class ColorfulConsoleWriter : IConsoleWriter
/// <param name="platform">The target platform.</param>
/// <param name="colorSchemeId">The color scheme ID in <paramref name="colorConfig"/> to use, or <see cref="MonitorColorScheme.AutoDetect"/> to select one automatically.</param>
/// <param name="colorConfig">The colors to use for text written to the SMAPI console.</param>
private IDictionary<ConsoleLogLevel, ConsoleColor> GetConsoleColorScheme(Platform platform, MonitorColorScheme colorSchemeId, Dictionary<MonitorColorScheme, Dictionary<ConsoleLogLevel, ConsoleColor>> colorConfig)
private static IDictionary<ConsoleLogLevel, ConsoleColor> GetConsoleColorScheme(Platform platform, MonitorColorScheme colorSchemeId, Dictionary<MonitorColorScheme, Dictionary<ConsoleLogLevel, ConsoleColor>> colorConfig)
{
// get color scheme ID
if (colorSchemeId == MonitorColorScheme.AutoDetect)
+54 -6
View File
@@ -28,6 +28,12 @@ internal class LogManager : IDisposable
/// <summary>Create a monitor instance given the ID and name.</summary>
private readonly Func<string, string, Monitor> GetMonitorImpl;
/// <summary>The console writer which sends color-coded text to the console.</summary>
private readonly ColorfulConsoleWriter ConsoleWriter;
/// <summary>The monitors managed by SMAPI.</summary>
private readonly List<Monitor> Monitors = [];
/*********
** Accessors
@@ -59,12 +65,9 @@ internal class LogManager : IDisposable
this.LogFile = new LogFileManager(logPath);
// init monitor
this.GetMonitorImpl = (id, name) => new Monitor(id, name, this.LogFile, colorSchemeId, colorConfig, verboseLogging.Contains("*") || verboseLogging.Contains(id), getScreenIdForLog)
{
WriteToConsole = writeToConsole,
ShowTraceInConsole = isDeveloperMode,
ShowFullStampInConsole = isDeveloperMode
};
this.ConsoleWriter = new ColorfulConsoleWriter(Constants.Platform, colorSchemeId, colorConfig);
this.GetMonitorImpl = (id, name) => this.CreateAndRegisterMonitor(id, name, verboseLogging, getScreenIdForLog, writeToConsole, isDeveloperMode);
this.Monitor = this.GetMonitor("SMAPI", "SMAPI");
this.MonitorForGame = this.GetMonitor("game", "game");
@@ -91,6 +94,19 @@ internal class LogManager : IDisposable
Console.Title = title;
}
/// <summary>Apply the SMAPI settings to the log manager and its managed monitors.</summary>
/// <param name="colorSchemeId">The color scheme ID in <paramref name="colorSchemes"/> to use, or <see cref="MonitorColorScheme.AutoDetect"/> to select one automatically.</param>
/// <param name="colorSchemes">The colors to use for text written to the SMAPI console.</param>
/// <param name="verboseLogging">The log contexts for which to enable verbose logging, which may show a lot more information to simplify troubleshooting.</param>
/// <param name="isDeveloperMode">Whether to enable full console output for developers.</param>
public void ApplySettings(MonitorColorScheme colorSchemeId, Dictionary<MonitorColorScheme, Dictionary<ConsoleLogLevel, ConsoleColor>> colorSchemes, HashSet<string> verboseLogging, bool isDeveloperMode)
{
foreach (Monitor monitor in this.Monitors)
this.ApplySettings(monitor, verboseLogging, isDeveloperMode);
this.ConsoleWriter.SetColors(colorSchemeId, colorSchemes);
}
/****
** Console input
****/
@@ -333,6 +349,38 @@ internal class LogManager : IDisposable
/*********
** Protected methods
*********/
/// <summary>Create and register a monitor instance.</summary>
/// <param name="modId">The mod ID, if applicable.</param>
/// <param name="source">The name of the module which logs messages using this instance.</param>
/// <param name="verboseLogging">The log contexts for which to enable verbose logging, which may show a lot more information to simplify troubleshooting.</param>
/// <param name="getScreenIdForLog">Get the screen ID that should be logged to distinguish between players in split-screen mode, if any.</param>
/// <param name="writeToConsole">Whether to write anything to the console. This should be disabled if no console is available.</param>
/// <param name="isDeveloperMode">Whether to enable full console output for developers.</param>
private Monitor CreateAndRegisterMonitor(string modId, string source, HashSet<string> verboseLogging, Func<int?> getScreenIdForLog, bool writeToConsole, bool isDeveloperMode)
{
Monitor monitor = new(modId, source, this.LogFile, this.ConsoleWriter, getScreenIdForLog)
{
WriteToConsole = writeToConsole
};
this.ApplySettings(monitor, verboseLogging, isDeveloperMode);
this.Monitors.Add(monitor);
return monitor;
}
/// <summary>Apply the SMAPI settings to a managed monitor.</summary>
/// <param name="monitor">The monitor to update.</param>
/// <param name="verboseLogging">The log contexts for which to enable verbose logging, which may show a lot more information to simplify troubleshooting.</param>
/// <param name="isDeveloperMode">Whether to enable full console output for developers.</param>
private void ApplySettings(Monitor monitor, HashSet<string> verboseLogging, bool isDeveloperMode)
{
monitor.IsVerbose = verboseLogging.Contains("*") || verboseLogging.Contains(monitor.ModId);
monitor.ShowTraceInConsole = isDeveloperMode;
monitor.ShowFullStampInConsole = isDeveloperMode;
}
/// <summary>Write a summary of mod warnings to the console and log.</summary>
/// <param name="mods">The loaded mods.</param>
/// <param name="skippedMods">The mods which could not be loaded.</param>
+23 -16
View File
@@ -15,20 +15,21 @@ internal class SConfig
/// <summary>The default config values, for fields that should be logged if different.</summary>
private static readonly IDictionary<string, object> DefaultValues = new Dictionary<string, object>
{
[nameof(CheckForUpdates)] = true,
[nameof(CheckForBlacklistUpdates)] = true,
[nameof(CheckContentIntegrity)] = true,
[nameof(ListenForConsoleInput)] = true,
[nameof(ParanoidWarnings)] = Constants.IsDebugBuild,
[nameof(UseBetaChannel)] = Constants.ApiVersion.IsPrerelease(),
[nameof(GitHubProjectName)] = "Pathoschild/SMAPI",
[nameof(WebApiBaseUrl)] = "https://smapi.io/api/",
[nameof(LogNetworkTraffic)] = false,
[nameof(LogTechnicalDetailsForBrokenMods)] = false,
[nameof(RewriteMods)] = true,
[nameof(FixHarmony)] = true,
[nameof(UseCaseInsensitivePaths)] = Constants.Platform is Platform.Android or Platform.Linux,
[nameof(SuppressHarmonyDebugMode)] = true
[nameof(SConfig.CheckForUpdates)] = true,
[nameof(SConfig.CheckForBlacklistUpdates)] = true,
[nameof(SConfig.CheckContentIntegrity)] = true,
[nameof(SConfig.ListenForConsoleInput)] = true,
[nameof(SConfig.ParanoidWarnings)] = Constants.IsDebugBuild,
[nameof(SConfig.UseBetaChannel)] = Constants.ApiVersion.IsPrerelease(),
[nameof(SConfig.GitHubProjectName)] = "Pathoschild/SMAPI",
[nameof(SConfig.WebApiBaseUrl)] = "https://smapi.io/api/",
[nameof(SConfig.LogNetworkTraffic)] = false,
[nameof(SConfig.LogTechnicalDetailsForBrokenMods)] = false,
[nameof(SConfig.RewriteMods)] = true,
[nameof(SConfig.EnableConfigMenu)] = true,
[nameof(SConfig.FixHarmony)] = true,
[nameof(SConfig.UseCaseInsensitivePaths)] = Constants.Platform is Platform.Android or Platform.Linux,
[nameof(SConfig.SuppressHarmonyDebugMode)] = true
};
/// <summary>The default values for <see cref="SuppressUpdateChecks"/>, to log changes if different.</summary>
@@ -46,7 +47,7 @@ internal class SConfig
// Note: properties must be writable to support merging config.user.json into it.
//
/// <summary>Whether to enable development features.</summary>
/// <summary>Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.</summary>
public bool DeveloperMode { get; set; }
/// <summary>Whether to check for newer versions of SMAPI and mods on startup.</summary>
@@ -61,7 +62,7 @@ internal class SConfig
/// <summary>Whether SMAPI should listen for console input to support console commands.</summary>
public bool ListenForConsoleInput { get; set; }
/// <summary>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.</summary>
/// <summary>Whether to add a section to the 'mod issues' list for mods which directly use potentially sensitive .NET APIs like file or shell access.</summary>
public bool ParanoidWarnings { get; set; }
/// <summary>Whether to show beta versions as valid updates.</summary>
@@ -83,6 +84,9 @@ internal class SConfig
/// <summary>Whether SMAPI should rewrite mods for compatibility.</summary>
public bool RewriteMods { get; set; }
/// <summary>Whether SMAPI should add an in-game config menu through Generic Mod Config Menu.</summary>
public bool EnableConfigMenu { get; set; }
/// <summary>Whether to apply fixes to Harmony so it works with Stardew Valley.</summary>
public bool FixHarmony { get; set; }
@@ -130,6 +134,7 @@ internal class SConfig
/// <param name="blacklistUrl"><inheritdoc cref="BlacklistUrl" path="/summary" /></param>
/// <param name="verboseLogging"><inheritdoc cref="VerboseLogging" path="/summary" /></param>
/// <param name="rewriteMods"><inheritdoc cref="RewriteMods" path="/summary" /></param>
/// <param name="enableConfigMenu"><inheritdoc cref="EnableConfigMenu" path="/summary" /></param>
/// <param name="fixHarmony"><inheritdoc cref="FixHarmony" path="/summary" /></param>
/// <param name="useCaseInsensitivePaths"><inheritdoc cref="UseCaseInsensitivePaths" path="/summary" /></param>
/// <param name="logNetworkTraffic"><inheritdoc cref="LogNetworkTraffic" path="/summary" /></param>
@@ -153,6 +158,7 @@ internal class SConfig
string blacklistUrl,
string[]? verboseLogging,
bool? rewriteMods,
bool? enableConfigMenu,
bool? fixHarmony,
bool? useCaseInsensitivePaths,
bool? logNetworkTraffic,
@@ -177,6 +183,7 @@ internal class SConfig
this.BlacklistUrl = blacklistUrl;
this.VerboseLogging = new HashSet<string>(verboseLogging ?? [], StringComparer.OrdinalIgnoreCase);
this.RewriteMods = rewriteMods ?? (bool)SConfig.DefaultValues[nameof(this.RewriteMods)];
this.EnableConfigMenu = enableConfigMenu ?? (bool)SConfig.DefaultValues[nameof(this.EnableConfigMenu)];
this.FixHarmony = fixHarmony ?? (bool)SConfig.DefaultValues[nameof(this.FixHarmony)];
this.UseCaseInsensitivePaths = useCaseInsensitivePaths ?? (bool)SConfig.DefaultValues[nameof(this.UseCaseInsensitivePaths)];
this.LogNetworkTraffic = logNetworkTraffic ?? (bool)SConfig.DefaultValues[nameof(this.LogNetworkTraffic)];
+11 -10
View File
@@ -13,9 +13,6 @@ internal class Monitor : IMonitor
/*********
** Fields
*********/
/// <summary>The mod ID, if applicable.</summary>
private readonly string ModId;
/// <summary>The name of the module which logs messages using this instance.</summary>
private readonly string Source;
@@ -41,6 +38,9 @@ internal class Monitor : IMonitor
/*********
** Accessors
*********/
/// <summary>The mod ID, if applicable.</summary>
public string ModId { get; }
/// <summary>Whether to log basic contextual info (like buttons pressed and menus opened) even if <see cref="IsVerbose"/> is disabled.</summary>
public static bool ForceLogContext { get; set; }
@@ -54,7 +54,11 @@ internal class Monitor : IMonitor
public static LogLevel ContextLogLevel => Monitor.ForceLogContext ? LogLevel.Info : LogLevel.Trace;
/// <inheritdoc />
public bool IsVerbose => field || Monitor.ForceVerboseLoggingForAll || Monitor.ForceVerboseLogging.Contains(this.ModId);
public bool IsVerbose
{
get => field || Monitor.ForceVerboseLoggingForAll || Monitor.ForceVerboseLogging.Contains(this.ModId);
set => field = value;
}
/// <summary>Whether to show the full log stamps (with time/level/logger) in the console. If false, shows a simplified stamp with only the logger.</summary>
internal bool ShowFullStampInConsole { get; set; }
@@ -73,11 +77,9 @@ internal class Monitor : IMonitor
/// <param name="modId">The mod ID, if applicable.</param>
/// <param name="source">The name of the module which logs messages using this instance.</param>
/// <param name="logFile">The log file to which to write messages.</param>
/// <param name="colorSchemeId">The color scheme ID in <paramref name="colorConfig"/> to use, or <see cref="MonitorColorScheme.AutoDetect"/> to select one automatically.</param>
/// <param name="colorConfig">The colors to use for text written to the SMAPI console.</param>
/// <param name="isVerbose">Whether verbose logging is enabled. This enables more detailed diagnostic messages than are normally needed.</param>
/// <param name="consoleWriter">Handles writing text to the console.</param>
/// <param name="getScreenIdForLog">Get the screen ID that should be logged to distinguish between players in split-screen mode, if any.</param>
public Monitor(string modId, string source, LogFileManager logFile, MonitorColorScheme colorSchemeId, Dictionary<MonitorColorScheme, Dictionary<ConsoleLogLevel, ConsoleColor>> colorConfig, bool isVerbose, Func<int?> getScreenIdForLog)
public Monitor(string modId, string source, LogFileManager logFile, IConsoleWriter consoleWriter, Func<int?> getScreenIdForLog)
{
// validate
if (string.IsNullOrWhiteSpace(source))
@@ -87,8 +89,7 @@ internal class Monitor : IMonitor
this.ModId = modId;
this.Source = source;
this.LogFile = logFile ?? throw new ArgumentNullException(nameof(logFile), "The log file manager cannot be null.");
this.ConsoleWriter = new ColorfulConsoleWriter(Constants.Platform, colorSchemeId, colorConfig);
this.IsVerbose = isVerbose;
this.ConsoleWriter = consoleWriter ?? throw new ArgumentNullException(nameof(consoleWriter), "The console writer cannot be null.");
this.GetScreenIdForLog = getScreenIdForLog;
}
+49 -17
View File
@@ -37,6 +37,7 @@ using StardewModdingAPI.Framework.Rendering;
using StardewModdingAPI.Framework.Serialization;
using StardewModdingAPI.Framework.StateTracking.Snapshots;
using StardewModdingAPI.Framework.Utilities;
using StardewModdingAPI.Integrations.GenericModConfigMenu;
using StardewModdingAPI.Internal;
using StardewModdingAPI.Toolkit;
using StardewModdingAPI.Toolkit.Framework.Clients.WebApi;
@@ -85,12 +86,12 @@ internal class SCore : IDisposable
/// <summary>Encapsulates access to SMAPI core translations.</summary>
private readonly Translator Translator = new();
/// <summary>The SMAPI configuration settings.</summary>
private readonly SConfig Settings;
/// <summary>The mod toolkit used for generic mod interactions.</summary>
private readonly ModToolkit Toolkit = new();
/// <summary>The SMAPI configuration settings.</summary>
private SConfig Settings;
/****
** Higher-level components
****/
@@ -113,13 +114,15 @@ internal class SCore : IDisposable
/// <summary>Manages SMAPI events for mods.</summary>
private readonly EventManager EventManager;
/****
** State
****/
/// <summary>The path to search for mods.</summary>
private string ModsPath => Constants.ModsPath;
/// <summary>The override to apply for <see cref="SConfig.DeveloperMode"/>, or <c>null</c> to use the value from the settings file.</summary>
private readonly bool? OverrideDeveloperMode;
/// <summary>Whether the game is currently running.</summary>
private bool IsGameRunning;
@@ -178,8 +181,8 @@ internal class SCore : IDisposable
/// <summary>Construct an instance.</summary>
/// <param name="modsPath">The path to search for mods.</param>
/// <param name="writeToConsole">Whether to output log messages to the console.</param>
/// <param name="developerMode">Whether to enable development features, or <c>null</c> to use the value from the settings file.</param>
public SCore(string modsPath, bool writeToConsole, bool? developerMode)
/// <param name="overrideDeveloperMode">The override to apply for <see cref="SConfig.DeveloperMode"/>, or <c>null</c> to use the value from the settings file.</param>
public SCore(string modsPath, bool writeToConsole, bool? overrideDeveloperMode)
{
SCore.Instance = this;
@@ -193,17 +196,8 @@ internal class SCore : IDisposable
string logPath = this.GetLogPath();
// init settings
{
var deserializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
this.Settings = JsonConvert.DeserializeObject<SConfig>(File.ReadAllText(Constants.ApiConfigPath)) ?? throw new InvalidOperationException("The 'smapi-internal/config.json' file is missing or invalid. You can reinstall SMAPI to fix this.");
if (File.Exists(Constants.ApiUserConfigPath))
JsonConvert.PopulateObject(File.ReadAllText(Constants.ApiUserConfigPath), this.Settings, deserializerSettings);
if (File.Exists(Constants.ApiModGroupConfigPath))
JsonConvert.PopulateObject(File.ReadAllText(Constants.ApiModGroupConfigPath), this.Settings, deserializerSettings);
if (developerMode.HasValue)
this.Settings.OverrideDeveloperMode(developerMode.Value);
}
this.OverrideDeveloperMode = overrideDeveloperMode;
this.ReloadSettings();
// init basics
this.LogManager = new LogManager(logPath: logPath, colorSchemeId: this.Settings.ConsoleColorScheme, colorConfig: this.Settings.ConsoleColorSchemes, writeToConsole: writeToConsole, verboseLogging: this.Settings.VerboseLogging, isDeveloperMode: this.Settings.DeveloperMode, getScreenIdForLog: this.GetScreenIdForLog);
@@ -521,6 +515,10 @@ internal class SCore : IDisposable
// check for updates
_ = this.CheckForUpdatesAsync(mods); // ignore task since the main thread doesn't need to wait for it
// register config menu with Generic Mod Config Menu
if (this.Settings.EnableConfigMenu)
new GenericModConfigMenuIntegration(this.Monitor, this.Translator, () => this.Settings, this.ReloadSettings).Register(this.ModRegistry);
}
// update window titles
@@ -1406,6 +1404,40 @@ internal class SCore : IDisposable
this.EventManager.AssetsInvalidated.Raise(new AssetsInvalidatedEventArgs(assetNames, assetNames.Select(p => p.GetBaseAssetName())));
}
/// <summary>Reload the SMAPI settings.</summary>
/// <exception cref="InvalidOperationException">The intern</exception>
[MemberNotNull(nameof(SCore.Settings))]
private void ReloadSettings()
{
JsonSerializerSettings deserializerSettings = new() { NullValueHandling = NullValueHandling.Ignore };
// load default settings
SConfig? settings = JsonConvert.DeserializeObject<SConfig>(File.ReadAllText(Constants.ApiConfigPath));
if (settings is null)
{
if (this.Settings is null)
throw new InvalidOperationException("The 'smapi-internal/config.json' file is missing or invalid. You can reinstall SMAPI to fix this.");
this.Monitor.Log("Could not load updated settings from the 'smapi-internal/config.json' file. Keeping the settings as-is.", LogLevel.Warn);
return;
}
// load user settings
if (File.Exists(Constants.ApiUserConfigPath))
JsonConvert.PopulateObject(File.ReadAllText(Constants.ApiUserConfigPath), settings, deserializerSettings);
if (File.Exists(Constants.ApiModGroupConfigPath))
JsonConvert.PopulateObject(File.ReadAllText(Constants.ApiModGroupConfigPath), settings, deserializerSettings);
if (this.OverrideDeveloperMode.HasValue)
settings.OverrideDeveloperMode(this.OverrideDeveloperMode.Value);
// apply
this.Settings = settings;
// update log manager if already initialized
// ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract
this.LogManager?.ApplySettings(settings.ConsoleColorScheme, settings.ConsoleColorSchemes, settings.VerboseLogging, this.OverrideDeveloperMode ?? settings.DeveloperMode);
}
/// <summary>Get the load/edit operations to apply to an asset by querying registered <see cref="IContentEvents.AssetRequested"/> event handlers.</summary>
/// <param name="asset">The asset info being requested.</param>
private AssetOperationGroup? RequestAssetOperations(IAssetInfo asset)
@@ -0,0 +1,343 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Models;
using StardewModdingAPI.Framework.ModHelpers;
using StardewModdingAPI.Framework.ModLoading;
using StardewModdingAPI.Framework.Reflection;
using StardewModdingAPI.Internal.ConsoleWriting;
using StardewModdingAPI.Toolkit.Serialization.Models;
using StardewModdingAPI.Toolkit.Utilities;
using StardewValley.Extensions;
namespace StardewModdingAPI.Integrations.GenericModConfigMenu
{
/// <summary>Registers the SMAPI configuration with Generic Mod Config Menu.</summary>
internal class GenericModConfigMenuIntegration
{
/*********
** Fields
*********/
/// <summary>The unique mod ID for Generic Mod Config Menu.</summary>
private const string GenericModConfigMenuModId = "spacechase0.GenericModConfigMenu";
/// <summary>The minimum version of Generic Mod Config Menu supported by this integration.</summary>
private const string MinVersion = "1.9.6";
/// <summary>Encapsulates monitoring and logging.</summary>
private readonly IMonitor Monitor;
/// <summary>The core SMAPI translations.</summary>
private readonly Translator Translations;
/// <summary>Get the current SMAPI settings.</summary>
private readonly Func<SConfig> GetConfig;
/// <summary>Reload the SMAPI settings when they're changed through the config menu.</summary>
private readonly Action ReloadConfig;
/// <summary>The custom setting values which haven't been saved yet.</summary>
private readonly Dictionary<string, object> StagedSettings = [];
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="monitor"><inheritdoc cref="Monitor" path="/summary" /></param>
/// <param name="translations"><inheritdoc cref="Translations" path="/summary" /></param>
/// <param name="getConfig"><inheritdoc cref="GetConfig" path="/summary" /></param>
/// <param name="reloadConfig"><inheritdoc cref="ReloadConfig" path="/summary" /></param>
public GenericModConfigMenuIntegration(IMonitor monitor, Translator translations, Func<SConfig> getConfig, Action reloadConfig)
{
this.Monitor = monitor;
this.Translations = translations;
this.GetConfig = getConfig;
this.ReloadConfig = reloadConfig;
}
/// <summary>Register the mod config.</summary>
/// <param name="internalModRegistry">An API for fetching metadata about loaded mods.</param>
public void Register(ModRegistry internalModRegistry)
{
try
{
// init
ModMetadata smapiMod = this.CreateFakeMod();
IModRegistry modRegistry = this.CreateModRegistryHelper(internalModRegistry, this.Monitor, smapiMod);
IGenericModConfigMenuApi? api = this.GetGenericModConfigMenuApi(modRegistry, this.Monitor);
if (api is null)
return;
// register config
api.Register(smapiMod.Manifest, this.OnReset, this.Save);
var getConfig = this.GetConfig;
// add 'SMAPI features' section
api.AddSectionTitle(smapiMod.Manifest, () => this.Translations.Get("config.section.features"));
api.AddBoolOption(
mod: smapiMod.Manifest,
name: () => this.Translations.Get("config.check-for-updates.name"),
tooltip: () => this.Translations.Get("config.check-for-updates.desc"),
getValue: () => getConfig().CheckForUpdates,
setValue: value => this.StageOption(nameof(SConfig.CheckForUpdates), value)
);
api.AddBoolOption(
mod: smapiMod.Manifest,
name: () => this.Translations.Get("config.check-content-integrity.name"),
tooltip: () => this.Translations.Get("config.check-content-integrity.desc"),
getValue: () => getConfig().CheckContentIntegrity,
setValue: value => this.StageOption(nameof(SConfig.CheckContentIntegrity), value)
);
api.AddBoolOption(
mod: smapiMod.Manifest,
name: () => this.Translations.Get("config.read-console-input.name"),
tooltip: () => this.Translations.Get("config.read-console-input.desc"),
getValue: () => getConfig().ListenForConsoleInput,
setValue: value => this.StageOption(nameof(SConfig.ListenForConsoleInput), value)
);
// add 'console window' section
api.AddSectionTitle(smapiMod.Manifest, () => this.Translations.Get("config.section.console-window"));
api.AddBoolOption(
mod: smapiMod.Manifest,
name: () => this.Translations.Get("config.developer-mode.name"),
tooltip: () => this.Translations.Get("config.developer-mode.desc"),
getValue: () => getConfig().DeveloperMode,
setValue: value => this.StageOption(nameof(SConfig.DeveloperMode), value)
);
api.AddTextOption(
mod: smapiMod.Manifest,
name: () => this.Translations.Get("config.color-scheme.name"),
tooltip: () => this.Translations.Get("config.color-scheme.desc"),
getValue: () => getConfig().ConsoleColorScheme.ToString(),
setValue: value => this.StageOption(nameof(SConfig.ConsoleColorScheme), value),
allowedValues: Enum.GetValues<MonitorColorScheme>().Select(p => p.ToString()).ToArray(),
formatAllowedValue: value => this.Translations.Get(
value is nameof(MonitorColorScheme.AutoDetect) && Constants.Platform == Platform.Windows
? $"config.color-scheme.options.{value}.on-windows"
: $"config.color-scheme.options.{value}"
));
// add 'verbose logging' section
api.AddSectionTitle(smapiMod.Manifest, () => this.Translations.Get("config.section.verbose-logs"));
api.AddParagraph(smapiMod.Manifest, () => this.Translations.Get("config.section.verbose-logs.explanation"));
api.AddTextOption(
mod: smapiMod.Manifest,
name: () => this.Translations.Get("config.enable-for.name"),
tooltip: () => this.Translations.Get("config.enable-for.desc"),
getValue: () => getConfig().VerboseLogging.Contains("*").ToString(),
setValue: value => this.StageVerboseLoggingOption("*", value == bool.TrueString),
allowedValues: [bool.TrueString, bool.FalseString],
formatAllowedValue: value => this.Translations.Get($"config.enable-for.options.{(value == bool.TrueString ? "all" : "selected")}")
);
api.AddBoolOption(
mod: smapiMod.Manifest,
name: () => this.Translations.Get("config.enable-for-smapi.name"),
tooltip: () => this.Translations.Get("config.enable-for-smapi.desc"),
getValue: () => getConfig().VerboseLogging.Contains("SMAPI"),
setValue: value => this.StageVerboseLoggingOption("SMAPI", value)
);
foreach (IModInfo mod in modRegistry.GetAll().OrderBy(p => p.Manifest.Name, StringComparer.OrdinalIgnoreCase))
{
if (mod.IsContentPack)
continue;
api.AddBoolOption(
mod: smapiMod.Manifest,
name: () => this.Translations.Get("config.enable-for-mod.name", new { modName = mod.Manifest.Name }),
tooltip: () => this.Translations.Get("config.enable-for-mod.desc", new { modName = mod.Manifest.Name }),
getValue: () => getConfig().VerboseLogging.Contains(mod.Manifest.UniqueID),
setValue: value => this.StageVerboseLoggingOption(mod.Manifest.UniqueID, value)
);
}
}
catch (Exception ex)
{
this.Monitor.Log("Couldn't register the SMAPI settings with Generic Mod Config Menu. This has no effect on SMAPI, but the in-game config menu won't be available.", LogLevel.Warn);
this.Monitor.Log(ex.ToString());
}
}
/*********
** Private methods
*********/
/****
** Save events
****/
/// <summary>Reset the SMAPI configuration to the default values.</summary>
private void OnReset()
{
try
{
foreach (string customPath in new[] { Constants.ApiUserConfigPath, Constants.ApiModGroupConfigPath })
{
if (File.Exists(customPath))
File.Delete(customPath);
}
this.ReloadConfig();
}
catch (Exception ex)
{
this.Monitor.Log($"Couldn't reset SMAPI to the default settings from the Generic Mod Config Menu UI.\n\nTechnical details:\n{ex}", LogLevel.Error);
}
}
/// <summary>Save the mod configuration.</summary>
private void Save()
{
try
{
// load settings
JsonSettingsWrapper? defaultSettings = JsonSettingsWrapper.TryLoadFile(Constants.ApiConfigPath, this.Monitor);
JsonSettingsWrapper? userSettings = JsonSettingsWrapper.TryLoadFile(Constants.ApiUserConfigPath, this.Monitor);
JsonSettingsWrapper? modGroupSettings = JsonSettingsWrapper.TryLoadFile(Constants.ApiModGroupConfigPath, this.Monitor);
// skip if invalid
if (defaultSettings is null)
{
this.Monitor.Log("Couldn't save the SMAPI settings from the Generic Mod Config Menu UI. The default settings could not be loaded.", LogLevel.Error);
return;
}
// apply edited options
if (this.StagedSettings.Count > 0)
{
// create settings file if needed
if (userSettings is null && modGroupSettings is null)
userSettings = new JsonSettingsWrapper(Constants.ApiUserConfigPath);
// save simple options
foreach ((string fieldName, object newValue) in this.StagedSettings)
{
// replace existing property if possible
if (modGroupSettings?.SetUserOption(fieldName, newValue, defaultSettings, overwriteOnly: true) is true)
continue;
if (userSettings?.SetUserOption(fieldName, newValue, defaultSettings, overwriteOnly: true) is true)
continue;
// else add new property
(modGroupSettings ?? userSettings)?.SetUserOption(fieldName, newValue, defaultSettings, overwriteOnly: false);
}
}
// save to files
if (modGroupSettings?.Changed is true)
modGroupSettings.SaveOrDeleteFile();
if (userSettings?.Changed is true)
userSettings.SaveOrDeleteFile();
// reload settings
this.StagedSettings.Clear();
this.ReloadConfig();
}
catch (Exception ex)
{
this.Monitor.Log($"Couldn't save the SMAPI settings from the Generic Mod Config Menu UI.\n\nTechnical details:\n{ex}", LogLevel.Error);
}
}
/****
** Config option staging
****/
/// <summary>Store a value set by the player before it's saved to the config files.</summary>
/// <param name="fieldName">The name of the <see cref="SConfig"/> field to change.</param>
/// <param name="value">The value to stage.</param>
private void StageOption(string fieldName, object value)
{
this.StagedSettings[fieldName] = value;
}
/// <summary>Store a custom <see cref="SConfig.VerboseLogging"/> option before it's saved to the config files.</summary>
/// <param name="id">The mod ID, 'SMAPI', or '*' (all) for which to toggle verbose logging.</param>
/// <param name="enable">Whether verbose logging is enabled.</param>
private void StageVerboseLoggingOption(string id, bool enable)
{
const string fieldName = nameof(SConfig.VerboseLogging);
if (this.StagedSettings.TryGetValue(fieldName, out object? rawValue) && rawValue is HashSet<string> set)
set.Toggle(id, enable);
else
{
HashSet<string> newSet = new HashSet<string>(this.GetConfig().VerboseLogging, StringComparer.OrdinalIgnoreCase);
newSet.Toggle(id, enable);
this.StagedSettings[fieldName] = newSet;
}
}
/****
** Initialization
****/
/// <summary>Get the public API for Generic Mod Config Menu, if it's available.</summary>
/// <param name="modRegistry">The mod registry to query.</param>
/// <param name="monitor">The monitor with which to log issues loading the API.</param>
/// <returns>Returns the API if it's available, else <c>null</c>.</returns>
private IGenericModConfigMenuApi? GetGenericModConfigMenuApi(IModRegistry modRegistry, IMonitor monitor)
{
// check mod is installed
if (modRegistry.Get(GenericModConfigMenuIntegration.GenericModConfigMenuModId) is not { } configMod)
return null;
// check min version
if (configMod.Manifest.Version.IsOlderThan(GenericModConfigMenuIntegration.MinVersion))
{
monitor.Log("Can't register the SMAPI settings with Generic Mod Config Menu, because you need version 1.9.6 or later of that mod.", LogLevel.Debug);
return null;
}
// check API
if (modRegistry.GetApi<IGenericModConfigMenuApi>(GenericModConfigMenuIntegration.GenericModConfigMenuModId) is not { } api)
{
monitor.Log("Can't register the SMAPI settings with Generic Mod Config Menu, because it unexpectedly had no API.", LogLevel.Debug);
return null;
}
return api;
}
/// <summary>Create a fake mod entry to represent SMAPI itself.</summary>
private ModMetadata CreateFakeMod()
{
IManifest manifest = new Manifest(
uniqueId: "SMAPI",
name: "SMAPI",
author: "Pathoschild",
description: string.Empty,
version: Constants.ApiVersion,
minimumApiVersion: Constants.ApiVersion,
minimumGameVersion: Constants.MinimumGameVersion,
entryDll: "StardewModdingAPI.exe",
contentPackFor: null,
dependencies: [],
updateKeys: []
);
return new ModMetadata(
displayName: "SMAPI",
directoryPath: Constants.GamePath,
rootPath: Constants.ModsPath,
manifest: manifest,
dataRecord: null,
isIgnored: false
);
}
/// <summary>Create a mod registry helper.</summary>
/// <param name="internalRegistry">The internal mod registry.</param>
/// <param name="monitor">Encapsulates monitoring and logging.</param>
/// <param name="smapiMod">The fake mod entry representing SMAPI itself.</param>
private IModRegistry CreateModRegistryHelper(ModRegistry internalRegistry, IMonitor monitor, ModMetadata smapiMod)
{
return new ModRegistryHelper(
mod: smapiMod,
registry: internalRegistry,
proxyFactory: new InterfaceProxyFactory(),
monitor: monitor
);
}
}
}
@@ -0,0 +1,55 @@
using System;
namespace StardewModdingAPI.Integrations.GenericModConfigMenu;
/// <summary>The API provided by the Generic Mod Config Menu mod.</summary>
public interface IGenericModConfigMenuApi
{
/*********
** Methods
*********/
/****
** Must be called first
****/
/// <summary>Register a mod whose config can be edited through the UI.</summary>
/// <param name="mod">The mod's manifest.</param>
/// <param name="reset">Reset the mod's config to its default values.</param>
/// <param name="save">Save the mod's current config to the <c>config.json</c> file.</param>
/// <param name="titleScreenOnly">Whether the options can only be edited from the title screen.</param>
void Register(IManifest mod, Action reset, Action save, bool titleScreenOnly = false);
/****
** Basic options
****/
/// <summary>Add a section title at the current position in the form.</summary>
/// <param name="mod">The mod's manifest.</param>
/// <param name="text">The title text shown in the form.</param>
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the title, or <c>null</c> to disable the tooltip.</param>
void AddSectionTitle(IManifest mod, Func<string> text, Func<string>? tooltip = null);
/// <summary>Add a paragraph of text at the current position in the form.</summary>
/// <param name="mod">The mod's manifest.</param>
/// <param name="text">The paragraph text to display.</param>
void AddParagraph(IManifest mod, Func<string> text);
/// <summary>Add a boolean option at the current position in the form.</summary>
/// <param name="mod">The mod's manifest.</param>
/// <param name="getValue">Get the current value from the mod config.</param>
/// <param name="setValue">Set a new value in the mod config.</param>
/// <param name="name">The label text to show in the form.</param>
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the field, or <c>null</c> to disable the tooltip.</param>
/// <param name="fieldId">The unique field ID for use with <c>OnFieldChanged</c>, or <c>null</c> to auto-generate a randomized ID.</param>
void AddBoolOption(IManifest mod, Func<bool> getValue, Action<bool> setValue, Func<string> name, Func<string>? tooltip = null, string? fieldId = null);
/// <summary>Add a string option at the current position in the form.</summary>
/// <param name="mod">The mod's manifest.</param>
/// <param name="getValue">Get the current value from the mod config.</param>
/// <param name="setValue">Set a new value in the mod config.</param>
/// <param name="name">The label text to show in the form.</param>
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the field, or <c>null</c> to disable the tooltip.</param>
/// <param name="allowedValues">The values that can be selected, or <c>null</c> to allow any.</param>
/// <param name="formatAllowedValue">Get the display text to show for a value from <paramref name="allowedValues"/>, or <c>null</c> to show the values as-is.</param>
/// <param name="fieldId">The unique field ID for use with <c>OnFieldChanged</c>, or <c>null</c> to auto-generate a randomized ID.</param>
void AddTextOption(IManifest mod, Func<string> getValue, Action<string> setValue, Func<string> name, Func<string>? tooltip = null, string[]? allowedValues = null, Func<string, string>? formatAllowedValue = null, string? fieldId = null);
}
@@ -0,0 +1,195 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using StardewModdingAPI.Framework.Models;
namespace StardewModdingAPI.Integrations.GenericModConfigMenu;
/// <summary>Wraps access to a JSON file which stores <see cref="SConfig"/> fields.</summary>
internal class JsonSettingsWrapper
{
/*********
** Accessors
*********/
/// <summary>The full path to the underlying file.</summary>
public string FilePath { get; }
/// <summary>The loaded option properties.</summary>
public Dictionary<string, JToken> Properties { get; }
/// <summary>Whether the saved values have changed.</summary>
public bool Changed { get; private set; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="filePath"><inheritdoc cref="FilePath" path="/summary" /></param>
public JsonSettingsWrapper(string filePath)
: this(filePath, new Dictionary<string, JToken>(StringComparer.OrdinalIgnoreCase)) { }
/// <summary>Set the value for a user settings field.</summary>
/// <param name="fieldName">The name of the field to set.</param>
/// <param name="newValue">The new value to set.</param>
/// <param name="defaultSettings">The default settings.</param>
/// <param name="overwriteOnly">Whether to only set the value if it's already set in this file.</param>
/// <returns>Returns whether the value changed.</returns>
public bool SetUserOption(string fieldName, object newValue, JsonSettingsWrapper defaultSettings, bool overwriteOnly)
{
return fieldName == nameof(SConfig.VerboseLogging)
? this.SetVerboseLoggingUserOption(fieldName, (HashSet<string>)newValue, defaultSettings, overwriteOnly)
: this.SetScalarUserOption(fieldName, newValue, defaultSettings, overwriteOnly);
}
/// <summary>Remove a user settings field.</summary>
/// <param name="fieldName">The name of the field to set.</param>
/// <returns>Returns whether the value was found and removed.</returns>
public bool RemoveUserOption(string fieldName)
{
bool changed = this.Properties.Remove(fieldName);
this.Changed = this.Changed || changed;
return changed;
}
/// <summary>Save the user settings to the file on disk, or delete the files if it's empty.</summary>
public void SaveOrDeleteFile()
{
if (this.Properties.Count == 0)
File.Delete(Constants.ApiUserConfigPath);
else
{
string json = JsonConvert.SerializeObject(this.Properties, Formatting.Indented);
File.WriteAllText(this.FilePath, json, Encoding.UTF8);
}
this.Changed = false;
}
/// <summary>Read a raw JSON settings file.</summary>
/// <param name="path">The full path for the file to read.</param>
/// <param name="monitor">The monitor with which to log errors.</param>
/// <returns>Returns the loaded JSON wrapper, or <c>null</c> if the file doesn't exist or couldn't be loaded.</returns>
public static JsonSettingsWrapper? TryLoadFile(string path, IMonitor monitor)
{
try
{
if (!File.Exists(path))
return null;
string rawJson = File.ReadAllText(path);
JObject? json = JsonConvert.DeserializeObject<JObject>(rawJson);
if (json is null)
return null;
Dictionary<string, JToken> properties = new(StringComparer.OrdinalIgnoreCase);
foreach (JProperty property in json.Properties())
properties[property.Name] = property.Value;
return new JsonSettingsWrapper(path, properties);
}
catch (Exception ex)
{
monitor.Log($"Can't read settings file at {path}.\n\nTechnical details:\n{ex}", LogLevel.Error);
return null;
}
}
/*********
** Private methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="filePath"><inheritdoc cref="FilePath" path="/summary" /></param>
/// <param name="properties"><inheritdoc cref="Properties" path="/summary" /></param>
private JsonSettingsWrapper(string filePath, Dictionary<string, JToken> properties)
{
this.FilePath = filePath;
this.Properties = properties;
}
/// <summary>Set the value for a scalar user settings field.</summary>
/// <param name="fieldName">The name of the field to set.</param>
/// <param name="newValue">The new value to set.</param>
/// <param name="defaultSettings">The default settings.</param>
/// <param name="overwriteOnly">Whether to only set the value if it's already set in this file.</param>
/// <returns>Returns whether the value changed.</returns>
public bool SetScalarUserOption(string fieldName, object newValue, JsonSettingsWrapper defaultSettings, bool overwriteOnly)
{
// remove default
if (defaultSettings.Properties.TryGetValue(fieldName, out JToken? rawDefaultValue) && this.TokenHasValue(rawDefaultValue, newValue))
return this.RemoveUserOption(fieldName);
// else overwrite value
if (this.Properties.TryGetValue(fieldName, out JToken? oldValue))
{
if (this.TokenHasValue(oldValue, newValue))
return false;
this.Properties[fieldName] = JToken.FromObject(newValue);
this.Changed = true;
return true;
}
// else add value
if (!overwriteOnly)
{
this.Properties[fieldName] = JToken.FromObject(newValue);
this.Changed = true;
return true;
}
return false;
}
/// <summary>Set the value for the verbose logging field.</summary>
/// <param name="fieldName">The name of the field to set.</param>
/// <param name="newValue">The new value to set.</param>
/// <param name="defaultSettings">The default settings.</param>
/// <param name="overwriteOnly">Whether to only set the value if it's already set in this file.</param>
/// <returns>Returns whether the value changed.</returns>
public bool SetVerboseLoggingUserOption(string fieldName, HashSet<string> newValue, JsonSettingsWrapper defaultSettings, bool overwriteOnly)
{
// remove default
if (newValue.Count == 0)
return this.RemoveUserOption(fieldName);
// else overwrite value
if (this.Properties.GetValueOrDefault(fieldName)?.ToObject<HashSet<string>>() is { } oldSet)
{
oldSet = new HashSet<string>(oldSet, StringComparer.OrdinalIgnoreCase);
bool changed = newValue.Count != oldSet.Count || !oldSet.All(newValue.Contains);
if (changed)
{
this.Properties[fieldName] = JToken.FromObject(newValue);
this.Changed = true;
}
return changed;
}
// else add value
if (!overwriteOnly)
{
this.Properties[fieldName] = JToken.FromObject(newValue);
this.Changed = true;
return true;
}
return false;
}
/// <summary>Get whether a token has the expected value.</summary>
/// <param name="token">The token whose value to check.</param>
/// <param name="expectedValue">The value to match.</param>
private bool TokenHasValue(JToken token, object expectedValue)
{
object? actualValue = token.Value<JValue>()?.Value;
return expectedValue.Equals(actualValue);
}
}
+3 -2
View File
@@ -45,8 +45,9 @@ in future SMAPI versions.
"CheckContentIntegrity": true,
/**
* Whether to enable features intended for mod developers. Currently this only makes TRACE-level
* messages appear in the console.
* Whether to show much more info in the SMAPI consoler window, intended for mod developers.
*
* Not recommended for most players.
*/
"DeveloperMode": true,
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{season}} {{day}}",
"generic.date-with-year": "{{season}} {{day}} im Jahr {{year}}"
"generic.date-with-year": "{{season}} {{day}} im Jahr {{year}}",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+49 -1
View File
@@ -1,6 +1,54 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{season}} {{day}}",
"generic.date-with-year": "{{season}} {{day}} in year {{year}}"
"generic.date-with-year": "{{season}} {{day}} in year {{year}}",
/*********
** Generic Mod Config Menu UI
*********/
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{seasonLowercase}} {{day}}",
"generic.date-with-year": "{{seasonLowercase}} {{day}} del año {{year}}"
"generic.date-with-year": "{{seasonLowercase}} {{day}} del año {{year}}",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{day}} {{seasonLowercase}}",
"generic.date-with-year": "{{day}} {{seasonLowercase}} de l'année {{year}}"
"generic.date-with-year": "{{day}} {{seasonLowercase}} de l'année {{year}}",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{season}} {{day}}",
"generic.date-with-year": "{{year}}. év {{season}} {{day}}"
"generic.date-with-year": "{{year}}. év {{season}} {{day}}",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "Tanggal {{day}} di {{season}}",
"generic.date-with-year": "Tanggal {{day}} di {{season}} tahun ke-{{year}}"
"generic.date-with-year": "Tanggal {{day}} di {{season}} tahun ke-{{year}}",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{day}} {{season}}",
"generic.date-with-year": "{{day}} {{season}} dell'anno {{year}}"
"generic.date-with-year": "{{day}} {{season}} dell'anno {{year}}",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{season}} {{day}}日",
"generic.date-with-year": "{{year}}年目 {{season}} {{day}}日"
"generic.date-with-year": "{{year}}年目 {{season}} {{day}}日",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{season}} {{day}}일",
"generic.date-with-year": "{{year}}년차 {{season}} {{day}}일"
"generic.date-with-year": "{{year}}년차 {{season}} {{day}}일",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{day}} {{seasonLowercase}}",
"generic.date-with-year": "{{day}} {{seasonLowercase}} w roku {{year}}"
"generic.date-with-year": "{{day}} {{seasonLowercase}} w roku {{year}}",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{season}} {{day}}",
"generic.date-with-year": "{{season}} {{day}} no ano {{year}}"
"generic.date-with-year": "{{season}} {{day}} no ano {{year}}",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{season}}, {{day}}-е число",
"generic.date-with-year": "{{season}}, {{day}}-е число, {{year}}-й год"
"generic.date-with-year": "{{season}}, {{day}}-е число, {{year}}-й год",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "วันที่ {{day}} {{season}}",
"generic.date-with-year": "วันที่ {{day}} {{season}} ปีที่ {{year}}"
"generic.date-with-year": "วันที่ {{day}} {{season}} ปีที่ {{year}}",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{day}} {{season}}",
"generic.date-with-year": "{{day}} {{season}} Yıl {{year}}"
"generic.date-with-year": "{{day}} {{season}} Yıl {{year}}",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{season}}, {{day}}-й день",
"generic.date-with-year": "{{season}}, {{day}}-й день, {{year}} рік"
"generic.date-with-year": "{{season}}, {{day}}-й день, {{year}} рік",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}
+50 -1
View File
@@ -1,6 +1,55 @@
{
/*********
** Date formatting
*********/
// short date format for SDate
// tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2)
"generic.date": "{{season}}{{day}}日",
"generic.date-with-year": "第{{year}}年{{season}}{{day}}日"
"generic.date-with-year": "第{{year}}年{{season}}{{day}}日",
/*********
** Generic Mod Config Menu UI
*********/
// TODO
// 'SMAPI features' section
"config.section.features": "SMAPI features",
"config.check-for-updates.name": "Check for updates",
"config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.",
"config.check-content-integrity.name": "Check content integrity",
"config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.",
"config.read-console-input.name": "Read console input",
"config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.",
// 'Console window' section
"config.section.console-window": "Console window",
"config.developer-mode.name": "Developer mode",
"config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.",
"config.color-scheme.name": "Color scheme",
"config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.",
"config.color-scheme.options.AutoDetect": "Auto-detect",
"config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)",
"config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)",
"config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)",
"config.color-scheme.options.None": "No colors",
// 'Verbose logging' section
"config.section.verbose-logs": "Verbose logs",
"config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.",
"config.enable-for.name": "Enable for",
"config.enable-for.desc": "Choose which mods have verbose logging enabled.",
"config.enable-for.options.all": "All (not recommended)",
"config.enable-for.options.selected": "Mods selected below",
"config.enable-for-smapi.name": "SMAPI",
"config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.",
"config.enable-for-mod.name": "{{modName}}",
"config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod."
}