Skip to content

Commit 4daed27

Browse files
committed
Merge branch 'develop' into stable
2 parents 6a1eb71 + 2769248 commit 4daed27

File tree

16 files changed

+35
-254
lines changed

16 files changed

+35
-254
lines changed

build/common.targets

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ repo. It imports the other MSBuild files as needed.
77
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
88
<PropertyGroup>
99
<!--set general build properties -->
10-
<Version>4.1.3</Version>
10+
<Version>4.1.4</Version>
1111
<Product>SMAPI</Product>
1212
<LangVersion>latest</LangVersion>
1313
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>

docs/release-notes.md

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
11
[README](README.md)
22

33
# Release notes
4+
## 4.1.4
5+
Released 05 November 2024 for Stardew Valley 1.6.10 or later.
6+
7+
* For players:
8+
* Fixed a wide variety of mod errors and crashes after SMAPI 4.1.0 in some specific cases (e.g. Content Patcher "unable to find constructor" errors).
9+
10+
* For mod authors:
11+
* Removed the new private assembly references feature. This may be revisited in a future update once the dust settles on 1.6.9.
12+
* Fixed error propagating edits to `Data/ChairTiles`.
13+
414
## 4.1.3
515
Released 04 November 2024 for Stardew Valley 1.6.10 or later.
616

7-
* Improved compatibility rewriters for Stardew Valley 1.6.9+.
17+
* For players:
18+
* Improved compatibility rewriters for Stardew Valley 1.6.9+.
819

920
## 4.1.2
1021
Released 04 November 2024 for Stardew Valley 1.6.10 or later.
1122

12-
* Updated for Stardew Valley 1.6.10.
13-
* Fixed various issues with custom maps loaded from `.tmx` files in Stardew Valley 1.6.9.
23+
* For players:
24+
* Updated for Stardew Valley 1.6.10.
25+
* Fixed various issues with custom maps loaded from `.tmx` files in Stardew Valley 1.6.9.
1426

1527
## 4.1.1
1628
Released 04 November 2024 for Stardew Valley 1.6.9 or later.
1729

18-
* Fixed crash when loading saves containing a custom spouse room loaded from a `.tmx` file.
30+
* For players:
31+
* Fixed crash when loading saves containing a custom spouse room loaded from a `.tmx` file.
1932

2033
## 4.1.0
2134
Released 04 November 2024 for Stardew Valley 1.6.9 or later. See [release highlights](https://www.patreon.com/posts/115304143).
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"Name": "Console Commands",
33
"Author": "SMAPI",
4-
"Version": "4.1.3",
4+
"Version": "4.1.4",
55
"Description": "Adds SMAPI console commands that let you manipulate the game.",
66
"UniqueID": "SMAPI.ConsoleCommands",
77
"EntryDll": "ConsoleCommands.dll",
8-
"MinimumApiVersion": "4.1.3"
8+
"MinimumApiVersion": "4.1.4"
99
}
+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"Name": "Save Backup",
33
"Author": "SMAPI",
4-
"Version": "4.1.3",
4+
"Version": "4.1.4",
55
"Description": "Automatically backs up all your saves once per day into its folder.",
66
"UniqueID": "SMAPI.SaveBackup",
77
"EntryDll": "SaveBackup.dll",
8-
"MinimumApiVersion": "4.1.3"
8+
"MinimumApiVersion": "4.1.4"
99
}

src/SMAPI.Tests/Core/ModResolverTests.cs

-1
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,6 @@ private Manifest GetManifest(string? id = null, string? name = null, string? ver
526526
minimumApiVersion: minimumApiVersion != null ? new SemanticVersion(minimumApiVersion) : null,
527527
minimumGameVersion: minimumGameVersion != null ? new SemanticVersion(minimumGameVersion) : null,
528528
dependencies: dependencies ?? Array.Empty<IManifestDependency>(),
529-
privateAssemblies: Array.Empty<IManifestPrivateAssembly>(),
530529
updateKeys: Array.Empty<string>()
531530
);
532531
}

src/SMAPI.Toolkit.CoreInterfaces/IManifest.cs

-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ public interface IManifest
3838
/// <summary>The other mods that must be loaded before this mod.</summary>
3939
IManifestDependency[] Dependencies { get; }
4040

41-
/// <summary>The assemblies in the mod folder which should only be referenced by this mod. These will be ignored when another mod tries to use assemblies with the same names.</summary>
42-
IManifestPrivateAssembly[] PrivateAssemblies { get; }
43-
4441
/// <summary>The namespaced mod IDs to query for updates (like <c>Nexus:541</c>).</summary>
4542
string[] UpdateKeys { get; }
4643

src/SMAPI.Toolkit.CoreInterfaces/IManifestPrivateAssembly.cs

-11
This file was deleted.

src/SMAPI.Toolkit/Framework/ManifestValidator.cs

-39
Original file line numberDiff line numberDiff line change
@@ -99,45 +99,6 @@ public static bool TryValidateFields(IManifest manifest, out string error)
9999
}
100100
}
101101

102-
// validate private assemblies format
103-
if (!hasDll)
104-
{
105-
if (manifest.PrivateAssemblies.Length > 0)
106-
{
107-
error = $"manifest includes {nameof(IManifest.PrivateAssemblies)}, which isn't valid for a content pack.";
108-
return false;
109-
}
110-
}
111-
else
112-
{
113-
foreach (IManifestPrivateAssembly? assembly in manifest.PrivateAssemblies)
114-
{
115-
if (assembly is null)
116-
{
117-
error = $"manifest has a null entry under {nameof(IManifest.PrivateAssemblies)}.";
118-
return false;
119-
}
120-
121-
if (string.IsNullOrWhiteSpace(assembly.Name))
122-
{
123-
error = $"manifest has a {nameof(IManifest.PrivateAssemblies)} entry with no {nameof(IManifestPrivateAssembly.Name)} field.";
124-
return false;
125-
}
126-
127-
if (assembly.Name.Contains('/') || assembly.Name.Contains('\\') || assembly.Name.Contains(".dll"))
128-
{
129-
error = $"manifest has a {nameof(IManifest.PrivateAssemblies)} entry with an invalid {nameof(IManifestPrivateAssembly.Name)} field (must be the assembly name without the file path, extension, or metadata).";
130-
return false;
131-
}
132-
133-
if (assembly.Name is "0Harmony" or "MonoGame.Framework" or "StardewModdingAPI" or "Stardew Valley" or "StardewValley.GameData")
134-
{
135-
error = $"manifest has a {nameof(IManifest.PrivateAssemblies)} entry with an invalid {nameof(IManifestPrivateAssembly.Name)} field (the '{assembly.Name}' assembly can't be private).";
136-
return false;
137-
}
138-
}
139-
}
140-
141102
error = "";
142103
return true;
143104
}

src/SMAPI.Toolkit/Serialization/Converters/ManifestPrivateAssemblyArrayConverter.cs

-52
This file was deleted.

src/SMAPI.Toolkit/Serialization/Models/Manifest.cs

+1-8
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@ public class Manifest : IManifest
4242
[JsonConverter(typeof(ManifestDependencyArrayConverter))]
4343
public IManifestDependency[] Dependencies { get; }
4444

45-
/// <inheritdoc />
46-
[JsonConverter(typeof(ManifestPrivateAssemblyArrayConverter))]
47-
public IManifestPrivateAssembly[] PrivateAssemblies { get; }
48-
4945
/// <inheritdoc />
5046
public string[] UpdateKeys { get; private set; }
5147

@@ -80,7 +76,6 @@ public Manifest(string uniqueID, string name, string author, string description,
8076
contentPackFor: contentPackFor != null
8177
? new ManifestContentPackFor(contentPackFor, null)
8278
: null,
83-
privateAssemblies: null,
8479
dependencies: null,
8580
updateKeys: null
8681
)
@@ -97,10 +92,9 @@ public Manifest(string uniqueID, string name, string author, string description,
9792
/// <param name="entryDll">The name of the DLL in the directory that has the <c>Entry</c> method. Mutually exclusive with <see cref="ContentPackFor"/>.</param>
9893
/// <param name="contentPackFor">The modID which will read this as a content pack.</param>
9994
/// <param name="dependencies">The other mods that must be loaded before this mod.</param>
100-
/// <param name="privateAssemblies">The names of assemblies that should be private to this mod. These assemblies will not be directly accessible by other mods and will be ignored when a mod tries to use an assembly with the same name in a public manner.</param>
10195
/// <param name="updateKeys">The namespaced mod IDs to query for updates (like <c>Nexus:541</c>).</param>
10296
[JsonConstructor]
103-
public Manifest(string uniqueId, string name, string author, string description, ISemanticVersion version, ISemanticVersion? minimumApiVersion, ISemanticVersion? minimumGameVersion, string? entryDll, IManifestContentPackFor? contentPackFor, IManifestDependency[]? dependencies, IManifestPrivateAssembly[]? privateAssemblies, string[]? updateKeys)
97+
public Manifest(string uniqueId, string name, string author, string description, ISemanticVersion version, ISemanticVersion? minimumApiVersion, ISemanticVersion? minimumGameVersion, string? entryDll, IManifestContentPackFor? contentPackFor, IManifestDependency[]? dependencies, string[]? updateKeys)
10498
{
10599
this.UniqueID = this.NormalizeField(uniqueId);
106100
this.Name = this.NormalizeField(name, replaceSquareBrackets: true);
@@ -112,7 +106,6 @@ public Manifest(string uniqueId, string name, string author, string description,
112106
this.EntryDll = this.NormalizeField(entryDll);
113107
this.ContentPackFor = contentPackFor;
114108
this.Dependencies = dependencies ?? Array.Empty<IManifestDependency>();
115-
this.PrivateAssemblies = privateAssemblies ?? Array.Empty<IManifestPrivateAssembly>();
116109
this.UpdateKeys = updateKeys ?? Array.Empty<string>();
117110
}
118111

src/SMAPI.Toolkit/Serialization/Models/ManifestPrivateAssembly.cs

-27
This file was deleted.

src/SMAPI/Constants.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ internal static class EarlyConstants
4949
internal static int? LogScreenId { get; set; }
5050

5151
/// <summary>SMAPI's current raw semantic version.</summary>
52-
internal static string RawApiVersion = "4.1.3";
52+
internal static string RawApiVersion = "4.1.4";
5353
}
5454

5555
/// <summary>Contains SMAPI's constants and assumptions.</summary>

src/SMAPI/Framework/ModLoading/AssemblyLoader.cs

+7-26
Original file line numberDiff line numberDiff line change
@@ -106,37 +106,22 @@ public AssemblyLoader(Platform targetPlatform, IMonitor monitor, bool paranoidMo
106106
/// <param name="mod">The mod for which the assembly is being loaded.</param>
107107
/// <param name="assemblyFile">The assembly file.</param>
108108
/// <param name="assumeCompatible">Assume the mod is compatible, even if incompatible code is detected.</param>
109-
/// <param name="assemblyLoadContext">The assembly load context with which to load assemblies for the current mod.</param>
110109
/// <returns>Returns the rewrite metadata for the preprocessed assembly.</returns>
111110
/// <exception cref="IncompatibleInstructionException">An incompatible CIL instruction was found while rewriting the assembly.</exception>
112-
public Assembly Load(IModMetadata mod, FileInfo assemblyFile, bool assumeCompatible, ModAssemblyLoadContext assemblyLoadContext)
111+
public Assembly Load(IModMetadata mod, FileInfo assemblyFile, bool assumeCompatible)
113112
{
114113
// get referenced local assemblies
115114
AssemblyParseResult[] assemblies;
116115
{
117116
HashSet<string> visitedAssemblyNames = new( // don't try loading assemblies that are already loaded
118117
from assembly in AppDomain.CurrentDomain.GetAssemblies()
119118
let name = assembly.GetName().Name
120-
where
121-
name != null
122-
&& (
123-
!assemblyLoadContext.IsPrivateAssembly(name)
124-
&& assemblyLoadContext.IsLoadedPublicAssembly(name)
125-
)
119+
where name != null
126120
select name
127121
);
128122
assemblies = this.GetReferencedLocalAssemblies(assemblyFile, visitedAssemblyNames, this.AssemblyDefinitionResolver).ToArray();
129123
}
130124

131-
// validate private assemblies
132-
foreach (IManifestPrivateAssembly entry in mod.Manifest.PrivateAssemblies)
133-
{
134-
string assemblyName = entry.Name;
135-
136-
if (!entry.UsedDynamically && assemblies.All(a => a.Definition?.Name.Name != assemblyName))
137-
this.Monitor.Log($" Mod '{mod.DisplayName}' refers to private assembly '{assemblyName}' in its manifest, but doesn't use it. This is a bug that should be reported to that mod's author.", LogLevel.Warn);
138-
}
139-
140125
// validate load
141126
if (!assemblies.Any() || assemblies[0].Status == AssemblyLoadStatus.Failed)
142127
{
@@ -174,27 +159,23 @@ select name
174159
}
175160

176161
// load assembly
177-
bool loadAsPrivate = assemblyLoadContext.IsPrivateAssembly(assembly.Definition.Name.Name);
178162
if (changed)
179163
{
180164
if (!oneAssembly)
181-
this.Monitor.Log($" Loading{(loadAsPrivate ? " private" : "")} assembly '{assembly.File.Name}' (rewritten)...");
165+
this.Monitor.Log($" Loading assembly '{assembly.File.Name}' (rewritten)...");
182166

183167
// load assembly
184168
using MemoryStream outAssemblyStream = new();
185169
using MemoryStream outSymbolStream = new();
186170
assembly.Definition.Write(outAssemblyStream, new WriterParameters { WriteSymbols = true, SymbolStream = outSymbolStream, SymbolWriterProvider = this.SymbolWriterProvider });
187-
outAssemblyStream.Position = 0;
188-
outSymbolStream.Position = 0;
189-
lastAssembly = assemblyLoadContext.LoadFromStream(outAssemblyStream, outSymbolStream);
190-
assemblyLoadContext.OnLoadedAssembly(lastAssembly);
171+
byte[] bytes = outAssemblyStream.ToArray();
172+
lastAssembly = Assembly.Load(bytes, outSymbolStream.ToArray());
191173
}
192174
else
193175
{
194176
if (!oneAssembly)
195-
this.Monitor.Log($" Loading{(loadAsPrivate ? " private" : "")} assembly '{assembly.File.Name}'...");
196-
lastAssembly = assemblyLoadContext.LoadFromAssemblyPath(assembly.File.FullName);
197-
assemblyLoadContext.OnLoadedAssembly(lastAssembly);
177+
this.Monitor.Log($" Loading assembly '{assembly.File.Name}'...");
178+
lastAssembly = Assembly.UnsafeLoadFrom(assembly.File.FullName);
198179
}
199180

200181
// track loaded assembly for definition resolution

0 commit comments

Comments
 (0)