summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/manifest.json4
-rw-r--r--src/SMAPI.Mods.ErrorHandler/manifest.json4
-rw-r--r--src/SMAPI.Mods.SaveBackup/manifest.json4
-rw-r--r--src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs63
-rw-r--r--src/SMAPI.Web/Framework/LogParsing/LogParser.cs4
-rw-r--r--src/SMAPI.Web/Framework/LogParsing/Models/ParsedLog.cs3
-rw-r--r--src/SMAPI.Web/Views/LogParser/Index.cshtml6
-rw-r--r--src/SMAPI.Web/wwwroot/Content/js/log-parser.js11
-rw-r--r--src/SMAPI/Constants.cs2
-rw-r--r--src/SMAPI/Framework/Content/AssetDataForImage.cs2
-rw-r--r--src/SMAPI/Framework/Models/SConfig.cs34
-rw-r--r--src/SMAPI/Framework/SCore.cs19
-rw-r--r--src/SMAPI/SMAPI.config.json6
13 files changed, 94 insertions, 68 deletions
diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json
index ecac30bf..d1296dbe 100644
--- a/src/SMAPI.Mods.ConsoleCommands/manifest.json
+++ b/src/SMAPI.Mods.ConsoleCommands/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Console Commands",
"Author": "SMAPI",
- "Version": "3.17.1",
+ "Version": "3.17.2",
"Description": "Adds SMAPI console commands that let you manipulate the game.",
"UniqueID": "SMAPI.ConsoleCommands",
"EntryDll": "ConsoleCommands.dll",
- "MinimumApiVersion": "3.17.1"
+ "MinimumApiVersion": "3.17.2"
}
diff --git a/src/SMAPI.Mods.ErrorHandler/manifest.json b/src/SMAPI.Mods.ErrorHandler/manifest.json
index 3d708876..c3757e8f 100644
--- a/src/SMAPI.Mods.ErrorHandler/manifest.json
+++ b/src/SMAPI.Mods.ErrorHandler/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Error Handler",
"Author": "SMAPI",
- "Version": "3.17.1",
+ "Version": "3.17.2",
"Description": "Handles some common vanilla errors to log more useful info or avoid breaking the game.",
"UniqueID": "SMAPI.ErrorHandler",
"EntryDll": "ErrorHandler.dll",
- "MinimumApiVersion": "3.17.1"
+ "MinimumApiVersion": "3.17.2"
}
diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json
index c2bf5f05..78821a3e 100644
--- a/src/SMAPI.Mods.SaveBackup/manifest.json
+++ b/src/SMAPI.Mods.SaveBackup/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Save Backup",
"Author": "SMAPI",
- "Version": "3.17.1",
+ "Version": "3.17.2",
"Description": "Automatically backs up all your saves once per day into its folder.",
"UniqueID": "SMAPI.SaveBackup",
"EntryDll": "SaveBackup.dll",
- "MinimumApiVersion": "3.17.1"
+ "MinimumApiVersion": "3.17.2"
}
diff --git a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs
index 1d518738..88142805 100644
--- a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs
+++ b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs
@@ -261,39 +261,50 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
/// <returns>The game directory, if found.</returns>
private string? GetPathFromSteamLibrary(string? steamPath)
{
- if (steamPath == null)
- return null;
-
- // get .vdf file path
- string libraryFoldersPath = Path.Combine(steamPath.Replace('/', '\\'), "steamapps\\libraryfolders.vdf");
- if (!File.Exists(libraryFoldersPath))
- return null;
-
- // read data
- using FileStream fileStream = File.OpenRead(libraryFoldersPath);
- VdfDeserializer deserializer = new();
- dynamic libraries = deserializer.Deserialize(fileStream);
- if (libraries?.libraryfolders is null)
- return null;
-
- // get path from Stardew Valley app (if any)
- foreach (dynamic pair in libraries.libraryfolders)
+ try
{
- dynamic library = pair.Value;
-
- foreach (dynamic app in library.apps)
+ if (steamPath == null)
+ return null;
+
+ // get .vdf file path
+ string libraryFoldersPath = Path.Combine(steamPath.Replace('/', '\\'), "steamapps\\libraryfolders.vdf");
+ if (!File.Exists(libraryFoldersPath))
+ return null;
+
+ // read data
+ using FileStream fileStream = File.OpenRead(libraryFoldersPath);
+ VdfDeserializer deserializer = new();
+ dynamic libraries = deserializer.Deserialize(fileStream);
+ if (libraries?.libraryfolders is null)
+ return null;
+
+ // get path from Stardew Valley app (if any)
+ foreach (dynamic pair in libraries.libraryfolders)
{
- string key = app.Key;
- if (key == GameScanner.SteamAppId)
+ dynamic library = pair.Value;
+
+ foreach (dynamic app in library.apps)
{
- string path = library.path;
+ string key = app.Key;
+ if (key == GameScanner.SteamAppId)
+ {
+ string path = library.path;
- return Path.Combine(path.Replace("\\\\", "\\"), "steamapps", "common", "Stardew Valley");
+ return Path.Combine(path.Replace("\\\\", "\\"), "steamapps", "common", "Stardew Valley");
+ }
}
}
- }
- return null;
+ return null;
+ }
+ catch
+ {
+ // The file might not be parseable in some cases (e.g. some players have an older Steam version using
+ // a different format). Ideally we'd log an error to know when it's actually an issue, but the SMAPI
+ // installer doesn't have a logging mechanism (and third-party code calling the toolkit may not either).
+ // So for now, just ignore the error and fallback to the other discovery mechanisms.
+ return null;
+ }
}
#endif
}
diff --git a/src/SMAPI.Web/Framework/LogParsing/LogParser.cs b/src/SMAPI.Web/Framework/LogParsing/LogParser.cs
index 5e0dedf3..c39e612b 100644
--- a/src/SMAPI.Web/Framework/LogParsing/LogParser.cs
+++ b/src/SMAPI.Web/Framework/LogParsing/LogParser.cs
@@ -108,6 +108,10 @@ namespace StardewModdingAPI.Web.Framework.LogParsing
}
}
+ // detect split-screen mode
+ if (message.ScreenId != 0)
+ log.IsSplitScreen = true;
+
// collect SMAPI metadata
if (message.Mod == "SMAPI")
{
diff --git a/src/SMAPI.Web/Framework/LogParsing/Models/ParsedLog.cs b/src/SMAPI.Web/Framework/LogParsing/Models/ParsedLog.cs
index cda0f653..2a2e5f5c 100644
--- a/src/SMAPI.Web/Framework/LogParsing/Models/ParsedLog.cs
+++ b/src/SMAPI.Web/Framework/LogParsing/Models/ParsedLog.cs
@@ -22,6 +22,9 @@ namespace StardewModdingAPI.Web.Framework.LogParsing.Models
/// <summary>The raw log text.</summary>
public string? RawText { get; set; }
+ /// <summary>Whether there are messages from multiple screens in the log.</summary>
+ public bool IsSplitScreen { get; set; }
+
/****
** Log data
****/
diff --git a/src/SMAPI.Web/Views/LogParser/Index.cshtml b/src/SMAPI.Web/Views/LogParser/Index.cshtml
index 28127903..c1251c21 100644
--- a/src/SMAPI.Web/Views/LogParser/Index.cshtml
+++ b/src/SMAPI.Web/Views/LogParser/Index.cshtml
@@ -47,7 +47,7 @@
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1" crossorigin="anonymous"></script>
<script src="~/Content/js/file-upload.js"></script>
- <script src="~/Content/js/log-parser.js?r=20220409"></script>
+ <script src="~/Content/js/log-parser.js"></script>
<script id="serializedData" type="application/json">
@if (!Model.ShowRaw)
@@ -86,7 +86,8 @@
showMods: @this.ForJson(log?.Mods.Where(p => p.Loaded && !p.IsContentPack).Select(p => Model.GetSlug(p.Name)).Distinct().ToDictionary(slug => slug, _ => true)),
showSections: @this.ForJson(Enum.GetNames(typeof(LogSection)).ToDictionary(section => section, _ => false)),
showLevels: @this.ForJson(defaultFilters),
- enableFilters: @this.ForJson(!Model.ShowRaw)
+ enableFilters: @this.ForJson(!Model.ShowRaw),
+ isSplitScreen: @this.ForJson(log?.IsSplitScreen ?? false)
}
);
@@ -494,7 +495,6 @@ else if (log?.IsValid == true)
<log-line
v-for="msg in visibleMessages"
v-bind:key="msg.id"
- v-bind:showScreenId="showScreenId"
v-bind:message="msg"
v-bind:highlight="shouldHighlight"
/>
diff --git a/src/SMAPI.Web/wwwroot/Content/js/log-parser.js b/src/SMAPI.Web/wwwroot/Content/js/log-parser.js
index fccd00be..324218bb 100644
--- a/src/SMAPI.Web/wwwroot/Content/js/log-parser.js
+++ b/src/SMAPI.Web/wwwroot/Content/js/log-parser.js
@@ -424,10 +424,6 @@ smapi.logParser = function (state) {
Vue.component("log-line", {
functional: true,
props: {
- showScreenId: {
- type: Boolean,
- required: true
- },
message: {
type: Object,
required: true
@@ -456,7 +452,7 @@ smapi.logParser = function (state) {
"td",
{
attrs: {
- colspan: context.props.showScreenId ? 4 : 3
+ colspan: state.isSplitScreen ? 4 : 3
}
},
""
@@ -541,7 +537,7 @@ smapi.logParser = function (state) {
},
[
createElement("td", message.Time),
- context.props.showScreenId ? createElement("td", message.ScreenId) : null,
+ state.isSplitScreen ? createElement("td", { attrs: { title: (message.ScreenId == 0 ? "main screen" : "screen #" + (message.ScreenId + 1)) + " in split-screen mode" } }, `🖵${message.ScreenId + 1}`) : null,
createElement("td", level.toUpperCase()),
createElement(
"td",
@@ -588,9 +584,6 @@ smapi.logParser = function (state) {
anyModsShown: function () {
return stats.modsShown > 0;
},
- showScreenId: function () {
- return this.data.screenIds.length > 1;
- },
// Maybe not strictly necessary, but the Vue template is being
// weird about accessing data entries on the app rather than
diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs
index ea41a4ee..77900ca6 100644
--- a/src/SMAPI/Constants.cs
+++ b/src/SMAPI/Constants.cs
@@ -52,7 +52,7 @@ namespace StardewModdingAPI
internal static int? LogScreenId { get; set; }
/// <summary>SMAPI's current raw semantic version.</summary>
- internal static string RawApiVersion = "3.17.1";
+ internal static string RawApiVersion = "3.17.2";
}
/// <summary>Contains SMAPI's constants and assumptions.</summary>
diff --git a/src/SMAPI/Framework/Content/AssetDataForImage.cs b/src/SMAPI/Framework/Content/AssetDataForImage.cs
index 241c09a8..7c8cc6a8 100644
--- a/src/SMAPI/Framework/Content/AssetDataForImage.cs
+++ b/src/SMAPI/Framework/Content/AssetDataForImage.cs
@@ -192,7 +192,7 @@ namespace StardewModdingAPI.Framework.Content
int topOffset = startIndex / sourceArea.Width;
int bottomOffset = endIndex / sourceArea.Width;
- targetArea = new(targetArea.X, targetArea.Y + topOffset, targetArea.Width, bottomOffset - topOffset + 1);
+ targetArea = new(targetArea.X, targetArea.Y + topOffset - startRow, targetArea.Width, bottomOffset - topOffset + 1);
pixelCount = targetArea.Width * targetArea.Height;
sourceOffset = topOffset * sourceArea.Width;
}
diff --git a/src/SMAPI/Framework/Models/SConfig.cs b/src/SMAPI/Framework/Models/SConfig.cs
index bceb0940..825ebb44 100644
--- a/src/SMAPI/Framework/Models/SConfig.cs
+++ b/src/SMAPI/Framework/Models/SConfig.cs
@@ -16,6 +16,7 @@ namespace StardewModdingAPI.Framework.Models
private static readonly IDictionary<string, object> DefaultValues = new Dictionary<string, object>
{
[nameof(CheckForUpdates)] = true,
+ [nameof(ListenForConsoleInput)] = true,
[nameof(ParanoidWarnings)] = Constants.IsDebugBuild,
[nameof(UseBetaChannel)] = Constants.ApiVersion.IsPrerelease(),
[nameof(GitHubProjectName)] = "Pathoschild/SMAPI",
@@ -48,6 +49,9 @@ namespace StardewModdingAPI.Framework.Models
/// <summary>Whether to check for newer versions of SMAPI and mods on startup.</summary>
public bool CheckForUpdates { get; set; }
+ /// <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>
public bool ParanoidWarnings { get; set; }
@@ -87,23 +91,25 @@ namespace StardewModdingAPI.Framework.Models
** Public methods
********/
/// <summary>Construct an instance.</summary>
- /// <param name="developerMode">Whether to enable development features.</param>
- /// <param name="checkForUpdates">Whether to check for newer versions of SMAPI and mods on startup.</param>
- /// <param name="paranoidWarnings">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.</param>
- /// <param name="useBetaChannel">Whether to show beta versions as valid updates.</param>
- /// <param name="gitHubProjectName">SMAPI's GitHub project name, used to perform update checks.</param>
- /// <param name="webApiBaseUrl">The base URL for SMAPI's web API, used to perform update checks.</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="rewriteMods">Whether SMAPI should rewrite mods for compatibility.</param>
- /// <param name="useCaseInsensitivePaths">>Whether to make SMAPI file APIs case-insensitive, even on Linux.</param>
- /// <param name="logNetworkTraffic">Whether SMAPI should log network traffic.</param>
- /// <param name="consoleColors">The colors to use for text written to the SMAPI console.</param>
- /// <param name="suppressHarmonyDebugMode">Whether to prevent mods from enabling Harmony's debug mode, which impacts performance and creates a file on your desktop. Debug mode should never be enabled by a released mod.</param>
- /// <param name="suppressUpdateChecks">The mod IDs SMAPI should ignore when performing update checks or validating update keys.</param>
- public SConfig(bool developerMode, bool? checkForUpdates, bool? paranoidWarnings, bool? useBetaChannel, string gitHubProjectName, string webApiBaseUrl, string[]? verboseLogging, bool? rewriteMods, bool? useCaseInsensitivePaths, bool? logNetworkTraffic, ColorSchemeConfig consoleColors, bool? suppressHarmonyDebugMode, string[]? suppressUpdateChecks)
+ /// <param name="developerMode"><inheritdoc cref="DeveloperMode" path="/summary" /></param>
+ /// <param name="checkForUpdates"><inheritdoc cref="CheckForUpdates" path="/summary" /></param>
+ /// <param name="listenForConsoleInput"><inheritdoc cref="ListenForConsoleInput" path="/summary" /></param>
+ /// <param name="paranoidWarnings"><inheritdoc cref="ParanoidWarnings" path="/summary" /></param>
+ /// <param name="useBetaChannel"><inheritdoc cref="UseBetaChannel" path="/summary" /></param>
+ /// <param name="gitHubProjectName"><inheritdoc cref="GitHubProjectName" path="/summary" /></param>
+ /// <param name="webApiBaseUrl"><inheritdoc cref="WebApiBaseUrl" path="/summary" /></param>
+ /// <param name="verboseLogging"><inheritdoc cref="VerboseLogging" path="/summary" /></param>
+ /// <param name="rewriteMods"><inheritdoc cref="RewriteMods" path="/summary" /></param>
+ /// <param name="useCaseInsensitivePaths"><inheritdoc cref="UseCaseInsensitivePaths" path="/summary" /></param>
+ /// <param name="logNetworkTraffic"><inheritdoc cref="LogNetworkTraffic" path="/summary" /></param>
+ /// <param name="consoleColors"><inheritdoc cref="ConsoleColors" path="/summary" /></param>
+ /// <param name="suppressHarmonyDebugMode"><inheritdoc cref="SuppressHarmonyDebugMode" path="/summary" /></param>
+ /// <param name="suppressUpdateChecks"><inheritdoc cref="SuppressUpdateChecks" path="/summary" /></param>
+ public SConfig(bool developerMode, bool? checkForUpdates, bool? listenForConsoleInput, bool? paranoidWarnings, bool? useBetaChannel, string gitHubProjectName, string webApiBaseUrl, string[]? verboseLogging, bool? rewriteMods, bool? useCaseInsensitivePaths, bool? logNetworkTraffic, ColorSchemeConfig consoleColors, bool? suppressHarmonyDebugMode, string[]? suppressUpdateChecks)
{
this.DeveloperMode = developerMode;
this.CheckForUpdates = checkForUpdates ?? (bool)SConfig.DefaultValues[nameof(this.CheckForUpdates)];
+ this.ListenForConsoleInput = listenForConsoleInput ?? (bool)SConfig.DefaultValues[nameof(this.ListenForConsoleInput)];
this.ParanoidWarnings = paranoidWarnings ?? (bool)SConfig.DefaultValues[nameof(this.ParanoidWarnings)];
this.UseBetaChannel = useBetaChannel ?? (bool)SConfig.DefaultValues[nameof(this.UseBetaChannel)];
this.GitHubProjectName = gitHubProjectName;
diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs
index 40979b09..7bb54653 100644
--- a/src/SMAPI/Framework/SCore.cs
+++ b/src/SMAPI/Framework/SCore.cs
@@ -447,14 +447,17 @@ namespace StardewModdingAPI.Framework
this.Monitor.Log("SMAPI found problems in your game's content files which are likely to cause errors or crashes. Consider uninstalling XNB mods or reinstalling the game.", LogLevel.Error);
// start SMAPI console
- new Thread(
- () => this.LogManager.RunConsoleInputLoop(
- commandManager: this.CommandManager,
- reloadTranslations: this.ReloadTranslations,
- handleInput: input => this.RawCommandQueue.Add(input),
- continueWhile: () => this.IsGameRunning && !this.IsExiting
- )
- ).Start();
+ if (this.Settings.ListenForConsoleInput)
+ {
+ new Thread(
+ () => this.LogManager.RunConsoleInputLoop(
+ commandManager: this.CommandManager,
+ reloadTranslations: this.ReloadTranslations,
+ handleInput: input => this.RawCommandQueue.Add(input),
+ continueWhile: () => this.IsGameRunning && !this.IsExiting
+ )
+ ).Start();
+ }
}
/// <summary>Raised after an instance finishes loading its initial content.</summary>
diff --git a/src/SMAPI/SMAPI.config.json b/src/SMAPI/SMAPI.config.json
index 635e3add..52f25fdd 100644
--- a/src/SMAPI/SMAPI.config.json
+++ b/src/SMAPI/SMAPI.config.json
@@ -42,6 +42,12 @@ copy all the settings, or you may cause bugs due to overridden changes in future
"DeveloperMode": true,
/**
+ * 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.
+ */
+ "ListenForConsoleInput": true,
+
+ /**
* Whether SMAPI should rewrite mods for compatibility. This may prevent older mods from
* loading, but bypasses a Visual Studio crash when debugging.
*/