Skip to content

Commit 4c7eac9

Browse files
committed
Merge branch 'develop' into stable
2 parents 5919337 + 679dfb3 commit 4c7eac9

File tree

278 files changed

+8600
-6219
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

278 files changed

+8600
-6219
lines changed

build/common.targets

+1-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ 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>3.18.6</Version>
10+
<Version>4.0.0</Version>
1111
<Product>SMAPI</Product>
1212
<LangVersion>latest</LangVersion>
1313
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
14-
<DefineConstants>$(DefineConstants);SMAPI_DEPRECATED</DefineConstants>
1514
<DebugSymbols>true</DebugSymbols>
1615

1716
<!--embed symbols for error stack trace line numbers on Linux/macOS: https://github.com/dotnet/runtime/issues/39987-->
@@ -34,13 +33,10 @@ repo. It imports the other MSBuild files as needed.
3433
warning | builds | summary | rationale
3534
┄┄┄┄┄┄┄ | ┄┄┄┄┄┄┄┄┄┄ | ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ | ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
3635
CS0436 | all | local type conflicts with imported type | SMAPI needs to use certain low-level code during very early compatibility checks, before it's safe to load any other DLLs.
37-
CS0612 | deprecated | member is obsolete | internal references to deprecated code when deprecated code is enabled.
38-
CS0618 | deprecated | member is obsolete (with message) | internal references to deprecated code when deprecated code is enabled.
3936
CA1416 | all | platform code available on all platforms | Compiler doesn't recognize the #if constants used by SMAPI.
4037
CS0809 | all | obsolete overload for non-obsolete member | This is deliberate to signal to mods that certain APIs are only implemented for the game and shouldn't be called by mods.
4138
NU1701 | all | NuGet package targets older .NET version | All such packages are carefully tested to make sure they do work.
4239
-->
43-
<NoWarn Condition="$(DefineConstants.Contains(SMAPI_DEPRECATED))">$(NoWarn);CS0612;CS0618</NoWarn>
4440
<NoWarn>$(NoWarn);CS0436;CA1416;CS0809;NU1701</NoWarn>
4541
</PropertyGroup>
4642

build/deploy-local-smapi.targets

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ This assumes `find-game-folder.targets` has already been imported and validated.
5555
</Target>
5656

5757
<!-- bundled mods -->
58-
<Target Name="CopyDefaultMods" Condition="'$(MSBuildProjectName)' == 'SMAPI.Mods.ConsoleCommands' OR '$(MSBuildProjectName)' == 'SMAPI.Mods.ErrorHandler' OR '$(MSBuildProjectName)' == 'SMAPI.Mods.SaveBackup'">
58+
<Target Name="CopyDefaultMods" Condition="'$(MSBuildProjectName)' == 'SMAPI.Mods.ConsoleCommands' OR '$(MSBuildProjectName)' == 'SMAPI.Mods.SaveBackup'">
5959
<ItemGroup>
6060
<TranslationFiles Include="$(TargetDir)\i18n\*.json" />
6161
</ItemGroup>

build/unix/prepare-install-package.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
##########
1414
# paths
1515
gamePath="/home/pathoschild/Stardew Valley"
16-
bundleModNames=("ConsoleCommands" "ErrorHandler" "SaveBackup")
16+
bundleModNames=("ConsoleCommands" "SaveBackup")
1717

1818
# build configuration
1919
buildConfig="Release"
@@ -69,7 +69,7 @@ for folder in ${folders[@]}; do
6969
for modName in ${bundleModNames[@]}; do
7070
echo "Compiling $modName for $folder..."
7171
echo "-------------------------------------------------"
72-
dotnet publish src/SMAPI.Mods.$modName --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false"
72+
dotnet publish src/SMAPI.Mods.$modName --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" --self-contained false
7373
echo ""
7474
echo ""
7575
done

build/unix/set-smapi-version.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ cd "`dirname "$0"`/../.."
2121
# apply changes
2222
sed "s/<Version>.+<\/Version>/<Version>$version<\/Version>/" "build/common.targets" --in-place --regexp-extended
2323
sed "s/RawApiVersion = \".+?\";/RawApiVersion = \"$version\";/" "src/SMAPI/Constants.cs" --in-place --regexp-extended
24-
for modName in "ConsoleCommands" "ErrorHandler" "SaveBackup"; do
24+
for modName in "ConsoleCommands" "SaveBackup"; do
2525
sed "s/\"(Version|MinimumApiVersion)\": \".+?\"/\"\1\": \"$version\"/g" "src/SMAPI.Mods.$modName/manifest.json" --in-place --regexp-extended
2626
done

build/windows/prepare-install-package.ps1

+5-4
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@
1717
##########
1818
# paths
1919
$gamePath = "C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley"
20-
$bundleModNames = "ConsoleCommands", "ErrorHandler", "SaveBackup"
20+
$bundleModNames = "ConsoleCommands", "SaveBackup"
2121

2222
# build configuration
2323
$buildConfig = "Release"
24+
$framework = "net6.0"
2425
$folders = "linux", "macOS", "windows"
2526
$runtimes = @{ linux = "linux-x64"; macOS = "osx-x64"; windows = "win-x64" }
2627
$msBuildPlatformNames = @{ linux = "Unix"; macOS = "OSX"; windows = "Windows_NT" }
@@ -72,20 +73,20 @@ foreach ($folder in $folders) {
7273

7374
echo "Compiling SMAPI for $folder..."
7475
echo "-------------------------------------------------"
75-
dotnet publish src/SMAPI --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" --self-contained true
76+
dotnet publish src/SMAPI --configuration $buildConfig -v minimal --runtime "$runtime" --framework "$framework" -p:OS="$msbuildPlatformName" -p:TargetFrameworks="$framework" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" --self-contained true
7677
echo ""
7778
echo ""
7879

7980
echo "Compiling installer for $folder..."
8081
echo "-------------------------------------------------"
81-
dotnet publish src/SMAPI.Installer --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" -p:PublishTrimmed=True -p:TrimMode=Link --self-contained true
82+
dotnet publish src/SMAPI.Installer --configuration $buildConfig -v minimal --runtime "$runtime" --framework "$framework" -p:OS="$msbuildPlatformName" -p:TargetFrameworks="$framework" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" -p:PublishTrimmed=True -p:TrimMode=Link --self-contained true
8283
echo ""
8384
echo ""
8485

8586
foreach ($modName in $bundleModNames) {
8687
echo "Compiling $modName for $folder..."
8788
echo "-------------------------------------------------"
88-
dotnet publish src/SMAPI.Mods.$modName --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false"
89+
dotnet publish src/SMAPI.Mods.$modName --configuration $buildConfig -v minimal --runtime "$runtime" --framework "$framework" -p:OS="$msbuildPlatformName" -p:TargetFrameworks="$framework" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" --self-contained false
8990
echo ""
9091
echo ""
9192
}

build/windows/set-smapi-version.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ cd "$PSScriptRoot/../.."
2020
# apply changes
2121
In-Place-Regex -Path "build/common.targets" -Search "<Version>.+</Version>" -Replace "<Version>$version</Version>"
2222
In-Place-Regex -Path "src/SMAPI/Constants.cs" -Search "RawApiVersion = `".+?`";" -Replace "RawApiVersion = `"$version`";"
23-
ForEach ($modName in "ConsoleCommands","ErrorHandler","SaveBackup") {
23+
ForEach ($modName in "ConsoleCommands","SaveBackup") {
2424
In-Place-Regex -Path "src/SMAPI.Mods.$modName/manifest.json" -Search "`"(Version|MinimumApiVersion)`": `".+?`"" -Replace "`"`$1`": `"$version`""
2525
}

docs/release-notes.md

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

33
# Release notes
4-
<!--
54
## 4.0.0
6-
* The installer no longer supports updating from SMAPI 2.11.3 or earlier (released in 2019).
7-
_If needed, you can update to SMAPI 3.16.0 first and then install the latest version._
8-
-->
5+
Released 19 March 2024 for Stardew Valley 1.6.0 or later. See [release highlights](https://www.patreon.com/posts/100388693).
6+
7+
* For players:
8+
* Updated for Stardew Valley 1.6.
9+
* Added support for overriding SMAPI configuration per `Mods` folder (thanks to Shockah!).
10+
* Improved performance.
11+
* Improved compatibility rewriting to handle more cases (thanks to SinZ for his contributions!).
12+
* Removed the bundled `ErrorHandler` mod, which is now integrated into Stardew Valley 1.6.
13+
* Removed obsolete console commands: `list_item_types` (no longer needed) and `player_setimmunity` (broke in 1.6 and rarely used).
14+
* Removed support for seamlessly updating from SMAPI 2.11.3 and earlier (released in 2019).
15+
_If needed, you can update to SMAPI 3.18.0 first and then install the latest version._
16+
17+
* For mod authors:
18+
* Updated to .NET 6.
19+
* Added [`RenderingStep` and `RenderedStep` events](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Events#Display.RenderingStep), which let you handle a specific step in the game's render cycle.
20+
* Added support for [custom update manifests](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Update_checks#Custom_update_manifest) (thanks to Jamie Taylor!).
21+
* Removed all deprecated APIs.
22+
* SMAPI no longer intercepts output written to the console. Mods which directly access `Console` will be listed under mod warnings.
23+
* Calling `Monitor.VerboseLog` with an interpolated string no longer evaluates the string if verbose mode is disabled (thanks to atravita!). This only applies to mods compiled in SMAPI 4.0.0 or later.
24+
* Fixed redundant `TRACE` logs for a broken mod which references members with the wrong types.
25+
26+
* For the web UI:
27+
* Updated JSON validator for Content Patcher 2.0.0.
28+
* Fixed uploaded log/JSON file expiry alway shown as renewed.
29+
* Fixed update check for mods with a prerelease version tag not recognized by the ModDrop API. SMAPI now parses the version itself if needed.
30+
31+
* For SMAPI developers:
32+
* Added `LogTechnicalDetailsForBrokenMods` option in `smapi-internal/config.json`, which adds more technical info to the SMAPI log when a mod is broken. This is mainly useful for creating compatibility rewriters.
933

1034
## 3.18.6
1135
Released 05 October 2023 for Stardew Valley 1.5.6 or later.

docs/technical/smapi.md

-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ SMAPI uses a small number of conditional compilation constants, which you can se
6464
flag | purpose
6565
---- | -------
6666
`SMAPI_FOR_WINDOWS` | Whether SMAPI is being compiled for Windows; if not set, the code assumes Linux/macOS. Set automatically in `common.targets`.
67-
`SMAPI_DEPRECATED` | Whether to include deprecated code in the build.
6867

6968
## Compile from source code
7069
### Main project

docs/technical/web.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,6 @@ field | summary
275275
`brokeIn` | The SMAPI or Stardew Valley version that broke this mod, if any.
276276
`betaCompatibilityStatus`<br />`betaCompatibilitySummary`<br />`betaBrokeIn` | Equivalent to the preceding fields, but for beta versions of SMAPI or Stardew Valley.
277277

278-
279278
</td>
280279
</tr>
281280
</table>
@@ -324,6 +323,15 @@ Example response with `includeExtendedMetadata: true`:
324323
]
325324
```
326325

326+
### `/mods/metrics`
327+
The `/mods/metrics` endpoint returns a summary of update-check metrics since the server was last
328+
deployed or restarted.
329+
330+
Example request:
331+
```js
332+
GET https://smapi.io/api/v3.0/mods/metrics
333+
```
334+
327335
## Short URLs
328336
The SMAPI web services provides a few short URLs for convenience:
329337

src/SMAPI.Installer/InteractiveInstaller.cs

+4-126
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ internal class InteractiveInstaller
2929
/// <summary>The mod IDs which the installer should allow as bundled mods.</summary>
3030
private readonly string[] BundledModIDs = {
3131
"SMAPI.SaveBackup",
32-
"SMAPI.ConsoleCommands",
33-
"SMAPI.ErrorHandler"
32+
"SMAPI.ConsoleCommands"
3433
};
3534

3635
/// <summary>Get the absolute file or folder paths to remove when uninstalling SMAPI.</summary>
@@ -41,7 +40,7 @@ private IEnumerable<string> GetUninstallPaths(DirectoryInfo installDir, Director
4140
{
4241
string GetInstallPath(string path) => Path.Combine(installDir.FullName, path);
4342

44-
// current files
43+
// installed files
4544
yield return GetInstallPath("StardewModdingAPI"); // Linux/macOS only
4645
yield return GetInstallPath("StardewModdingAPI.deps.json");
4746
yield return GetInstallPath("StardewModdingAPI.dll");
@@ -54,38 +53,8 @@ private IEnumerable<string> GetUninstallPaths(DirectoryInfo installDir, Director
5453
yield return GetInstallPath("smapi-internal");
5554
yield return GetInstallPath("steam_appid.txt");
5655

57-
#if SMAPI_DEPRECATED
58-
// obsolete
59-
yield return GetInstallPath("libgdiplus.dylib"); // before 3.13 (macOS only)
60-
yield return GetInstallPath(Path.Combine("Mods", ".cache")); // 1.3-1.4
61-
yield return GetInstallPath(Path.Combine("Mods", "TrainerMod")); // *–2.0 (renamed to ConsoleCommands)
62-
yield return GetInstallPath("Mono.Cecil.Rocks.dll"); // 1.3–1.8
63-
yield return GetInstallPath("StardewModdingAPI-settings.json"); // 1.0-1.4
64-
yield return GetInstallPath("StardewModdingAPI.AssemblyRewriters.dll"); // 1.3-2.5.5
65-
yield return GetInstallPath("0Harmony.dll"); // moved in 2.8
66-
yield return GetInstallPath("0Harmony.pdb"); // moved in 2.8
67-
yield return GetInstallPath("Mono.Cecil.dll"); // moved in 2.8
68-
yield return GetInstallPath("Newtonsoft.Json.dll"); // moved in 2.8
69-
yield return GetInstallPath("StardewModdingAPI.config.json"); // moved in 2.8
70-
yield return GetInstallPath("StardewModdingAPI.crash.marker"); // moved in 2.8
71-
yield return GetInstallPath("StardewModdingAPI.metadata.json"); // moved in 2.8
72-
yield return GetInstallPath("StardewModdingAPI.update.marker"); // moved in 2.8
73-
yield return GetInstallPath("StardewModdingAPI.Toolkit.dll"); // moved in 2.8
74-
yield return GetInstallPath("StardewModdingAPI.Toolkit.pdb"); // moved in 2.8
75-
yield return GetInstallPath("StardewModdingAPI.Toolkit.xml"); // moved in 2.8
76-
yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.dll"); // moved in 2.8
77-
yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.pdb"); // moved in 2.8
78-
yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.xml"); // moved in 2.8
79-
yield return GetInstallPath("StardewModdingAPI-x64.exe"); // before 3.13
80-
81-
if (modsDir.Exists)
82-
{
83-
foreach (DirectoryInfo modDir in modsDir.EnumerateDirectories())
84-
yield return Path.Combine(modDir.FullName, ".cache"); // 1.4–1.7
85-
}
86-
#endif
87-
88-
yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "ErrorLogs"); // remove old log files
56+
// old log files
57+
yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "ErrorLogs");
8958
}
9059

9160
/// <summary>Handles writing text to the console.</summary>
@@ -516,11 +485,6 @@ public void Run(string[] args)
516485
.Replace(@"""UseScheme"": ""AutoDetect""", $@"""UseScheme"": ""{scheme}""");
517486
File.WriteAllText(paths.ApiConfigPath, text);
518487
}
519-
520-
#if SMAPI_DEPRECATED
521-
// remove obsolete appdata mods
522-
this.InteractivelyRemoveAppDataMods(paths.ModsDir, bundledModsDir, allowUserInput);
523-
#endif
524488
}
525489
}
526490
Console.WriteLine();
@@ -848,92 +812,6 @@ private IEnumerable<DirectoryInfo> DetectGameFolders(ModToolkit toolkit, Install
848812
}
849813
}
850814

851-
#if SMAPI_DEPRECATED
852-
/// <summary>Interactively move mods out of the app data directory.</summary>
853-
/// <param name="properModsDir">The directory which should contain all mods.</param>
854-
/// <param name="packagedModsDir">The installer directory containing packaged mods.</param>
855-
/// <param name="allowUserInput">Whether the installer can ask for user input from the terminal.</param>
856-
private void InteractivelyRemoveAppDataMods(DirectoryInfo properModsDir, DirectoryInfo packagedModsDir, bool allowUserInput)
857-
{
858-
// get packaged mods to delete
859-
string[] packagedModNames = packagedModsDir.GetDirectories().Select(p => p.Name).ToArray();
860-
861-
// get path
862-
string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley");
863-
DirectoryInfo modDir = new(Path.Combine(appDataPath, "Mods"));
864-
865-
// check if migration needed
866-
if (!modDir.Exists)
867-
return;
868-
this.PrintDebug($"Found an obsolete mod path: {modDir.FullName}");
869-
this.PrintDebug(" Support for mods here was dropped in SMAPI 1.0 (it was never officially supported).");
870-
871-
// move mods if no conflicts (else warn)
872-
foreach (FileSystemInfo entry in modDir.EnumerateFileSystemInfos().Where(this.ShouldCopy))
873-
{
874-
// get type
875-
bool isDir = entry is DirectoryInfo;
876-
if (!isDir && entry is not FileInfo)
877-
continue; // should never happen
878-
879-
// delete packaged mods (newer version bundled into SMAPI)
880-
if (isDir && packagedModNames.Contains(entry.Name, StringComparer.OrdinalIgnoreCase))
881-
{
882-
this.PrintDebug($" Deleting {entry.Name} because it's bundled into SMAPI...");
883-
this.InteractivelyDelete(entry.FullName, allowUserInput);
884-
continue;
885-
}
886-
887-
// check paths
888-
string newPath = Path.Combine(properModsDir.FullName, entry.Name);
889-
if (isDir ? Directory.Exists(newPath) : File.Exists(newPath))
890-
{
891-
this.PrintWarning($" Can't move {entry.Name} because it already exists in your game's mod directory.");
892-
continue;
893-
}
894-
895-
// move into mods
896-
this.PrintDebug($" Moving {entry.Name} into the game's mod directory...");
897-
this.Move(entry, newPath);
898-
}
899-
900-
// delete if empty
901-
if (modDir.EnumerateFileSystemInfos().Any())
902-
this.PrintWarning(" You have files in this folder which couldn't be moved automatically. These will be ignored by SMAPI.");
903-
else
904-
{
905-
this.PrintDebug(" Deleted empty directory.");
906-
modDir.Delete(recursive: true);
907-
}
908-
}
909-
910-
/// <summary>Move a filesystem entry to a new parent directory.</summary>
911-
/// <param name="entry">The filesystem entry to move.</param>
912-
/// <param name="newPath">The destination path.</param>
913-
/// <remarks>We can't use <see cref="FileInfo.MoveTo(string)"/> or <see cref="DirectoryInfo.MoveTo"/>, because those don't work across partitions.</remarks>
914-
private void Move(FileSystemInfo entry, string newPath)
915-
{
916-
// file
917-
if (entry is FileInfo file)
918-
{
919-
file.CopyTo(newPath);
920-
file.Delete();
921-
}
922-
923-
// directory
924-
else
925-
{
926-
Directory.CreateDirectory(newPath);
927-
928-
DirectoryInfo directory = (DirectoryInfo)entry;
929-
foreach (FileSystemInfo child in directory.EnumerateFileSystemInfos().Where(this.ShouldCopy))
930-
this.Move(child, Path.Combine(newPath, child.Name));
931-
932-
directory.Delete(recursive: true);
933-
}
934-
}
935-
#endif
936-
937815
/// <summary>Get whether a file or folder should be copied from the installer files.</summary>
938816
/// <param name="entry">The file or folder info.</param>
939817
private bool ShouldCopy(FileSystemInfo entry)

0 commit comments

Comments
 (0)