mirror of
https://github.com/Pathoschild/SMAPI.git
synced 2026-10-12 02:08:51 +00:00
Merge branch 'develop' into stable
This commit is contained in:
@@ -7,7 +7,7 @@ repo. It imports the other MSBuild files as needed.
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<!--set general build properties -->
|
||||
<Version>4.0.4</Version>
|
||||
<Version>4.0.5</Version>
|
||||
<Product>SMAPI</Product>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
← [README](README.md)
|
||||
|
||||
# Release notes
|
||||
## 4.0.5
|
||||
Released 06 April 2024 for Stardew Valley 1.6.0 or later.
|
||||
|
||||
* For players:
|
||||
* The installer now deletes obsolete files from very old SMAPI versions again.
|
||||
* The installer now deletes Error Handler automatically if it's at the default path.
|
||||
* Fixed mods sometimes not applying logic inside new buildings.
|
||||
* Minor optimizations.
|
||||
* Updated mod compatibility list.
|
||||
|
||||
* For mod authors:
|
||||
* Fixed world-changed events (e.g. `ObjectListChanged`) not working correctly inside freshly-constructed buildings.
|
||||
|
||||
## 4.0.4
|
||||
Released 29 March 2024 for Stardew Valley 1.6.0 or later.
|
||||
|
||||
|
||||
@@ -53,6 +53,30 @@ namespace StardewModdingApi.Installer
|
||||
yield return GetInstallPath("smapi-internal");
|
||||
yield return GetInstallPath("steam_appid.txt");
|
||||
|
||||
// obsolete files
|
||||
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", "ErrorHandler")); // before 4.0 (no longer needed)
|
||||
yield return GetInstallPath(Path.Combine("Mods", "TrainerMod")); // before 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
|
||||
|
||||
// old log files
|
||||
yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "ErrorLogs");
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"Name": "Console Commands",
|
||||
"Author": "SMAPI",
|
||||
"Version": "4.0.4",
|
||||
"Version": "4.0.5",
|
||||
"Description": "Adds SMAPI console commands that let you manipulate the game.",
|
||||
"UniqueID": "SMAPI.ConsoleCommands",
|
||||
"EntryDll": "ConsoleCommands.dll",
|
||||
"MinimumApiVersion": "4.0.4"
|
||||
"MinimumApiVersion": "4.0.5"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"Name": "Save Backup",
|
||||
"Author": "SMAPI",
|
||||
"Version": "4.0.4",
|
||||
"Version": "4.0.5",
|
||||
"Description": "Automatically backs up all your saves once per day into its folder.",
|
||||
"UniqueID": "SMAPI.SaveBackup",
|
||||
"EntryDll": "SaveBackup.dll",
|
||||
"MinimumApiVersion": "4.0.4"
|
||||
"MinimumApiVersion": "4.0.5"
|
||||
}
|
||||
|
||||
@@ -208,14 +208,19 @@
|
||||
},
|
||||
"Bulk Animal Purchase": {
|
||||
"ID": "aedenthorn.BulkAnimalPurchase",
|
||||
"~1.1.2 | Status": "AssumeBroken",
|
||||
"~1.1.2 | StatusReasonDetails": "Harmony patches fail at runtime"
|
||||
"~0.2.1 | Status": "AssumeBroken",
|
||||
"~0.2.1 | StatusReasonDetails": "Harmony patches fail at runtime"
|
||||
},
|
||||
"Build On Any Tile": {
|
||||
"ID": "Esca.BuildOnAnyTile",
|
||||
"~1.1.2 | Status": "AssumeBroken",
|
||||
"~1.1.2 | StatusReasonDetails": "Harmony patches fail at runtime"
|
||||
},
|
||||
"Carry Chest": {
|
||||
"ID": "spacechase0.CarryChest",
|
||||
"~1.3.6 | Status": "AssumeBroken",
|
||||
"~1.3.6 | StatusReasonDetails": "loses items when chest is placed"
|
||||
},
|
||||
"Categories in Recipes": {
|
||||
"ID": "Traktori.CategoriesInRecipes",
|
||||
"~1.0.0 | Status": "AssumeBroken",
|
||||
@@ -256,10 +261,10 @@
|
||||
"~0.1.1 | Status": "AssumeBroken",
|
||||
"~0.1.1 | StatusReasonDetails": "Harmony patches fail at runtime"
|
||||
},
|
||||
"Enemy health Bars": {
|
||||
"Enemy Health Bars": {
|
||||
"ID": "Speeder.HealthBars",
|
||||
"~1.9.1 | Status": "AssumeBroken",
|
||||
"~1.9.1 | StatusReasonDetails": "causes runtime errors"
|
||||
"~1.9.1-unofficial.2-libraryaddict | Status": "AssumeBroken",
|
||||
"~1.9.1-unofficial.2-libraryaddict | StatusReasonDetails": "causes runtime errors"
|
||||
},
|
||||
"Extreme Weather": {
|
||||
"ID": "BlaDe.ExtremeWeather",
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace StardewModdingAPI
|
||||
internal static int? LogScreenId { get; set; }
|
||||
|
||||
/// <summary>SMAPI's current raw semantic version.</summary>
|
||||
internal static string RawApiVersion = "4.0.4";
|
||||
internal static string RawApiVersion = "4.0.5";
|
||||
}
|
||||
|
||||
/// <summary>Contains SMAPI's constants and assumptions.</summary>
|
||||
|
||||
@@ -74,7 +74,9 @@ namespace StardewModdingAPI.Framework.StateTracking
|
||||
public void Reset()
|
||||
{
|
||||
// update stack sizes
|
||||
foreach (Item item in this.StackSizes.Keys.ToArray().Concat(this.Added))
|
||||
foreach (Item item in this.StackSizes.Keys)
|
||||
this.StackSizes[item] = item.Stack;
|
||||
foreach (Item item in this.Added)
|
||||
this.StackSizes[item] = item.Stack;
|
||||
|
||||
// update watcher
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using StardewModdingAPI.Framework.StateTracking.Comparers;
|
||||
using StardewValley;
|
||||
|
||||
@@ -14,6 +13,9 @@ namespace StardewModdingAPI.Framework.StateTracking.Snapshots
|
||||
/// <summary>A map of tracked locations.</summary>
|
||||
private readonly Dictionary<GameLocation, LocationSnapshot> LocationsDict = new(new ObjectReferenceComparer<GameLocation>());
|
||||
|
||||
/// <summary>The pooled list instance for <see cref="GetMissingLocations"/>.</summary>
|
||||
private static readonly List<GameLocation> PooledMissingLocations = new();
|
||||
|
||||
|
||||
/*********
|
||||
** Accessors
|
||||
@@ -36,7 +38,7 @@ namespace StardewModdingAPI.Framework.StateTracking.Snapshots
|
||||
this.LocationList.Update(watcher.IsLocationListChanged, watcher.Added, watcher.Removed);
|
||||
|
||||
// remove missing locations
|
||||
foreach (var key in this.LocationsDict.Keys.Where(key => !watcher.HasLocationTracker(key)).ToArray())
|
||||
foreach (var key in this.GetMissingLocations(watcher))
|
||||
this.LocationsDict.Remove(key);
|
||||
|
||||
// update locations
|
||||
@@ -48,5 +50,26 @@ namespace StardewModdingAPI.Framework.StateTracking.Snapshots
|
||||
snapshot.Update(locationWatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>Get the watched locations which no longer exist in the world, if any.</summary>
|
||||
/// <param name="watcher">The location list tracker.</param>
|
||||
private List<GameLocation> GetMissingLocations(WorldLocationsTracker watcher)
|
||||
{
|
||||
List<GameLocation> list = WorldLocationsSnapshot.PooledMissingLocations;
|
||||
if (list.Count > 0)
|
||||
list.Clear();
|
||||
|
||||
foreach (GameLocation location in this.LocationsDict.Keys)
|
||||
{
|
||||
if (!watcher.HasLocationTracker(location))
|
||||
list.Add(location);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ namespace StardewModdingAPI.Framework.StateTracking
|
||||
/// <summary>A lookup of registered buildings and their indoor location.</summary>
|
||||
private readonly Dictionary<Building, GameLocation?> BuildingIndoors = new(new ObjectReferenceComparer<Building>());
|
||||
|
||||
/// <summary>The pooled list instance for <see cref="GetLocationsWhoseBuildingsChanged"/>.</summary>
|
||||
private static readonly List<LocationTracker> PooledLocationsWithBuildingsChanged = new();
|
||||
|
||||
|
||||
/*********
|
||||
** Accessors
|
||||
@@ -95,21 +98,23 @@ namespace StardewModdingAPI.Framework.StateTracking
|
||||
}
|
||||
|
||||
// detect building changed
|
||||
foreach (LocationTracker watcher in this.Locations.Where(p => p.BuildingsWatcher.IsChanged).ToArray())
|
||||
foreach (LocationTracker watcher in this.GetLocationsWhoseBuildingsChanged())
|
||||
{
|
||||
this.Remove(watcher.BuildingsWatcher.Removed);
|
||||
this.Add(watcher.BuildingsWatcher.Added);
|
||||
}
|
||||
|
||||
// detect building interiors changed (e.g. construction completed)
|
||||
foreach ((Building building, GameLocation? oldIndoors) in this.BuildingIndoors.Where(p => !object.Equals(p.Key.indoors.Value, p.Value)))
|
||||
foreach ((Building building, GameLocation? oldIndoors) in this.BuildingIndoors)
|
||||
{
|
||||
GameLocation? newIndoors = building.indoors.Value;
|
||||
if (object.ReferenceEquals(oldIndoors, newIndoors))
|
||||
continue;
|
||||
|
||||
if (oldIndoors != null)
|
||||
this.Added.Add(oldIndoors);
|
||||
if (newIndoors != null)
|
||||
this.Removed.Add(newIndoors);
|
||||
this.Remove(oldIndoors);
|
||||
this.Add(newIndoors);
|
||||
|
||||
this.BuildingIndoors[building] = newIndoors;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,5 +264,21 @@ namespace StardewModdingAPI.Framework.StateTracking
|
||||
foreach (LocationTracker watcher in this.Locations)
|
||||
yield return watcher;
|
||||
}
|
||||
|
||||
/// <summary>Get the locations whose building list changed, if any.</summary>
|
||||
private List<LocationTracker> GetLocationsWhoseBuildingsChanged()
|
||||
{
|
||||
List<LocationTracker> list = WorldLocationsTracker.PooledLocationsWithBuildingsChanged;
|
||||
if (list.Count > 0)
|
||||
list.Clear();
|
||||
|
||||
foreach (LocationTracker watcher in this.LocationDict.Values)
|
||||
{
|
||||
if (watcher.IsChanged)
|
||||
list.Add(watcher);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user