summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2021-08-25 21:54:00 -0400
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2021-08-25 21:54:00 -0400
commit211f89821e34bb55a6266384d9bac68ec0c64744 (patch)
treeaa0d9915b01aad436ed6b1a2028602c048666457
parent80d3dd1f786f7e5846f9adb7f7a4d82e5b9b92fd (diff)
parent31ac964a8b19623b0472931403a33d51db6fb271 (diff)
downloadSMAPI-211f89821e34bb55a6266384d9bac68ec0c64744.tar.gz
SMAPI-211f89821e34bb55a6266384d9bac68ec0c64744.tar.bz2
SMAPI-211f89821e34bb55a6266384d9bac68ec0c64744.zip
Merge branch 'develop' into stable
-rw-r--r--build/common.targets2
-rw-r--r--docs/release-notes.md21
-rw-r--r--docs/technical/mod-package.md33
-rw-r--r--src/SMAPI.Installer/InteractiveInstaller.cs2
-rw-r--r--src/SMAPI.Internal/ExceptionExtensions.cs27
-rw-r--r--src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs3
-rw-r--r--src/SMAPI.ModBuildConfig.Analyzer/ObsoleteFieldAnalyzer.cs3
-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/LowLevelEnvironmentUtility.cs6
-rw-r--r--src/SMAPI.Toolkit/SemanticVersionComparer.cs32
-rw-r--r--src/SMAPI.Toolkit/Utilities/EnvironmentUtility.cs7
-rw-r--r--src/SMAPI.Web/Controllers/ModsApiController.cs6
-rw-r--r--src/SMAPI.Web/Framework/ModSiteManager.cs73
-rw-r--r--src/SMAPI.Web/SMAPI.Web.csproj2
-rw-r--r--src/SMAPI.Web/Views/Mods/Index.cshtml2
-rw-r--r--src/SMAPI/Constants.cs29
-rw-r--r--src/SMAPI/Framework/Logging/LogManager.cs7
-rw-r--r--src/SMAPI/Framework/ModHelpers/DataHelper.cs6
-rw-r--r--src/SMAPI/Framework/ModHelpers/TranslationHelper.cs6
-rw-r--r--src/SMAPI/Framework/ModLoading/AssemblyDefinitionResolver.cs16
-rw-r--r--src/SMAPI/Framework/ModLoading/AssemblyLoader.cs38
-rw-r--r--src/SMAPI/Framework/ModLoading/Symbols/SymbolReader.cs72
-rw-r--r--src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs54
-rw-r--r--src/SMAPI/Framework/ModLoading/Symbols/SymbolWriterProvider.cs40
-rw-r--r--src/SMAPI/Framework/SCore.cs15
-rw-r--r--src/SMAPI/Framework/Translator.cs65
-rw-r--r--src/SMAPI/IDataHelper.cs6
-rw-r--r--src/SMAPI/ITranslationHelper.cs7
30 files changed, 484 insertions, 108 deletions
diff --git a/build/common.targets b/build/common.targets
index 498ec7af..06e0a245 100644
--- a/build/common.targets
+++ b/build/common.targets
@@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!--set general build properties -->
- <Version>3.12.2</Version>
+ <Version>3.12.3</Version>
<Product>SMAPI</Product>
<LangVersion>latest</LangVersion>
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 4e9dacbf..07eb6c03 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -1,8 +1,27 @@
← [README](README.md)
# Release notes
+## 3.12.3
+Released 25 August 2021 for Stardew Valley 1.5.4 or later.
+
+* For players:
+ * Added friendly error in 64-bit mode when a mod is 32-bit only.
+ * Fixed console encoding issues on Linux/macOS.
+ * Fixed some installer errors not showing info header.
+
+* For mod authors:
+ * Added `helper.Translation.GetInAllLocales` to get a translation in every available locale.
+ * Fixed Visual Studio debugger crash when any mods are rewritten for compatibility (thanks to spacechase0!).
+ * Fixed `helper.Data.WriteJsonFile` not deleting the file if the model is null, unlike the other `Write*` methods.
+ * Fixed error-handling for `StackOverflowException` thrown on Linux/macOS.
+ * Internal changes to prepare for Stardew Valley 1.5.5.
+
+* For the web API:
+ * Fixed update checks not shown for prerelease mod versions when you have a SMAPI beta.
+ * Fixed update checks shown for prerelease mod versions if you have a working non-prerelease version.
+
## 3.12.2
-Released 04 August 2021 for Stardew Valley 1.5.4 or later.
+Released 05 August 2021 for Stardew Valley 1.5.4 or later.
* For players:
* Fixed error creating a new save or joining a multiplayer world in 3.12.1.
diff --git a/docs/technical/mod-package.md b/docs/technical/mod-package.md
index 91da971b..7eefc7a4 100644
--- a/docs/technical/mod-package.md
+++ b/docs/technical/mod-package.md
@@ -365,7 +365,10 @@ The NuGet package is generated automatically in `StardewModdingAPI.ModBuildConfi
when you compile it.
## Release notes
-## 3.3
+## Upcoming release
+* Improved analyzer performance by enabling parallel execution.
+
+## 3.3.0
Released 30 March 2021.
* Added a build warning when the mod isn't compiled for `Any CPU`.
@@ -385,19 +388,19 @@ Released 11 September 2020.
* Added more detailed logging.
* Fixed _path's format is not supported_ error when using default `Mods` path in 3.2.
-### 3.2
+### 3.2.0
Released 07 September 2020.
* Added option to change `Mods` folder path.
* Rewrote documentation to make it easier to read.
-### 3.1
+### 3.1.0
Released 01 February 2020.
* Added support for semantic versioning 2.0.
* `0Harmony.dll` is now ignored if the mod references Harmony directly (it's bundled with SMAPI).
-### 3.0
+### 3.0.0
Released 26 November 2019.
* Updated for SMAPI 3.0 and Stardew Valley 1.4.
@@ -412,14 +415,14 @@ Released 26 November 2019.
* Dropped support for older versions of SMAPI and Visual Studio.
* Migrated package icon to NuGet's new format.
-### 2.2
+### 2.2.0
Released 28 October 2018.
* Added support for SMAPI 2.8+ (still compatible with earlier versions).
* Added default game paths for 32-bit Windows.
* Fixed valid manifests marked invalid in some cases.
-### 2.1
+### 2.1.0
Released 27 July 2018.
* Added support for Stardew Valley 1.3.
@@ -439,7 +442,7 @@ Released 11 October 2017.
* Fixed mod deploy failing to create subfolders if they don't already exist.
-### 2.0
+### 2.0.0
Released 11 October 2017.
* Added: mods are now copied into the `Mods` folder automatically (configurable).
@@ -457,7 +460,7 @@ Released 28 July 2017.
* The manifest/i18n files in the project now take precedence over those in the build output if both
are present.
-### 1.7
+### 1.7.0
Released 28 July 2017.
* Added option to create release zips on build.
@@ -474,19 +477,19 @@ Released 09 July 2017.
* Improved crossplatform game path detection.
-### 1.6
+### 1.6.0
Released 05 June 2017.
* Added support for deploying mod files into `Mods` automatically.
* Added a build error if a game folder is found, but doesn't contain Stardew Valley or SMAPI.
-### 1.5
+### 1.5.0
Released 23 January 2017.
* Added support for setting a custom game path globally.
* Added default GOG path on macOS.
-### 1.4
+### 1.4.0
Released 11 January 2017.
* Fixed detection of non-default game paths on 32-bit Windows.
@@ -494,22 +497,22 @@ Released 11 January 2017.
* Removed support for overriding the target platform (no longer needed since SMAPI crossplatforms
mods automatically).
-### 1.3
+### 1.3.0
Released 31 December 2016.
* Added support for non-default game paths on Windows.
-### 1.2
+### 1.2.0
Released 24 October 2016.
* Exclude game binaries from mod build output.
-### 1.1
+### 1.1.0
Released 21 October 2016.
* Added support for overriding the target platform.
-### 1.0
+### 1.0.0
Released 21 October 2016.
* Initial release.
diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs
index ab07c864..b91d0dd3 100644
--- a/src/SMAPI.Installer/InteractiveInstaller.cs
+++ b/src/SMAPI.Installer/InteractiveInstaller.cs
@@ -272,7 +272,6 @@ namespace StardewModdingApi.Installer
DirectoryInfo bundleDir = new DirectoryInfo(this.BundlePath);
paths = new InstallerPaths(bundleDir, installDir, context.ExecutableName);
}
- Console.Clear();
/*********
@@ -309,6 +308,7 @@ namespace StardewModdingApi.Installer
return;
}
}
+ Console.Clear();
/*********
diff --git a/src/SMAPI.Internal/ExceptionExtensions.cs b/src/SMAPI.Internal/ExceptionExtensions.cs
index 5f1ee1fa..d8189048 100644
--- a/src/SMAPI.Internal/ExceptionExtensions.cs
+++ b/src/SMAPI.Internal/ExceptionExtensions.cs
@@ -13,19 +13,26 @@ namespace StardewModdingAPI.Internal
/// <param name="exception">The error to summarize.</param>
public static string GetLogSummary(this Exception exception)
{
- switch (exception)
+ try
{
- case TypeLoadException ex:
- return $"Failed loading type '{ex.TypeName}': {exception}";
+ switch (exception)
+ {
+ case TypeLoadException ex:
+ return $"Failed loading type '{ex.TypeName}': {exception}";
- case ReflectionTypeLoadException ex:
- string summary = ex.ToString();
- foreach (Exception childEx in ex.LoaderExceptions ?? new Exception[0])
- summary += $"\n\n{childEx?.GetLogSummary()}";
- return summary;
+ case ReflectionTypeLoadException ex:
+ string summary = ex.ToString();
+ foreach (Exception childEx in ex.LoaderExceptions ?? new Exception[0])
+ summary += $"\n\n{childEx?.GetLogSummary()}";
+ return summary;
- default:
- return exception.ToString();
+ default:
+ return exception?.ToString() ?? $"<null exception>\n{Environment.StackTrace}";
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"Failed handling {exception?.GetType().FullName} (original message: {exception?.Message})", ex);
}
}
diff --git a/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs b/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs
index a9b981bd..1efc1616 100644
--- a/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs
+++ b/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs
@@ -174,6 +174,9 @@ namespace StardewModdingAPI.ModBuildConfig.Analyzer
/// <param name="context">The analysis context.</param>
public override void Initialize(AnalysisContext context)
{
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
+ context.EnableConcurrentExecution();
+
context.RegisterSyntaxNodeAction(
this.AnalyzeMemberAccess,
SyntaxKind.SimpleMemberAccessExpression,
diff --git a/src/SMAPI.ModBuildConfig.Analyzer/ObsoleteFieldAnalyzer.cs b/src/SMAPI.ModBuildConfig.Analyzer/ObsoleteFieldAnalyzer.cs
index d071f0c1..722d5227 100644
--- a/src/SMAPI.ModBuildConfig.Analyzer/ObsoleteFieldAnalyzer.cs
+++ b/src/SMAPI.ModBuildConfig.Analyzer/ObsoleteFieldAnalyzer.cs
@@ -56,6 +56,9 @@ namespace StardewModdingAPI.ModBuildConfig.Analyzer
/// <param name="context">The analysis context.</param>
public override void Initialize(AnalysisContext context)
{
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
+ context.EnableConcurrentExecution();
+
context.RegisterSyntaxNodeAction(
this.AnalyzeObsoleteFields,
SyntaxKind.SimpleMemberAccessExpression,
diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json
index 6b49cd5f..e04d3497 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.12.2",
+ "Version": "3.12.3",
"Description": "Adds SMAPI console commands that let you manipulate the game.",
"UniqueID": "SMAPI.ConsoleCommands",
"EntryDll": "ConsoleCommands.dll",
- "MinimumApiVersion": "3.12.2"
+ "MinimumApiVersion": "3.12.3"
}
diff --git a/src/SMAPI.Mods.ErrorHandler/manifest.json b/src/SMAPI.Mods.ErrorHandler/manifest.json
index 7759d1d5..54758a36 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.12.2",
+ "Version": "3.12.3",
"Description": "Handles some common vanilla errors to log more useful info or avoid breaking the game.",
"UniqueID": "SMAPI.ErrorHandler",
"EntryDll": "ErrorHandler.dll",
- "MinimumApiVersion": "3.12.2"
+ "MinimumApiVersion": "3.12.3"
}
diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json
index 1e5b8b97..f23f0958 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.12.2",
+ "Version": "3.12.3",
"Description": "Automatically backs up all your saves once per day into its folder.",
"UniqueID": "SMAPI.SaveBackup",
"EntryDll": "SaveBackup.dll",
- "MinimumApiVersion": "3.12.2"
+ "MinimumApiVersion": "3.12.3"
}
diff --git a/src/SMAPI.Toolkit/Framework/LowLevelEnvironmentUtility.cs b/src/SMAPI.Toolkit/Framework/LowLevelEnvironmentUtility.cs
index be0c18ce..2636aae0 100644
--- a/src/SMAPI.Toolkit/Framework/LowLevelEnvironmentUtility.cs
+++ b/src/SMAPI.Toolkit/Framework/LowLevelEnvironmentUtility.cs
@@ -90,10 +90,10 @@ namespace StardewModdingAPI.Toolkit.Framework
}
/// <summary>Get whether an executable is 64-bit.</summary>
- /// <param name="executablePath">The absolute path to the executable file.</param>
- public static bool Is64BitAssembly(string executablePath)
+ /// <param name="path">The absolute path to the assembly file.</param>
+ public static bool Is64BitAssembly(string path)
{
- return AssemblyName.GetAssemblyName(executablePath).ProcessorArchitecture != ProcessorArchitecture.X86;
+ return AssemblyName.GetAssemblyName(path).ProcessorArchitecture != ProcessorArchitecture.X86;
}
diff --git a/src/SMAPI.Toolkit/SemanticVersionComparer.cs b/src/SMAPI.Toolkit/SemanticVersionComparer.cs
new file mode 100644
index 00000000..9f6b57a2
--- /dev/null
+++ b/src/SMAPI.Toolkit/SemanticVersionComparer.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+
+namespace StardewModdingAPI.Toolkit
+{
+ /// <summary>A comparer for semantic versions based on the <see cref="SemanticVersion.CompareTo(ISemanticVersion)"/> field.</summary>
+ public class SemanticVersionComparer : IComparer<ISemanticVersion>
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>A singleton instance of the comparer.</summary>
+ public static SemanticVersionComparer Instance { get; } = new SemanticVersionComparer();
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <inheritdoc />
+ public int Compare(ISemanticVersion x, ISemanticVersion y)
+ {
+ if (object.ReferenceEquals(x, y))
+ return 0;
+
+ if (x is null)
+ return -1;
+ if (y is null)
+ return 1;
+
+ return x.CompareTo(y);
+ }
+ }
+}
diff --git a/src/SMAPI.Toolkit/Utilities/EnvironmentUtility.cs b/src/SMAPI.Toolkit/Utilities/EnvironmentUtility.cs
index 62bd13cd..6de79a85 100644
--- a/src/SMAPI.Toolkit/Utilities/EnvironmentUtility.cs
+++ b/src/SMAPI.Toolkit/Utilities/EnvironmentUtility.cs
@@ -46,5 +46,12 @@ namespace StardewModdingAPI.Toolkit.Utilities
{
return LowLevelEnvironmentUtility.GetExecutableName(platform.ToString());
}
+
+ /// <summary>Get whether an executable is 64-bit.</summary>
+ /// <param name="path">The absolute path to the assembly file.</param>
+ public static bool Is64BitAssembly(string path)
+ {
+ return LowLevelEnvironmentUtility.Is64BitAssembly(path);
+ }
}
}
diff --git a/src/SMAPI.Web/Controllers/ModsApiController.cs b/src/SMAPI.Web/Controllers/ModsApiController.cs
index 1956bf29..c6e9a713 100644
--- a/src/SMAPI.Web/Controllers/ModsApiController.cs
+++ b/src/SMAPI.Web/Controllers/ModsApiController.cs
@@ -123,6 +123,10 @@ namespace StardewModdingAPI.Web.Controllers
ModOverrideConfig overrides = this.Config.Value.ModOverrides.FirstOrDefault(p => p.ID.Equals(search.ID?.Trim(), StringComparison.OrdinalIgnoreCase));
bool allowNonStandardVersions = overrides?.AllowNonStandardVersions ?? false;
+ // SMAPI versions with a '-beta' tag indicate major changes that may need beta mod versions.
+ // This doesn't apply to normal prerelease versions which have an '-alpha' tag.
+ bool isSmapiBeta = apiVersion.IsPrerelease() && apiVersion.PrereleaseTag.StartsWith("beta");
+
// get latest versions
ModEntryModel result = new ModEntryModel { ID = search.ID };
IList<string> errors = new List<string>();
@@ -198,7 +202,7 @@ namespace StardewModdingAPI.Web.Controllers
List<ModEntryVersionModel> updates = new List<ModEntryVersionModel>();
if (this.IsRecommendedUpdate(installedVersion, main?.Version, useBetaChannel: true))
updates.Add(main);
- if (this.IsRecommendedUpdate(installedVersion, optional?.Version, useBetaChannel: installedVersion.IsPrerelease() || search.IsBroken))
+ if (this.IsRecommendedUpdate(installedVersion, optional?.Version, useBetaChannel: isSmapiBeta || installedVersion.IsPrerelease() || search.IsBroken))
updates.Add(optional);
if (this.IsRecommendedUpdate(installedVersion, unofficial?.Version, useBetaChannel: true))
updates.Add(unofficial);
diff --git a/src/SMAPI.Web/Framework/ModSiteManager.cs b/src/SMAPI.Web/Framework/ModSiteManager.cs
index 68b4c6ac..8f21d2f5 100644
--- a/src/SMAPI.Web/Framework/ModSiteManager.cs
+++ b/src/SMAPI.Web/Framework/ModSiteManager.cs
@@ -110,41 +110,70 @@ namespace StardewModdingAPI.Web.Framework
main = null;
preview = null;
- ISemanticVersion ParseVersion(string raw)
+ // parse all versions from the mod page
+ IEnumerable<(string name, string description, ISemanticVersion version)> GetAllVersions()
{
- raw = this.NormalizeVersion(raw);
- return this.GetMappedVersion(raw, mapRemoteVersions, allowNonStandardVersions);
+ if (mod != null)
+ {
+ ISemanticVersion ParseAndMapVersion(string raw)
+ {
+ raw = this.NormalizeVersion(raw);
+ return this.GetMappedVersion(raw, mapRemoteVersions, allowNonStandardVersions);
+ }
+
+ // get mod version
+ ISemanticVersion modVersion = ParseAndMapVersion(mod.Version);
+ if (modVersion != null)
+ yield return (name: null, description: null, version: ParseAndMapVersion(mod.Version));
+
+ // get file versions
+ foreach (IModDownload download in mod.Downloads)
+ {
+ ISemanticVersion cur = ParseAndMapVersion(download.Version);
+ if (cur != null)
+ yield return (download.Name, download.Description, cur);
+ }
+ }
}
+ var versions = GetAllVersions()
+ .OrderByDescending(p => p.version, SemanticVersionComparer.Instance)
+ .ToArray();
- if (mod != null)
+ // get main + preview versions
+ void TryGetVersions(out ISemanticVersion mainVersion, out ISemanticVersion previewVersion, Func<(string name, string description, ISemanticVersion version), bool> filter = null)
{
- // get mod version
- if (subkey == null)
- main = ParseVersion(mod.Version);
+ mainVersion = null;
+ previewVersion = null;
- // get file versions
- foreach (IModDownload download in mod.Downloads)
+ // get latest main + preview version
+ foreach (var entry in versions)
{
- // check for subkey if specified
- if (subkey != null && download.Name?.Contains(subkey, StringComparison.OrdinalIgnoreCase) != true && download.Description?.Contains(subkey, StringComparison.OrdinalIgnoreCase) != true)
+ if (filter?.Invoke(entry) == false)
continue;
- // parse version
- ISemanticVersion cur = ParseVersion(download.Version);
- if (cur == null)
- continue;
+ if (entry.version.IsPrerelease())
+ previewVersion ??= entry.version;
+ else
+ mainVersion ??= entry.version;
- // track highest versions
- if (main == null || cur.IsNewerThan(main))
- main = cur;
- if (cur.IsPrerelease() && (preview == null || cur.IsNewerThan(preview)))
- preview = cur;
+ if (mainVersion != null)
+ break; // any other values will be older
}
- if (preview != null && !preview.IsNewerThan(main))
- preview = null;
+ // normalize values
+ if (previewVersion is not null)
+ {
+ mainVersion ??= previewVersion; // if every version is prerelease, latest one is the main version
+ if (!previewVersion.IsNewerThan(mainVersion))
+ previewVersion = null;
+ }
}
+ if (subkey is not null)
+ TryGetVersions(out main, out preview, entry => entry.name?.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true || entry.description?.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true);
+ if (main is null)
+ TryGetVersions(out main, out preview);
+
return main != null;
}
diff --git a/src/SMAPI.Web/SMAPI.Web.csproj b/src/SMAPI.Web/SMAPI.Web.csproj
index e9d209ec..4c8465a6 100644
--- a/src/SMAPI.Web/SMAPI.Web.csproj
+++ b/src/SMAPI.Web/SMAPI.Web.csproj
@@ -2,7 +2,7 @@
<PropertyGroup>
<AssemblyName>SMAPI.Web</AssemblyName>
<RootNamespace>StardewModdingAPI.Web</RootNamespace>
- <TargetFramework>netcoreapp3.1</TargetFramework>
+ <TargetFramework>net5.0</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>
diff --git a/src/SMAPI.Web/Views/Mods/Index.cshtml b/src/SMAPI.Web/Views/Mods/Index.cshtml
index fa77c220..7dcd0718 100644
--- a/src/SMAPI.Web/Views/Mods/Index.cshtml
+++ b/src/SMAPI.Web/Views/Mods/Index.cshtml
@@ -9,7 +9,7 @@
TimeSpan staleAge = DateTimeOffset.UtcNow - Model.LastUpdated;
bool hasBeta = Model.BetaVersion != null;
- string betaLabel = "SDV @Model.BetaVersion only";
+ string betaLabel = $"SDV {Model.BetaVersion} only";
}
@section Head {
<link rel="stylesheet" href="~/Content/css/mods.css?r=20200218" />
diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs
index 6cbdeb8e..cce267ba 100644
--- a/src/SMAPI/Constants.cs
+++ b/src/SMAPI/Constants.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
+using Mono.Cecil;
using StardewModdingAPI.Enums;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.ModLoading;
@@ -61,7 +62,7 @@ namespace StardewModdingAPI
internal static int? LogScreenId { get; set; }
/// <summary>SMAPI's current raw semantic version.</summary>
- internal static string RawApiVersion = "3.12.2";
+ internal static string RawApiVersion = "3.12.3";
}
/// <summary>Contains SMAPI's constants and assumptions.</summary>
@@ -229,6 +230,32 @@ namespace StardewModdingAPI
}
}
+ /// <summary>Configure the Mono.Cecil assembly resolver.</summary>
+ /// <param name="resolver">The assembly resolver.</param>
+ internal static void ConfigureAssemblyResolver(AssemblyDefinitionResolver resolver)
+ {
+ // add search paths
+ resolver.AddSearchDirectory(Constants.ExecutionPath);
+ resolver.AddSearchDirectory(Constants.InternalFilesPath);
+
+ // add SMAPI explicitly
+ // Normally this would be handled automatically by the search paths, but for some reason there's a specific
+ // case involving unofficial 64-bit Stardew Valley when launched through Steam (for some players only)
+ // where Mono.Cecil can't resolve references to SMAPI.
+ resolver.Add(AssemblyDefinition.ReadAssembly(typeof(SGame).Assembly.Location));
+
+ // make sure game assembly names can be resolved
+ // The game assembly can have one of three names depending how the mod was compiled:
+ // - 'StardewValley': assembly name on Linux/macOS;
+ // - 'Stardew Valley': assembly name on Windows;
+ // - 'Netcode': an assembly that's separate on Windows only.
+ resolver.Add(AssemblyDefinition.ReadAssembly(typeof(Game1).Assembly.Location), "StardewValley", "Stardew Valley"
+#if !SMAPI_FOR_WINDOWS
+ , "Netcode"
+#endif
+ );
+ }
+
/// <summary>Get metadata for mapping assemblies to the current platform.</summary>
/// <param name="targetPlatform">The target game platform.</param>
/// <param name="framework">The game framework running the game.</param>
diff --git a/src/SMAPI/Framework/Logging/LogManager.cs b/src/SMAPI/Framework/Logging/LogManager.cs
index a3d4f23d..c6faa90d 100644
--- a/src/SMAPI/Framework/Logging/LogManager.cs
+++ b/src/SMAPI/Framework/Logging/LogManager.cs
@@ -109,9 +109,12 @@ namespace StardewModdingAPI.Framework.Logging
output.OnMessageIntercepted += message => this.HandleConsoleMessage(this.MonitorForGame, message);
Console.SetOut(output);
- // enable Unicode handling
+ // enable Unicode handling on Windows
+ // (the terminal defaults to UTF-8 on Linux/macOS)
+#if SMAPI_FOR_WINDOWS
Console.InputEncoding = Encoding.Unicode;
Console.OutputEncoding = Encoding.Unicode;
+#endif
}
/// <summary>Get a monitor instance derived from SMAPI's current settings.</summary>
@@ -162,8 +165,6 @@ namespace StardewModdingAPI.Framework.Logging
// keep console thread alive while the game is running
while (continueWhile())
Thread.Sleep(1000 / 10);
- if (inputThread.ThreadState == ThreadState.Running)
- inputThread.Abort();
}
/// <summary>Show a 'press any key to exit' message, and exit when they press a key.</summary>
diff --git a/src/SMAPI/Framework/ModHelpers/DataHelper.cs b/src/SMAPI/Framework/ModHelpers/DataHelper.cs
index 0fe3209f..4cbfd73f 100644
--- a/src/SMAPI/Framework/ModHelpers/DataHelper.cs
+++ b/src/SMAPI/Framework/ModHelpers/DataHelper.cs
@@ -58,7 +58,11 @@ namespace StardewModdingAPI.Framework.ModHelpers
throw new InvalidOperationException($"You must call {nameof(IMod.Helper)}.{nameof(IModHelper.Data)}.{nameof(this.WriteJsonFile)} with a relative path (without directory climbing).");
path = Path.Combine(this.ModFolderPath, PathUtilities.NormalizePath(path));
- this.JsonHelper.WriteJsonFile(path, data);
+
+ if (data != null)
+ this.JsonHelper.WriteJsonFile(path, data);
+ else
+ File.Delete(path);
}
/****
diff --git a/src/SMAPI/Framework/ModHelpers/TranslationHelper.cs b/src/SMAPI/Framework/ModHelpers/TranslationHelper.cs
index a88ca9c9..869664fe 100644
--- a/src/SMAPI/Framework/ModHelpers/TranslationHelper.cs
+++ b/src/SMAPI/Framework/ModHelpers/TranslationHelper.cs
@@ -55,6 +55,12 @@ namespace StardewModdingAPI.Framework.ModHelpers
return this.Translator.Get(key, tokens);
}
+ /// <inheritdoc />
+ public IDictionary<string, Translation> GetInAllLocales(string key, bool withFallback = false)
+ {
+ return this.Translator.GetInAllLocales(key, withFallback);
+ }
+
/// <summary>Set the translations to use.</summary>
/// <param name="translations">The translations to use.</param>
internal TranslationHelper SetTranslations(IDictionary<string, IDictionary<string, string>> translations)
diff --git a/src/SMAPI/Framework/Mod