Skip to content

Commit

Permalink
Merge branch 'develop' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
Pathoschild committed Mar 19, 2024
2 parents 5919337 + 679dfb3 commit 4c7eac9
Show file tree
Hide file tree
Showing 278 changed files with 8,600 additions and 6,219 deletions.
6 changes: 1 addition & 5 deletions build/common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ repo. It imports the other MSBuild files as needed.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!--set general build properties -->
<Version>3.18.6</Version>
<Version>4.0.0</Version>
<Product>SMAPI</Product>
<LangVersion>latest</LangVersion>
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
<DefineConstants>$(DefineConstants);SMAPI_DEPRECATED</DefineConstants>
<DebugSymbols>true</DebugSymbols>

<!--embed symbols for error stack trace line numbers on Linux/macOS: https://github.com/dotnet/runtime/issues/39987-->
Expand All @@ -34,13 +33,10 @@ repo. It imports the other MSBuild files as needed.
warning | builds | summary | rationale
┄┄┄┄┄┄┄ | ┄┄┄┄┄┄┄┄┄┄ | ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ | ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
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.
CS0612 | deprecated | member is obsolete | internal references to deprecated code when deprecated code is enabled.
CS0618 | deprecated | member is obsolete (with message) | internal references to deprecated code when deprecated code is enabled.
CA1416 | all | platform code available on all platforms | Compiler doesn't recognize the #if constants used by SMAPI.
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.
NU1701 | all | NuGet package targets older .NET version | All such packages are carefully tested to make sure they do work.
-->
<NoWarn Condition="$(DefineConstants.Contains(SMAPI_DEPRECATED))">$(NoWarn);CS0612;CS0618</NoWarn>
<NoWarn>$(NoWarn);CS0436;CA1416;CS0809;NU1701</NoWarn>
</PropertyGroup>

Expand Down
2 changes: 1 addition & 1 deletion build/deploy-local-smapi.targets
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ This assumes `find-game-folder.targets` has already been imported and validated.
</Target>

<!-- bundled mods -->
<Target Name="CopyDefaultMods" Condition="'$(MSBuildProjectName)' == 'SMAPI.Mods.ConsoleCommands' OR '$(MSBuildProjectName)' == 'SMAPI.Mods.ErrorHandler' OR '$(MSBuildProjectName)' == 'SMAPI.Mods.SaveBackup'">
<Target Name="CopyDefaultMods" Condition="'$(MSBuildProjectName)' == 'SMAPI.Mods.ConsoleCommands' OR '$(MSBuildProjectName)' == 'SMAPI.Mods.SaveBackup'">
<ItemGroup>
<TranslationFiles Include="$(TargetDir)\i18n\*.json" />
</ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions build/unix/prepare-install-package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
##########
# paths
gamePath="/home/pathoschild/Stardew Valley"
bundleModNames=("ConsoleCommands" "ErrorHandler" "SaveBackup")
bundleModNames=("ConsoleCommands" "SaveBackup")

# build configuration
buildConfig="Release"
Expand Down Expand Up @@ -69,7 +69,7 @@ for folder in ${folders[@]}; do
for modName in ${bundleModNames[@]}; do
echo "Compiling $modName for $folder..."
echo "-------------------------------------------------"
dotnet publish src/SMAPI.Mods.$modName --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false"
dotnet publish src/SMAPI.Mods.$modName --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" --self-contained false
echo ""
echo ""
done
Expand Down
2 changes: 1 addition & 1 deletion build/unix/set-smapi-version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ cd "`dirname "$0"`/../.."
# apply changes
sed "s/<Version>.+<\/Version>/<Version>$version<\/Version>/" "build/common.targets" --in-place --regexp-extended
sed "s/RawApiVersion = \".+?\";/RawApiVersion = \"$version\";/" "src/SMAPI/Constants.cs" --in-place --regexp-extended
for modName in "ConsoleCommands" "ErrorHandler" "SaveBackup"; do
for modName in "ConsoleCommands" "SaveBackup"; do
sed "s/\"(Version|MinimumApiVersion)\": \".+?\"/\"\1\": \"$version\"/g" "src/SMAPI.Mods.$modName/manifest.json" --in-place --regexp-extended
done
9 changes: 5 additions & 4 deletions build/windows/prepare-install-package.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
##########
# paths
$gamePath = "C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley"
$bundleModNames = "ConsoleCommands", "ErrorHandler", "SaveBackup"
$bundleModNames = "ConsoleCommands", "SaveBackup"

# build configuration
$buildConfig = "Release"
$framework = "net6.0"
$folders = "linux", "macOS", "windows"
$runtimes = @{ linux = "linux-x64"; macOS = "osx-x64"; windows = "win-x64" }
$msBuildPlatformNames = @{ linux = "Unix"; macOS = "OSX"; windows = "Windows_NT" }
Expand Down Expand Up @@ -72,20 +73,20 @@ foreach ($folder in $folders) {

echo "Compiling SMAPI for $folder..."
echo "-------------------------------------------------"
dotnet publish src/SMAPI --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" --self-contained true
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
echo ""
echo ""

echo "Compiling installer for $folder..."
echo "-------------------------------------------------"
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
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
echo ""
echo ""

foreach ($modName in $bundleModNames) {
echo "Compiling $modName for $folder..."
echo "-------------------------------------------------"
dotnet publish src/SMAPI.Mods.$modName --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false"
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
echo ""
echo ""
}
Expand Down
2 changes: 1 addition & 1 deletion build/windows/set-smapi-version.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ cd "$PSScriptRoot/../.."
# apply changes
In-Place-Regex -Path "build/common.targets" -Search "<Version>.+</Version>" -Replace "<Version>$version</Version>"
In-Place-Regex -Path "src/SMAPI/Constants.cs" -Search "RawApiVersion = `".+?`";" -Replace "RawApiVersion = `"$version`";"
ForEach ($modName in "ConsoleCommands","ErrorHandler","SaveBackup") {
ForEach ($modName in "ConsoleCommands","SaveBackup") {
In-Place-Regex -Path "src/SMAPI.Mods.$modName/manifest.json" -Search "`"(Version|MinimumApiVersion)`": `".+?`"" -Replace "`"`$1`": `"$version`""
}
32 changes: 28 additions & 4 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,35 @@
[README](README.md)

# Release notes
<!--
## 4.0.0
* The installer no longer supports updating from SMAPI 2.11.3 or earlier (released in 2019).
_If needed, you can update to SMAPI 3.16.0 first and then install the latest version._
-->
Released 19 March 2024 for Stardew Valley 1.6.0 or later. See [release highlights](https://www.patreon.com/posts/100388693).

* For players:
* Updated for Stardew Valley 1.6.
* Added support for overriding SMAPI configuration per `Mods` folder (thanks to Shockah!).
* Improved performance.
* Improved compatibility rewriting to handle more cases (thanks to SinZ for his contributions!).
* Removed the bundled `ErrorHandler` mod, which is now integrated into Stardew Valley 1.6.
* Removed obsolete console commands: `list_item_types` (no longer needed) and `player_setimmunity` (broke in 1.6 and rarely used).
* Removed support for seamlessly updating from SMAPI 2.11.3 and earlier (released in 2019).
_If needed, you can update to SMAPI 3.18.0 first and then install the latest version._

* For mod authors:
* Updated to .NET 6.
* 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.
* Added support for [custom update manifests](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Update_checks#Custom_update_manifest) (thanks to Jamie Taylor!).
* Removed all deprecated APIs.
* SMAPI no longer intercepts output written to the console. Mods which directly access `Console` will be listed under mod warnings.
* 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.
* Fixed redundant `TRACE` logs for a broken mod which references members with the wrong types.

* For the web UI:
* Updated JSON validator for Content Patcher 2.0.0.
* Fixed uploaded log/JSON file expiry alway shown as renewed.
* Fixed update check for mods with a prerelease version tag not recognized by the ModDrop API. SMAPI now parses the version itself if needed.

* For SMAPI developers:
* 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.

## 3.18.6
Released 05 October 2023 for Stardew Valley 1.5.6 or later.
Expand Down
1 change: 0 additions & 1 deletion docs/technical/smapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ SMAPI uses a small number of conditional compilation constants, which you can se
flag | purpose
---- | -------
`SMAPI_FOR_WINDOWS` | Whether SMAPI is being compiled for Windows; if not set, the code assumes Linux/macOS. Set automatically in `common.targets`.
`SMAPI_DEPRECATED` | Whether to include deprecated code in the build.

## Compile from source code
### Main project
Expand Down
10 changes: 9 additions & 1 deletion docs/technical/web.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,6 @@ field | summary
`brokeIn` | The SMAPI or Stardew Valley version that broke this mod, if any.
`betaCompatibilityStatus`<br />`betaCompatibilitySummary`<br />`betaBrokeIn` | Equivalent to the preceding fields, but for beta versions of SMAPI or Stardew Valley.


</td>
</tr>
</table>
Expand Down Expand Up @@ -324,6 +323,15 @@ Example response with `includeExtendedMetadata: true`:
]
```

### `/mods/metrics`
The `/mods/metrics` endpoint returns a summary of update-check metrics since the server was last
deployed or restarted.

Example request:
```js
GET https://smapi.io/api/v3.0/mods/metrics
```

## Short URLs
The SMAPI web services provides a few short URLs for convenience:

Expand Down
130 changes: 4 additions & 126 deletions src/SMAPI.Installer/InteractiveInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ internal class InteractiveInstaller
/// <summary>The mod IDs which the installer should allow as bundled mods.</summary>
private readonly string[] BundledModIDs = {
"SMAPI.SaveBackup",
"SMAPI.ConsoleCommands",
"SMAPI.ErrorHandler"
"SMAPI.ConsoleCommands"
};

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

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

#if SMAPI_DEPRECATED
// obsolete
yield return GetInstallPath("libgdiplus.dylib"); // before 3.13 (macOS only)
yield return GetInstallPath(Path.Combine("Mods", ".cache")); // 1.3-1.4
yield return GetInstallPath(Path.Combine("Mods", "TrainerMod")); // *–2.0 (renamed to ConsoleCommands)
yield return GetInstallPath("Mono.Cecil.Rocks.dll"); // 1.3–1.8
yield return GetInstallPath("StardewModdingAPI-settings.json"); // 1.0-1.4
yield return GetInstallPath("StardewModdingAPI.AssemblyRewriters.dll"); // 1.3-2.5.5
yield return GetInstallPath("0Harmony.dll"); // moved in 2.8
yield return GetInstallPath("0Harmony.pdb"); // moved in 2.8
yield return GetInstallPath("Mono.Cecil.dll"); // moved in 2.8
yield return GetInstallPath("Newtonsoft.Json.dll"); // moved in 2.8
yield return GetInstallPath("StardewModdingAPI.config.json"); // moved in 2.8
yield return GetInstallPath("StardewModdingAPI.crash.marker"); // moved in 2.8
yield return GetInstallPath("StardewModdingAPI.metadata.json"); // moved in 2.8
yield return GetInstallPath("StardewModdingAPI.update.marker"); // moved in 2.8
yield return GetInstallPath("StardewModdingAPI.Toolkit.dll"); // moved in 2.8
yield return GetInstallPath("StardewModdingAPI.Toolkit.pdb"); // moved in 2.8
yield return GetInstallPath("StardewModdingAPI.Toolkit.xml"); // moved in 2.8
yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.dll"); // moved in 2.8
yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.pdb"); // moved in 2.8
yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.xml"); // moved in 2.8
yield return GetInstallPath("StardewModdingAPI-x64.exe"); // before 3.13

if (modsDir.Exists)
{
foreach (DirectoryInfo modDir in modsDir.EnumerateDirectories())
yield return Path.Combine(modDir.FullName, ".cache"); // 1.4–1.7
}
#endif

yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "ErrorLogs"); // remove old log files
// old log files
yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "ErrorLogs");
}

/// <summary>Handles writing text to the console.</summary>
Expand Down Expand Up @@ -516,11 +485,6 @@ public void Run(string[] args)
.Replace(@"""UseScheme"": ""AutoDetect""", $@"""UseScheme"": ""{scheme}""");
File.WriteAllText(paths.ApiConfigPath, text);
}

#if SMAPI_DEPRECATED
// remove obsolete appdata mods
this.InteractivelyRemoveAppDataMods(paths.ModsDir, bundledModsDir, allowUserInput);
#endif
}
}
Console.WriteLine();
Expand Down Expand Up @@ -848,92 +812,6 @@ private IEnumerable<DirectoryInfo> DetectGameFolders(ModToolkit toolkit, Install
}
}

#if SMAPI_DEPRECATED
/// <summary>Interactively move mods out of the app data directory.</summary>
/// <param name="properModsDir">The directory which should contain all mods.</param>
/// <param name="packagedModsDir">The installer directory containing packaged mods.</param>
/// <param name="allowUserInput">Whether the installer can ask for user input from the terminal.</param>
private void InteractivelyRemoveAppDataMods(DirectoryInfo properModsDir, DirectoryInfo packagedModsDir, bool allowUserInput)
{
// get packaged mods to delete
string[] packagedModNames = packagedModsDir.GetDirectories().Select(p => p.Name).ToArray();

// get path
string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley");
DirectoryInfo modDir = new(Path.Combine(appDataPath, "Mods"));

// check if migration needed
if (!modDir.Exists)
return;
this.PrintDebug($"Found an obsolete mod path: {modDir.FullName}");
this.PrintDebug(" Support for mods here was dropped in SMAPI 1.0 (it was never officially supported).");

// move mods if no conflicts (else warn)
foreach (FileSystemInfo entry in modDir.EnumerateFileSystemInfos().Where(this.ShouldCopy))
{
// get type
bool isDir = entry is DirectoryInfo;
if (!isDir && entry is not FileInfo)
continue; // should never happen

// delete packaged mods (newer version bundled into SMAPI)
if (isDir && packagedModNames.Contains(entry.Name, StringComparer.OrdinalIgnoreCase))
{
this.PrintDebug($" Deleting {entry.Name} because it's bundled into SMAPI...");
this.InteractivelyDelete(entry.FullName, allowUserInput);
continue;
}

// check paths
string newPath = Path.Combine(properModsDir.FullName, entry.Name);
if (isDir ? Directory.Exists(newPath) : File.Exists(newPath))
{
this.PrintWarning($" Can't move {entry.Name} because it already exists in your game's mod directory.");
continue;
}

// move into mods
this.PrintDebug($" Moving {entry.Name} into the game's mod directory...");
this.Move(entry, newPath);
}

// delete if empty
if (modDir.EnumerateFileSystemInfos().Any())
this.PrintWarning(" You have files in this folder which couldn't be moved automatically. These will be ignored by SMAPI.");
else
{
this.PrintDebug(" Deleted empty directory.");
modDir.Delete(recursive: true);
}
}

/// <summary>Move a filesystem entry to a new parent directory.</summary>
/// <param name="entry">The filesystem entry to move.</param>
/// <param name="newPath">The destination path.</param>
/// <remarks>We can't use <see cref="FileInfo.MoveTo(string)"/> or <see cref="DirectoryInfo.MoveTo"/>, because those don't work across partitions.</remarks>
private void Move(FileSystemInfo entry, string newPath)
{
// file
if (entry is FileInfo file)
{
file.CopyTo(newPath);
file.Delete();
}

// directory
else
{
Directory.CreateDirectory(newPath);

DirectoryInfo directory = (DirectoryInfo)entry;
foreach (FileSystemInfo child in directory.EnumerateFileSystemInfos().Where(this.ShouldCopy))
this.Move(child, Path.Combine(newPath, child.Name));

directory.Delete(recursive: true);
}
}
#endif

/// <summary>Get whether a file or folder should be copied from the installer files.</summary>
/// <param name="entry">The file or folder info.</param>
private bool ShouldCopy(FileSystemInfo entry)
Expand Down
Loading

0 comments on commit 4c7eac9

Please sign in to comment.