diff --git a/docs/release-notes.md b/docs/release-notes.md
index e555440a..684fb49d 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -1,6 +1,9 @@
← [README](README.md)
# Release notes
+## Upcoming release
+* Fixed Linux/macOS launch error in 3.13.3.
+
## 3.13.3
Released 16 January 2022 for Stardew Valley 1.5.6 or later.
diff --git a/src/SMAPI/Program.cs b/src/SMAPI/Program.cs
index 67ff8322..0c90f2aa 100644
--- a/src/SMAPI/Program.cs
+++ b/src/SMAPI/Program.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -16,7 +17,10 @@ namespace StardewModdingAPI
** Fields
*********/
/// The absolute path to search for SMAPI's internal DLLs.
- internal static readonly string DllSearchPath = EarlyConstants.InternalFilesPath;
+ private static readonly string DllSearchPath = EarlyConstants.InternalFilesPath;
+
+ /// The assembly paths in the search folders indexed by assembly name.
+ private static Dictionary AssemblyPathsByName;
/*********
@@ -57,16 +61,36 @@ namespace StardewModdingAPI
/// The event arguments.
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs e)
{
+ // cache assembly paths by name
+ if (Program.AssemblyPathsByName == null)
+ {
+ Program.AssemblyPathsByName = new(StringComparer.OrdinalIgnoreCase);
+
+ foreach (string searchPath in new[] { EarlyConstants.ExecutionPath, Program.DllSearchPath })
+ {
+ foreach (string dllPath in Directory.EnumerateFiles(searchPath, "*.dll"))
+ {
+ try
+ {
+ string curName = AssemblyName.GetAssemblyName(dllPath).Name;
+ if (curName != null)
+ Program.AssemblyPathsByName[curName] = dllPath;
+ }
+ catch
+ {
+ continue;
+ }
+ }
+ }
+ }
+
+ // resolve
try
{
- AssemblyName name = new AssemblyName(e.Name);
- foreach (FileInfo dll in new DirectoryInfo(Program.DllSearchPath).EnumerateFiles("*.dll"))
- {
- if (name.Name.Equals(AssemblyName.GetAssemblyName(dll.FullName).Name, StringComparison.OrdinalIgnoreCase))
- return Assembly.LoadFrom(dll.FullName);
- }
-
- return null;
+ string searchName = new AssemblyName(e.Name).Name;
+ return searchName != null && Program.AssemblyPathsByName.TryGetValue(searchName, out string assemblyPath)
+ ? Assembly.LoadFrom(assemblyPath)
+ : null;
}
catch (Exception ex)
{