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 21, 2021
2 parents fc5fc54 + 74215e8 commit 75f3600
Show file tree
Hide file tree
Showing 37 changed files with 469 additions and 221 deletions.
4 changes: 2 additions & 2 deletions build/common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

<!--set properties -->
<PropertyGroup>
<Version>3.9.4</Version>
<Version>3.9.5</Version>
<Product>SMAPI</Product>

<LangVersion>latest</LangVersion>
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
<DefineConstants Condition="$(OS) == 'Windows_NT'">$(DefineConstants);SMAPI_FOR_WINDOWS</DefineConstants>
<DefineConstants Condition="$(OS) == 'Windows_NT'">$(DefineConstants);SMAPI_FOR_WINDOWS;SMAPI_FOR_XNA</DefineConstants>
</PropertyGroup>

<!-- if game path is invalid, show one user-friendly error instead of a slew of reference errors -->
Expand Down
21 changes: 21 additions & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@
* Migrated to Harmony 2.0 (see [_migrate to Harmony 2.0_](https://stardewvalleywiki.com/Modding:Migrate_to_Harmony_2.0) for more info).
-->

## 3.9.5
Released 21 March 2021 for Stardew Valley 1.5.4 or later.

* For players:
* Added console command to reset community center bundles _(in Console Commands)_.
* Disabled aggressive memory optimization by default.
_The option was added in SMAPI 3.9.2 to reduce errors for some players, but it can cause multiplayer crashes with some mods. If you often see `OutOfMemoryException` errors, you can edit `smapi-internal/config.json` to re-enable it. We're experimenting with making Stardew Valley 64-bit to address memory issues more systematically._
* Fixed bundles corrupted in non-English saves created after SMAPI 3.9.2.
_If you have an affected save, you can load your save and then enter the `regenerate_bundles confirm` command in the SMAPI console to fix it._
* Internal changes to prepare for unofficial 64-bit.

* For mod authors:
* Improved asset propagation:
* Added for interior door sprites.
* SMAPI now updates the NPC pathfinding cache when map warps are changed through the content API.
* Reduced performance impact of invalidating cached assets before a save is loaded.
* Fixed asset changes not reapplied in the edge case where you're playing in non-English, and the changes are only applied after the save is loaded, and the player returns to title and reloads a save, and the game reloads the target asset before the save is loaded.
* Added a second `KeybindList` constructor to simplify single-key default bindings.
* Added a `Constants.GameFramework` field which indicates whether the game is using XNA Framework or MonoGame.
_Note: mods don't need to handle the difference in most cases, but some players may use MonoGame on Windows in upcoming versions. Mods which check `Constants.TargetPlatform` should review usages as needed._

## 3.9.4
Released 07 March 2021 for Stardew Valley 1.5.4 or later.

Expand Down
4 changes: 2 additions & 2 deletions docs/technical/smapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ environment variable | purpose
`SMAPI_NO_TERMINAL` | Equivalent to `--no-terminal` above.
`SMAPI_MODS_PATH` | Equivalent to `--mods-path` above.


### Compile flags
SMAPI uses a small number of conditional compilation constants, which you can set by editing the
`<DefineConstants>` element in `SMAPI.csproj`. Supported constants:

flag | purpose
---- | -------
`SMAPI_FOR_WINDOWS` | Whether SMAPI is being compiled on Windows for players on Windows. Set automatically in `crossplatform.targets`.
`SMAPI_FOR_WINDOWS` | Whether SMAPI is being compiled for Windows; if not set, the code assumes Linux/MacOS. Set automatically in `common.targets`.
`SMAPI_FOR_XNA` | Whether SMAPI is being compiled for XNA Framework; if not set, the code assumes MonoGame. Set automatically in `common.targets` with the same value as `SMAPI_FOR_WINDOWS`.
`HARMONY_2` | Whether to enable experimental Harmony 2.0 support and rewrite existing Harmony 1._x_ mods for compatibility. Note that you need to replace `build/0Harmony.dll` with a Harmony 2.0 build (or switch to a package reference) to use this flag.

## For SMAPI developers
Expand Down
1 change: 0 additions & 1 deletion src/SMAPI.Installer/SMAPI.Installer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<Description>The SMAPI installer for players.</Description>
<TargetFramework>net45</TargetFramework>
<OutputType>Exe</OutputType>
<PlatformTarget>x86</PlatformTarget>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>

Expand Down
1 change: 0 additions & 1 deletion src/SMAPI.ModBuildConfig/SMAPI.ModBuildConfig.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<!--build-->
<RootNamespace>StardewModdingAPI.ModBuildConfig</RootNamespace>
<TargetFramework>net45</TargetFramework>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>latest</LangVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>

Expand Down
26 changes: 17 additions & 9 deletions src/SMAPI.ModBuildConfig/build/smapi.targets
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,27 @@
<Reference Include="0Harmony" Condition="'$(EnableHarmony)' == 'true'" HintPath="$(GamePath)\smapi-internal\0Harmony.dll" Private="$(CopyModReferencesToBuildOutput)" />
</ItemGroup>

<!-- Windows -->
<!-- Windows only -->
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="$(CopyModReferencesToBuildOutput)" />
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="$(CopyModReferencesToBuildOutput)" />
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="$(CopyModReferencesToBuildOutput)" />
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="$(CopyModReferencesToBuildOutput)" />
<Reference Include="Netcode" HintPath="$(GamePath)\Netcode.dll" Private="$(CopyModReferencesToBuildOutput)" />
</ItemGroup>

<!-- Linux/Mac -->
<ItemGroup Condition="'$(OS)' != 'Windows_NT'">
<Reference Include="MonoGame.Framework" HintPath="$(GamePath)\MonoGame.Framework.dll" Private="$(CopyModReferencesToBuildOutput)" />
</ItemGroup>
<!-- Game framework -->
<Choose>
<When Condition="$(DefineConstants.Contains(SMAPI_FOR_XNA))">
<ItemGroup>
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="$(CopyModReferencesToBuildOutput)" />
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="$(CopyModReferencesToBuildOutput)" />
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="$(CopyModReferencesToBuildOutput)" />
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="$(CopyModReferencesToBuildOutput)" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Reference Include="MonoGame.Framework" HintPath="$(GamePath)\MonoGame.Framework.dll" Private="$(CopyModReferencesToBuildOutput)" />
</ItemGroup>
</Otherwise>
</Choose>


<!--*********************************************
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Netcode;
using StardewValley;
using StardewValley.Network;

namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Other
{
/// <summary>A command which regenerates the game's bundles.</summary>
internal class RegenerateBundlesCommand : ConsoleCommand
{
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
public RegenerateBundlesCommand()
: base("regenerate_bundles", $"Regenerate the game's community center bundle data. WARNING: this will reset all bundle progress, and may have unintended effects if you've already completed bundles. DO NOT USE THIS unless you're absolutely sure.\n\nUsage: regenerate_bundles confirm [<type>] [ignore_seed]\nRegenerate all bundles for this save. If the <type> is set to '{string.Join("' or '", Enum.GetNames(typeof(Game1.BundleType)))}', change the bundle type for the save. If an 'ignore_seed' option is included, remixed bundles are re-randomized without using the predetermined save seed.\n\nExample: regenerate_bundles remixed confirm") { }

/// <summary>Handle the command.</summary>
/// <param name="monitor">Writes messages to the console and log file.</param>
/// <param name="command">The command name.</param>
/// <param name="args">The command arguments.</param>
public override void Handle(IMonitor monitor, string command, ArgumentParser args)
{
// get flags
var bundleType = Game1.bundleType;
bool confirmed = false;
bool useSeed = true;
foreach (string arg in args)
{
if (arg.Equals("confirm", StringComparison.OrdinalIgnoreCase))
confirmed = true;
else if (arg.Equals("ignore_seed", StringComparison.OrdinalIgnoreCase))
useSeed = false;
else if (Enum.TryParse(arg, ignoreCase: true, out Game1.BundleType type))
bundleType = type;
else
{
monitor.Log($"Invalid option '{arg}'. Type 'help {command}' for usage.", LogLevel.Error);
return;
}
}

// require confirmation
if (!confirmed)
{
monitor.Log($"WARNING: this may have unintended consequences (type 'help {command}' for details). Are you sure?", LogLevel.Warn);

string[] newArgs = args.Concat(new[] { "confirm" }).ToArray();
monitor.Log($"To confirm, enter this command: '{command} {string.Join(" ", newArgs)}'.", LogLevel.Info);
return;
}

// need a loaded save
if (!Context.IsWorldReady)
{
monitor.Log("You need to load a save to use this command.", LogLevel.Error);
return;
}

// get private fields
IWorldState state = Game1.netWorldState.Value;
var bundleData = state.GetType().GetField("_bundleData", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)?.GetValue(state) as IDictionary<string, string>
?? throw new InvalidOperationException("Can't access '_bundleData' field on world state.");
var netBundleData = state.GetType().GetField("netBundleData", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)?.GetValue(state) as NetStringDictionary<string, NetString>
?? throw new InvalidOperationException("Can't access 'netBundleData' field on world state.");

// clear bundle data
state.BundleData.Clear();
state.Bundles.Clear();
state.BundleRewards.Clear();
bundleData.Clear();
netBundleData.Clear();

// regenerate bundles
var locale = LocalizedContentManager.CurrentLanguageCode;
try
{
LocalizedContentManager.CurrentLanguageCode = LocalizedContentManager.LanguageCode.en; // the base bundle data needs to be unlocalized (the game will add localized names later)

Game1.bundleType = bundleType;
Game1.GenerateBundles(bundleType, use_seed: useSeed);
}
finally
{
LocalizedContentManager.CurrentLanguageCode = locale;
}

monitor.Log("Regenerated bundles and reset bundle progress.", LogLevel.Info);
monitor.Log("This may have unintended effects if you've already completed any bundles. If you're not sure, exit your game without saving to cancel.", LogLevel.Warn);
}
}
}
16 changes: 9 additions & 7 deletions src/SMAPI.Mods.ConsoleCommands/SMAPI.Mods.ConsoleCommands.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
<RootNamespace>StardewModdingAPI.Mods.ConsoleCommands</RootNamespace>
<TargetFramework>net45</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>

<Import Project="..\..\build\common.targets" />

<ItemGroup>
<ProjectReference Include="..\SMAPI\SMAPI.csproj" Private="False" />
</ItemGroup>
Expand All @@ -16,19 +17,21 @@
<Reference Include="StardewValley.GameData" HintPath="$(GamePath)\StardewValley.GameData.dll" Private="False" />
</ItemGroup>

<!-- Windows only -->
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
<Reference Include="Netcode" HintPath="$(GamePath)\Netcode.dll" Private="False" />
</ItemGroup>

<!-- Game framework -->
<Choose>
<!-- Windows -->
<When Condition="$(OS) == 'Windows_NT'">
<When Condition="$(DefineConstants.Contains(SMAPI_FOR_XNA))">
<ItemGroup>
<Reference Include="Netcode" HintPath="$(GamePath)\Netcode.dll" Private="False" />
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="False" />
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="False" />
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="False" />
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="False" />
</ItemGroup>
</When>

<!-- Linux/Mac -->
<Otherwise>
<ItemGroup>
<Reference Include="MonoGame.Framework" HintPath="$(GamePath)\MonoGame.Framework.dll" Private="False" />
Expand All @@ -41,5 +44,4 @@
</ItemGroup>

<Import Project="..\SMAPI.Internal\SMAPI.Internal.projitems" Label="Shared" />
<Import Project="..\..\build\common.targets" />
</Project>
4 changes: 2 additions & 2 deletions src/SMAPI.Mods.ConsoleCommands/manifest.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"Name": "Console Commands",
"Author": "SMAPI",
"Version": "3.9.4",
"Version": "3.9.5",
"Description": "Adds SMAPI console commands that let you manipulate the game.",
"UniqueID": "SMAPI.ConsoleCommands",
"EntryDll": "ConsoleCommands.dll",
"MinimumApiVersion": "3.9.4"
"MinimumApiVersion": "3.9.5"
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ public void Apply(HarmonyInstance harmony)
#endif
{
harmony.Patch(
#if SMAPI_FOR_WINDOWS
original: AccessTools.Method(typeof(SpriteBatch), "InternalDraw"),
#else
original: AccessTools.Method(typeof(SpriteBatch), "CheckValid", new[] { typeof(Texture2D) }),
#endif
original: Constants.GameFramework == GameFramework.Xna
? AccessTools.Method(typeof(SpriteBatch), "InternalDraw")
: AccessTools.Method(typeof(SpriteBatch), "CheckValid", new[] { typeof(Texture2D) }),
postfix: new HarmonyMethod(this.GetType(), nameof(SpriteBatchValidationPatches.After_SpriteBatch_CheckValid))
);
}
Expand All @@ -40,7 +38,7 @@ public void Apply(HarmonyInstance harmony)
/*********
** Private methods
*********/
#if SMAPI_FOR_WINDOWS
#if SMAPI_FOR_XNA
/// <summary>The method to call instead of <see cref="SpriteBatch.InternalDraw"/>.</summary>
/// <param name="texture">The texture to validate.</param>
#else
Expand Down
16 changes: 9 additions & 7 deletions src/SMAPI.Mods.ErrorHandler/SMAPI.Mods.ErrorHandler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
<RootNamespace>StardewModdingAPI.Mods.ErrorHandler</RootNamespace>
<TargetFramework>net45</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>

<Import Project="..\..\build\common.targets" />

<ItemGroup>
<ProjectReference Include="..\SMAPI\SMAPI.csproj" Private="False" />
<Reference Include="..\..\build\0Harmony.dll" Private="False" />
Expand All @@ -16,19 +17,21 @@
<Reference Include="$(GameExecutableName)" HintPath="$(GamePath)\$(GameExecutableName).exe" Private="False" />
</ItemGroup>

<!-- Windows only -->
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
<Reference Include="Netcode" HintPath="$(GamePath)\Netcode.dll" Private="False" />
</ItemGroup>

<!-- Game framework -->
<Choose>
<!-- Windows -->
<When Condition="$(OS) == 'Windows_NT'">
<When Condition="$(DefineConstants.Contains(SMAPI_FOR_XNA))">
<ItemGroup>
<Reference Include="Netcode" HintPath="$(GamePath)\Netcode.dll" Private="False" />
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="False" />
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="False" />
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="False" />
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" Private="False" />
</ItemGroup>
</When>

<!-- Linux/Mac -->
<Otherwise>
<ItemGroup>
<Reference Include="MonoGame.Framework" HintPath="$(GamePath)\MonoGame.Framework.dll" Private="False" />
Expand All @@ -42,5 +45,4 @@
</ItemGroup>

<Import Project="..\SMAPI.Internal\SMAPI.Internal.projitems" Label="Shared" />
<Import Project="..\..\build\common.targets" />
</Project>
4 changes: 2 additions & 2 deletions src/SMAPI.Mods.ErrorHandler/manifest.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"Name": "Error Handler",
"Author": "SMAPI",
"Version": "3.9.4",
"Version": "3.9.5",
"Description": "Handles some common vanilla errors to log more useful info or avoid breaking the game.",
"UniqueID": "SMAPI.ErrorHandler",
"EntryDll": "ErrorHandler.dll",
"MinimumApiVersion": "3.9.4"
"MinimumApiVersion": "3.9.5"
}
4 changes: 2 additions & 2 deletions src/SMAPI.Mods.SaveBackup/SMAPI.Mods.SaveBackup.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
<RootNamespace>StardewModdingAPI.Mods.SaveBackup</RootNamespace>
<TargetFramework>net45</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>

<Import Project="..\..\build\common.targets" />

<ItemGroup>
<ProjectReference Include="..\SMAPI\SMAPI.csproj" Private="False" />
</ItemGroup>
Expand All @@ -20,5 +21,4 @@
</ItemGroup>

<Import Project="..\SMAPI.Internal\SMAPI.Internal.projitems" Label="Shared" />
<Import Project="..\..\build\common.targets" />
</Project>
4 changes: 2 additions & 2 deletions src/SMAPI.Mods.SaveBackup/manifest.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"Name": "Save Backup",
"Author": "SMAPI",
"Version": "3.9.4",
"Version": "3.9.5",
"Description": "Automatically backs up all your saves once per day into its folder.",
"UniqueID": "SMAPI.SaveBackup",
"EntryDll": "SaveBackup.dll",
"MinimumApiVersion": "3.9.4"
"MinimumApiVersion": "3.9.5"
}
Loading

0 comments on commit 75f3600

Please sign in to comment.