summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/release-notes.md3
-rw-r--r--src/SMAPI.Installer/InteractiveInstaller.cs12
-rw-r--r--src/SMAPI.Toolkit/Properties/AssemblyInfo.cs1
-rw-r--r--src/SMAPI.Toolkit/Utilities/PathUtilities.cs25
-rw-r--r--src/SMAPI/Framework/Logging/LogManager.cs13
5 files changed, 52 insertions, 2 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md
index ebe44f09..39e33305 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -9,8 +9,9 @@
## Upcoming release
* For players:
- * Fixed console showing _found 1 mod with warnings_ with no mods listed.
* If the installer crashes, the window now stays open if possible so you can read the error and ask for help.
+ * Added descriptive error if possible when a `PathTooLongException` crashes SMAPI or the installer.
+ * Fixed console showing _found 1 mod with warnings_ with no mods listed.
* For mod authors:
* Added three stages to the `LoadStageChanged` event: `CreatedInitialLocations`/`SaveAddedLocations` (raised immediately after the game adds locations but before they're initialized), and `ReturningToTitle` (raised before exiting to the title screen).
diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs
index ff74a659..3d673719 100644
--- a/src/SMAPI.Installer/InteractiveInstaller.cs
+++ b/src/SMAPI.Installer/InteractiveInstaller.cs
@@ -279,6 +279,7 @@ namespace StardewModdingApi.Installer
/*********
** Step 4: validate assumptions
*********/
+ // executable exists
if (!File.Exists(paths.ExecutablePath))
{
this.PrintError("The detected game install path doesn't contain a Stardew Valley executable.");
@@ -286,6 +287,17 @@ namespace StardewModdingApi.Installer
return;
}
+ // game folder doesn't contain paths beyond the max limit
+ {
+ string[] tooLongPaths = PathUtilities.GetTooLongPaths(Path.Combine(paths.GamePath, "Mods")).ToArray();
+ if (tooLongPaths.Any())
+ {
+ this.PrintError($"SMAPI can't install to the detected game folder, because some of its files exceed the maximum {context.Platform} path length.\nIf you need help fixing this error, see https://smapi.io/help\n\nAffected paths:\n {string.Join("\n ", tooLongPaths)}");
+ Console.ReadLine();
+ return;
+ }
+ }
+
/*********
** Step 5: ask what to do
diff --git a/src/SMAPI.Toolkit/Properties/AssemblyInfo.cs b/src/SMAPI.Toolkit/Properties/AssemblyInfo.cs
index 233e680b..eede4562 100644
--- a/src/SMAPI.Toolkit/Properties/AssemblyInfo.cs
+++ b/src/SMAPI.Toolkit/Properties/AssemblyInfo.cs
@@ -1,4 +1,5 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("StardewModdingAPI")]
+[assembly: InternalsVisibleTo("SMAPI.Installer")]
[assembly: InternalsVisibleTo("SMAPI.Web")]
diff --git a/src/SMAPI.Toolkit/Utilities/PathUtilities.cs b/src/SMAPI.Toolkit/Utilities/PathUtilities.cs
index c9fb6213..a394edba 100644
--- a/src/SMAPI.Toolkit/Utilities/PathUtilities.cs
+++ b/src/SMAPI.Toolkit/Utilities/PathUtilities.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
@@ -133,5 +134,29 @@ namespace StardewModdingAPI.Toolkit.Utilities
{
return !Regex.IsMatch(str, "[^a-z0-9_.-]", RegexOptions.IgnoreCase);
}
+
+ /// <summary>Get the paths which exceed the OS length limit.</summary>
+ /// <param name="rootPath">The root path to search.</param>
+ internal static IEnumerable<string> GetTooLongPaths(string rootPath)
+ {
+ return Directory
+ .EnumerateFileSystemEntries(rootPath, "*.*", SearchOption.AllDirectories)
+ .Where(PathUtilities.IsPathTooLong);
+ }
+
+ /// <summary>Get whether a file or directory path exceeds the OS path length limit.</summary>
+ /// <param name="path">The path to test.</param>
+ internal static bool IsPathTooLong(string path)
+ {
+ try
+ {
+ _ = Path.GetFullPath(path);
+ return false;
+ }
+ catch (PathTooLongException)
+ {
+ return true;
+ }
+ }
}
}
diff --git a/src/SMAPI/Framework/Logging/LogManager.cs b/src/SMAPI/Framework/Logging/LogManager.cs
index f3656886..0dd45355 100644
--- a/src/SMAPI/Framework/Logging/LogManager.cs
+++ b/src/SMAPI/Framework/Logging/LogManager.cs
@@ -252,11 +252,22 @@ namespace StardewModdingAPI.Framework.Logging
break;
// missing content folder exception
- case FileNotFoundException ex when ex.Message == "Could not find file 'C:\\Program Files (x86)\\Steam\\SteamApps\\common\\Stardew Valley\\Content\\XACT\\FarmerSounds.xgs'.": // path in error is hardcoded regardless of install path
+ case FileNotFoundException ex when ex.Message == "Couldn't find file 'C:\\Program Files (x86)\\Steam\\SteamApps\\common\\Stardew Valley\\Content\\XACT\\FarmerSounds.xgs'.": // path in error is hardcoded regardless of install path
this.Monitor.Log("The game can't find its Content\\XACT\\FarmerSounds.xgs file. You can usually fix this by resetting your content files (see https://smapi.io/troubleshoot#reset-content ), or by uninstalling and reinstalling the game.", LogLevel.Error);
this.Monitor.Log($"Technical details: {ex.GetLogSummary()}");
break;
+ // path too long exception
+ case PathTooLongException:
+ {
+ string[] affectedPaths = PathUtilities.GetTooLongPaths(Constants.ModsPath).ToArray();
+ string message = affectedPaths.Any()
+ ? $"SMAPI can't launch because some of your mod files exceed the maximum path length on {Constants.Platform}.\nIf you need help fixing this error, see https://smapi.io/help\n\nAffected paths:\n {string.Join("\n ", affectedPaths)}"
+ : $"The game failed to launch: {exception.GetLogSummary()}";
+ this.MonitorForGame.Log(message, LogLevel.Error);
+ }
+ break;
+
// generic exception
default:
this.MonitorForGame.Log($"The game failed to launch: {exception.GetLogSummary()}", LogLevel.Error);