Skip to content

Commit a1bc96d

Browse files
committed
Merge branch 'develop' into stable
2 parents d51ffe5 + f3a7921 commit a1bc96d

Some content is hidden

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

44 files changed

+359
-123
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ appsettings.Development.json
3434
# Azure generated files
3535
src/SMAPI.Web/Properties/PublishProfiles/*.pubxml
3636
src/SMAPI.Web/Properties/ServiceDependencies/* - Web Deploy/
37+
38+
# macOS
39+
.DS_Store

build/common.targets

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ 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.15.1</Version>
10+
<Version>3.16.0</Version>
1111
<Product>SMAPI</Product>
1212
<LangVersion>latest</LangVersion>
1313
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
1414
<DefineConstants>$(DefineConstants);SMAPI_DEPRECATED</DefineConstants>
15-
<DebugType>pdbonly</DebugType>
1615
<DebugSymbols>true</DebugSymbols>
1716

1817
<!--enable nullable annotations, except in .NET Standard 2.0 where they aren't supported-->

docs/release-notes.md

+32-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,39 @@
44
<!--
55
## 4.0.0
66
* 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.15.0 first and then install to the latest version._
7+
_If needed, you can update to SMAPI 3.16.0 first and then install the latest version._
88
-->
99

10+
## 3.16.0
11+
Released 22 August 2022 for Stardew Valley 1.5.6 or later. See [release highlights](https://www.patreon.com/posts/70797008).
12+
13+
* For players:
14+
* Added error message if mod files are detected directly under `Mods` (instead of each mod having its own subfolder).
15+
* SMAPI now sets a success/error code when the game exits.
16+
_This is used by your OS (like Windows) to decide whether to keep the console window open when the game ends._
17+
* Fixed SMAPI on Windows applying different DPI awareness settings than the game (thanks to spacechase0!).
18+
* Fixed Linux/macOS installer's color scheme question partly unreadable if the terminal background is dark.
19+
* Fixed error message when a mod loads an invalid PNG file (thanks to atravita!).
20+
* Fixed error message when a mod is duplicated, but one of the copies is also missing the DLL file. This now shows the duplicate-mod message instead of the missing-DLL message.
21+
* Fixed macOS launcher using Terminal regardless of the system's default terminal (thanks to ishan!).
22+
* Fixed best practices in Linux/macOS launcher scripts (thanks to ishan!).
23+
* Improved translations. Thanks to KediDili (updated Turkish)!
24+
25+
* For mod authors:
26+
* While loading your mod, SMAPI now searches for indirect dependencies in your mod's folder (thanks to TehPers)! This mainly enables F# mods.
27+
* **Raised deprecation message levels.**
28+
_Deprecation warnings are now player-visible in the SMAPI console as faded `DEBUG` messages._
29+
* Updated to Pintail 2.2.1 (see [changes](https://github.com/Nanoray-pl/Pintail/blob/master/docs/release-notes.md#221)).
30+
* Switched SMAPI's `.pdb` files to the newer 'portable' format. This has no effect on mods.
31+
32+
* For the web UI:
33+
* Added log parser warning about performance of PyTK 1.23.0 or earlier.
34+
* Converted images to SVG (thanks to ishan!).
35+
* Updated log parser for the new update alert format in SMAPI 3.15.1.
36+
* Updated the JSON validator/schema for Content Patcher 1.28.0.
37+
* Fixed log parsing for invalid content packs.
38+
* Fixed log parsing if a mod logged a null character.
39+
1040
## 3.15.1
1141
Released 06 July 2022 for Stardew Valley 1.5.6 or later.
1242

@@ -41,7 +71,7 @@ Released 17 June 2022 for Stardew Valley 1.5.6 or later. See [release highlights
4171
* Updated dependencies:
4272
* Harmony 2.2.1 (see changes in [2.2.0](https://github.com/pardeike/Harmony/releases/tag/v2.2.0.0) and [2.2.1](https://github.com/pardeike/Harmony/releases/tag/v2.2.1.0));
4373
* Newtonsoft.Json 13.0.1 (see [changes](https://github.com/JamesNK/Newtonsoft.Json/releases/tag/13.0.1));
44-
* Pintail 2.2.0.
74+
* Pintail 2.2.0 (see [changes](https://github.com/Nanoray-pl/Pintail/blob/master/docs/release-notes.md#220)).
4575
* Removed transitional `UsePintail` option added in 3.14.0 (now always enabled).
4676
* Fixed `onBehalfOf` arguments in the new content API being case-sensitive.
4777
* Fixed map edits which change warps sometimes rebuilding the NPC pathfinding cache unnecessarily, which could cause a noticeable delay for players.

docs/technical/mod-package.md

+3
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,9 @@ The NuGet package is generated automatically in `StardewModdingAPI.ModBuildConfi
412412
when you compile it.
413413

414414
## Release notes
415+
### Upcoming release
416+
* Switched to the newer crossplatform `portable` debug symbols (thanks to lanturnalis!).
417+
415418
### 4.0.1
416419
Released 14 April 2022.
417420

docs/technical/smapi.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ argument | purpose
3333
`--uninstall` | Preselects the uninstall action, skipping the prompt asking what the user wants to do.
3434
`--game-path "path"` | Specifies the full path to the folder containing the Stardew Valley executable, skipping automatic detection and any prompt to choose a path. If the path is not valid, the installer displays an error.
3535

36-
SMAPI itself recognises five arguments **on Windows only**, but these are intended for internal use
37-
or testing and may change without warning. On Linux/macOS, see _environment variables_ below.
36+
SMAPI itself recognises five arguments, but these are meant for internal use or testing, and might
37+
change without warning. **On Linux/macOS**, command-line arguments won't work; see _environment
38+
variables_ below instead.
3839

3940
argument | purpose
4041
-------- | -------
4142
`--developer-mode`<br />`--developer-mode-off` | Enable or disable features intended for mod developers. Currently this only makes `TRACE`-level messages appear in the console.
42-
`--no-terminal` | The SMAPI launcher won't try to open a terminal window, and SMAPI won't log anything to the console. (Messages will still be written to the log file.)
43-
`--use-current-shell` | The SMAPI launcher won't try to open a terminal window, but SMAPI will still log to the console. (Messages will still be written to the log file.)
43+
`--no-terminal` | SMAPI won't log anything to the console. On Linux/macOS only, this will also prevent the launch script from trying to open a terminal window. (Messages will still be written to the log file.)
44+
`--use-current-shell` | On Linux/macOS only, the launch script won't try to open a terminal window. All console output will be sent to the shell running the launch script.
4445
`--mods-path` | The path to search for mods, if not the standard `Mods` folder. This can be a path relative to the game folder (like `--mods-path "Mods (test)"`) or an absolute path.
4546

4647
### Environment variables

src/SMAPI.Installer/InteractiveInstaller.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ public void Run(string[] args)
206206
Console.WriteLine();
207207

208208
// handle choice
209-
string choice = this.InteractivelyChoose("Type 1 or 2, then press enter.", new[] { "1", "2" });
209+
string choice = this.InteractivelyChoose("Type 1 or 2, then press enter.", new[] { "1", "2" }, printLine: Console.WriteLine);
210210
switch (choice)
211211
{
212212
case "1":
@@ -629,22 +629,22 @@ private void RecursiveCopy(FileSystemInfo source, DirectoryInfo targetFolder, Fu
629629
}
630630

631631
/// <summary>Interactively ask the user to choose a value.</summary>
632-
/// <param name="print">A callback which prints a message to the console.</param>
632+
/// <param name="printLine">A callback which prints a message to the console.</param>
633633
/// <param name="message">The message to print.</param>
634634
/// <param name="options">The allowed options (not case sensitive).</param>
635635
/// <param name="indent">The indentation to prefix to output.</param>
636-
private string InteractivelyChoose(string message, string[] options, string indent = "", Action<string>? print = null)
636+
private string InteractivelyChoose(string message, string[] options, string indent = "", Action<string>? printLine = null)
637637
{
638-
print ??= this.PrintInfo;
638+
printLine ??= this.PrintInfo;
639639

640640
while (true)
641641
{
642-
print(indent + message);
642+
printLine(indent + message);
643643
Console.Write(indent);
644644
string? input = Console.ReadLine()?.Trim().ToLowerInvariant();
645645
if (input == null || !options.Contains(input))
646646
{
647-
print($"{indent}That's not a valid option.");
647+
printLine($"{indent}That's not a valid option.");
648648
continue;
649649
}
650650
return input;

src/SMAPI.Installer/assets/unix-launcher.sh

+18-16
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ if [ "$(uname)" == "Darwin" ]; then
5454
# https://stackoverflow.com/a/29511052/262123
5555
if [ "$USE_CURRENT_SHELL" == "false" ]; then
5656
echo "Reopening in the Terminal app..."
57-
echo '#!/bin/sh' > /tmp/open-smapi-terminal.sh
58-
echo "\"$0\" $@ --use-current-shell" >> /tmp/open-smapi-terminal.sh
59-
chmod +x /tmp/open-smapi-terminal.sh
60-
cat /tmp/open-smapi-terminal.sh
61-
open -W -a Terminal /tmp/open-smapi-terminal.sh
62-
rm /tmp/open-smapi-terminal.sh
57+
echo '#!/bin/sh' > /tmp/open-smapi-terminal.command
58+
echo "\"$0\" $@ --use-current-shell" >> /tmp/open-smapi-terminal.command
59+
chmod +x /tmp/open-smapi-terminal.command
60+
cat /tmp/open-smapi-terminal.command
61+
open -W /tmp/open-smapi-terminal.command
62+
rm /tmp/open-smapi-terminal.command
6363
exit 0
6464
fi
6565
fi
@@ -71,8 +71,8 @@ fi
7171
##########
7272
# script must be run from the game folder
7373
if [ ! -f "Stardew Valley.dll" ]; then
74-
echo "Oops! SMAPI must be placed in the Stardew Valley game folder.\nSee instructions: https://stardewvalleywiki.com/Modding:Player_Guide";
75-
read
74+
printf "Oops! SMAPI must be placed in the Stardew Valley game folder.\nSee instructions: https://stardewvalleywiki.com/Modding:Player_Guide";
75+
read -r
7676
exit 1
7777
fi
7878

@@ -102,37 +102,39 @@ else
102102

103103
# find the true shell behind x-terminal-emulator
104104
if [ "$TERMINAL_NAME" = "x-terminal-emulator" ]; then
105-
export TERMINAL_NAME="$(basename "$(readlink -f $(command -v x-terminal-emulator))")"
105+
TERMINAL_NAME="$(basename "$(readlink -f "$(command -v x-terminal-emulator)")")"
106+
export TERMINAL_NAME
106107
fi
107108

108109
# run in selected terminal and account for quirks
109-
export TERMINAL_PATH="$(command -v $TERMINAL_NAME)"
110-
if [ -x $TERMINAL_PATH ]; then
110+
TERMINAL_PATH="$(command -v "$TERMINAL_NAME")"
111+
export TERMINAL_PATH
112+
if [ -x "$TERMINAL_PATH" ]; then
111113
case $TERMINAL_NAME in
112114
terminal|termite)
113115
# consumes only one argument after -e
114116
# options containing space characters are unsupported
115-
exec $TERMINAL_NAME -e "env TERM=xterm $LAUNCH_FILE $@"
117+
exec "$TERMINAL_NAME" -e "env TERM=xterm $LAUNCH_FILE $@"
116118
;;
117119

118120
xterm|konsole|alacritty)
119121
# consumes all arguments after -e
120-
exec $TERMINAL_NAME -e env TERM=xterm $LAUNCH_FILE "$@"
122+
exec "$TERMINAL_NAME" -e env TERM=xterm $LAUNCH_FILE "$@"
121123
;;
122124

123125
terminator|xfce4-terminal|mate-terminal)
124126
# consumes all arguments after -x
125-
exec $TERMINAL_NAME -x env TERM=xterm $LAUNCH_FILE "$@"
127+
exec "$TERMINAL_NAME" -x env TERM=xterm $LAUNCH_FILE "$@"
126128
;;
127129

128130
gnome-terminal)
129131
# consumes all arguments after --
130-
exec $TERMINAL_NAME -- env TERM=xterm $LAUNCH_FILE "$@"
132+
exec "$TERMINAL_NAME" -- env TERM=xterm $LAUNCH_FILE "$@"
131133
;;
132134

133135
kitty)
134136
# consumes all trailing arguments
135-
exec $TERMINAL_NAME env TERM=xterm $LAUNCH_FILE "$@"
137+
exec "$TERMINAL_NAME" env TERM=xterm $LAUNCH_FILE "$@"
136138
;;
137139

138140
*)

src/SMAPI.ModBuildConfig/build/smapi.targets

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
** Set build options
99
**********************************************-->
1010
<PropertyGroup>
11-
<!-- include PDB file by default to enable line numbers in stack traces -->
12-
<DebugType>pdbonly</DebugType>
11+
<!-- enable line numbers in stack traces -->
1312
<DebugSymbols>true</DebugSymbols>
1413

1514
<!-- don't create the 'refs' folder (which isn't useful for mods) -->
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"Name": "Console Commands",
33
"Author": "SMAPI",
4-
"Version": "3.15.1",
4+
"Version": "3.16.0",
55
"Description": "Adds SMAPI console commands that let you manipulate the game.",
66
"UniqueID": "SMAPI.ConsoleCommands",
77
"EntryDll": "ConsoleCommands.dll",
8-
"MinimumApiVersion": "3.15.1"
8+
"MinimumApiVersion": "3.16.0"
99
}
+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"Name": "Error Handler",
33
"Author": "SMAPI",
4-
"Version": "3.15.1",
4+
"Version": "3.16.0",
55
"Description": "Handles some common vanilla errors to log more useful info or avoid breaking the game.",
66
"UniqueID": "SMAPI.ErrorHandler",
77
"EntryDll": "ErrorHandler.dll",
8-
"MinimumApiVersion": "3.15.1"
8+
"MinimumApiVersion": "3.16.0"
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": "3.15.1",
4+
"Version": "3.16.0",
55
"Description": "Automatically backs up all your saves once per day into its folder.",
66
"UniqueID": "SMAPI.SaveBackup",
77
"EntryDll": "SaveBackup.dll",
8-
"MinimumApiVersion": "3.15.1"
8+
"MinimumApiVersion": "3.16.0"
99
}

src/SMAPI.Web/Controllers/LogParserController.cs

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
2-
using System.Linq;
2+
using System.Collections.Specialized;
3+
using System.IO;
34
using System.Text;
45
using System.Threading.Tasks;
6+
using System.Web;
57
using Microsoft.AspNetCore.Mvc;
68
using StardewModdingAPI.Toolkit.Utilities;
79
using StardewModdingAPI.Web.Framework;
@@ -87,9 +89,15 @@ public async Task<ActionResult> Index(string? id = null, LogViewFormat format =
8789
public async Task<ActionResult> PostAsync()
8890
{
8991
// get raw log text
90-
string? input = this.Request.Form["input"].FirstOrDefault();
91-
if (string.IsNullOrWhiteSpace(input))
92-
return this.View("Index", this.GetModel(null, uploadError: "The log file seems to be empty."));
92+
// note: avoid this.Request.Form, which fails if any mod logged a null character.
93+
string? input;
94+
{
95+
using StreamReader reader = new StreamReader(this.Request.Body);
96+
NameValueCollection parsed = HttpUtility.ParseQueryString(await reader.ReadToEndAsync());
97+
input = parsed["input"];
98+
if (string.IsNullOrWhiteSpace(input))
99+
return this.View("Index", this.GetModel(null, uploadError: "The log file seems to be empty."));
100+
}
93101

94102
// upload log
95103
UploadResult uploadResult = await this.Storage.SaveAsync(input);

src/SMAPI.Web/Framework/LogParsing/LogParser.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ public class LogParser
3636
private readonly Regex ContentPackListStartPattern = new(@"^Loaded \d+ content packs:$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
3737

3838
/// <summary>A regex pattern matching an entry in SMAPI's content pack list.</summary>
39-
private readonly Regex ContentPackListEntryPattern = new(@"^ (?<name>.+?) (?<version>[^\s]+)(?: by (?<author>[^\|]+))? \| for (?<for>[^\|]+)(?: \| (?<description>.+))?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
39+
private readonly Regex ContentPackListEntryPattern = new(@"^ (?<name>.+?) (?<version>[^\s]+)(?: by (?<author>[^\|]+))? \| for (?<for>[^\|]*)(?: \| (?<description>.+))?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
4040

4141
/// <summary>A regex pattern matching the start of SMAPI's mod update list.</summary>
4242
private readonly Regex ModUpdateListStartPattern = new(@"^You can update \d+ mods?:$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
4343

4444
/// <summary>A regex pattern matching an entry in SMAPI's mod update list.</summary>
45-
private readonly Regex ModUpdateListEntryPattern = new(@"^ (?<name>.+) (?<version>[^\s]+): (?<link>.+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
45+
private readonly Regex ModUpdateListEntryPattern = new(@"^ (?<name>.+) (?<version>[^\s]+): (?<link>[^\s]+)(?: \(you have [^\)]+\))?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
4646

4747
/// <summary>A regex pattern matching SMAPI's update line.</summary>
4848
private readonly Regex SmapiUpdatePattern = new(@"^You can update SMAPI to (?<version>[^\s]+): (?<link>.+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
@@ -77,8 +77,8 @@ public ParsedLog Parse(string? logText)
7777
};
7878

7979
// parse log messages
80-
LogModInfo smapiMod = new(name: "SMAPI", author: "Pathoschild", version: "", description: "", loaded: true, isMod: false);
81-
LogModInfo gameMod = new(name: "game", author: "", version: "", description: "", loaded: true, isMod: false);
80+
LogModInfo smapiMod = new(ModType.Special, name: "SMAPI", author: "Pathoschild", version: "", description: "", loaded: true);
81+
LogModInfo gameMod = new(ModType.Special, name: "game", author: "", version: "", description: "", loaded: true);
8282
IDictionary<string, List<LogModInfo>> mods = new Dictionary<string, List<LogModInfo>>();
8383
bool inModList = false;
8484
bool inContentPackList = false;
@@ -133,7 +133,7 @@ public ParsedLog Parse(string? logText)
133133

134134
if (!mods.TryGetValue(name, out List<LogModInfo>? entries))
135135
mods[name] = entries = new List<LogModInfo>();
136-
entries.Add(new LogModInfo(name: name, author: author, version: version, description: description, loaded: true));
136+
entries.Add(new LogModInfo(ModType.CodeMod, name: name, author: author, version: version, description: description, loaded: true));
137137

138138
message.Section = LogSection.ModsList;
139139
}
@@ -156,7 +156,7 @@ public ParsedLog Parse(string? logText)
156156

157157
if (!mods.TryGetValue(name, out List<LogModInfo>? entries))
158158
mods[name] = entries = new List<LogModInfo>();
159-
entries.Add(new LogModInfo(name: name, author: author, version: version, description: description, contentPackFor: forMod, loaded: true));
159+
entries.Add(new LogModInfo(ModType.ContentPack, name: name, author: author, version: version, description: description, contentPackFor: forMod, loaded: true));
160160

161161
message.Section = LogSection.ContentPackList;
162162
}

0 commit comments

Comments
 (0)