From 98d01d522d488192b5d5da50d70752a8c0739a94 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 5 Dec 2021 00:51:24 -0500 Subject: improve error when installer is pointed at a compatibility-branch game folder --- .../Framework/GameScanning/GameFolderType.cs | 21 +++++++++ .../Framework/GameScanning/GameScanner.cs | 54 +++++++++++++++------- 2 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 src/SMAPI.Toolkit/Framework/GameScanning/GameFolderType.cs (limited to 'src/SMAPI.Toolkit/Framework/GameScanning') diff --git a/src/SMAPI.Toolkit/Framework/GameScanning/GameFolderType.cs b/src/SMAPI.Toolkit/Framework/GameScanning/GameFolderType.cs new file mode 100644 index 00000000..d18af59b --- /dev/null +++ b/src/SMAPI.Toolkit/Framework/GameScanning/GameFolderType.cs @@ -0,0 +1,21 @@ +namespace StardewModdingAPI.Toolkit.Framework.GameScanning +{ + /// The detected validity for a Stardew Valley game folder based on file structure heuristics. + public enum GameFolderType + { + /// The folder seems to contain a valid Stardew Valley 1.5.5+ install. + Valid, + + /// The folder doesn't contain Stardew Valley. + NoGameFound, + + /// The folder contains Stardew Valley 1.5.4 or earlier. This version uses XNA Framework and 32-bit .NET Framework 4.5.2 on Windows and Mono on Linux/macOS, and isn't compatible with current versions of SMAPI. + Legacy154OrEarlier, + + /// The folder contains Stardew Valley from the game's legacy compatibility branch, which backports newer changes to the format. + LegacyCompatibilityBranch, + + /// The folder seems to contain Stardew Valley files, but they failed to load for unknown reasons (e.g. corrupted executable). + InvalidUnknown + } +} diff --git a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs index c7ebe6e0..37e4f263 100644 --- a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs +++ b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs @@ -55,36 +55,58 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning /// The folder to check. public bool LooksLikeGameFolder(DirectoryInfo dir) { - return - dir.Exists - && dir.EnumerateFiles("Stardew Valley.dll").Any(); + return this.GetGameFolderType(dir) == GameFolderType.Valid; } - /// Get whether a folder seems to contain Stardew Valley 1.5.4 or earlier. + /// Detect the validity of a game folder based on file structure heuristics. /// The folder to check. - public bool LooksLikeStardewValley154(DirectoryInfo dir) + public GameFolderType GetGameFolderType(DirectoryInfo dir) { - if (!dir.Exists || this.LooksLikeGameFolder(dir)) - return false; + // no such folder + if (!dir.Exists) + return GameFolderType.NoGameFound; - // get legacy executable - FileInfo executable = new FileInfo(Path.Combine(dir.FullName, "Stardew Valley.exe")); + // apparently valid + if (dir.EnumerateFiles("Stardew Valley.dll").Any()) + return GameFolderType.Valid; + + // doesn't contain any version of Stardew Valley + FileInfo executable = new(Path.Combine(dir.FullName, "Stardew Valley.exe")); if (!executable.Exists) - executable = new FileInfo(Path.Combine(dir.FullName, "StardewValley.exe")); + executable = new(Path.Combine(dir.FullName, "StardewValley.exe")); // pre-1.5.5 Linux/macOS executable if (!executable.Exists) - return false; + return GameFolderType.NoGameFound; - // check if it's a standard .NET assembly - // This will fail in Stardew Valley 1.5.5+, where it's a binary wrapper around Stardew Valley.dll. + // get assembly version + Version version; try { - Version version = AssemblyName.GetAssemblyName(executable.FullName).Version; - return true; + version = AssemblyName.GetAssemblyName(executable.FullName).Version; } catch { - return false; + // The executable exists but it doesn't seem to be a valid assembly. This would + // happen with Stardew Valley 1.5.5+, but that should have been flagged as a valid + // folder before this point. + return GameFolderType.InvalidUnknown; } + + // ignore Stardew Valley 1.5.5+ at this point + if (version.Major == 1 && version.Minor == 3 && version.Build == 37) + return GameFolderType.InvalidUnknown; + + // incompatible version + if (version.Major == 1 && version.Minor < 4) + { + // Stardew Valley 1.5.4 and earlier have assembly versions <= 1.3.7853.31734 + if (version.Minor < 3 || version.Build <= 7853) + return GameFolderType.Legacy154OrEarlier; + + // Stardew Valley 1.5.5+ legacy compatibility branch + return GameFolderType.LegacyCompatibilityBranch; + } + + return GameFolderType.InvalidUnknown; } /********* -- cgit