From 06c7e4e2b92849858002835ed41c7e9cce60fde4 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 29 Dec 2020 23:58:54 -0500 Subject: show details in TRACE logs when a mod is blocked by compatibility list --- docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'docs') diff --git a/docs/release-notes.md b/docs/release-notes.md index 90557c54..ac4a89c6 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -7,6 +7,10 @@ * Migrated to Harmony 2.0 (see [_migrate to Harmony 2.0_](https://stardewvalleywiki.com/Modding:Migrate_to_Harmony_2.0) for more info). --> +## Upcoming release +* For modders: + * When a mod is blocked by SMAPI's internal compatibility list, the `TRACE` messages while loading it now indicates that and specifies the reason. + ## 3.8.1 Released 26 December 2020 for Stardew Valley 1.5.1 or later. -- cgit From 847826198ff0cc836f566c14725d98b44aa67fdd Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 30 Dec 2020 00:25:32 -0500 Subject: add status reason details to past mods, clean out some old blacklist entries --- docs/release-notes.md | 3 + src/SMAPI.Web/wwwroot/SMAPI.metadata.json | 183 ++++++++++-------------------- 2 files changed, 66 insertions(+), 120 deletions(-) (limited to 'docs') diff --git a/docs/release-notes.md b/docs/release-notes.md index ac4a89c6..c68b3d62 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -8,6 +8,9 @@ --> ## Upcoming release +* For players: + * Updated compatibility list. + * For modders: * When a mod is blocked by SMAPI's internal compatibility list, the `TRACE` messages while loading it now indicates that and specifies the reason. diff --git a/src/SMAPI.Web/wwwroot/SMAPI.metadata.json b/src/SMAPI.Web/wwwroot/SMAPI.metadata.json index b570a322..06762a3f 100644 --- a/src/SMAPI.Web/wwwroot/SMAPI.metadata.json +++ b/src/SMAPI.Web/wwwroot/SMAPI.metadata.json @@ -79,8 +79,7 @@ "JSON Assets": { "ID": "spacechase0.JsonAssets", - "Default | UpdateKey": "Nexus:1720", - "1.3.1 | Status": "AssumeBroken" // causes runtime crashes + "Default | UpdateKey": "Nexus:1720" }, "Mail Framework": { @@ -90,8 +89,7 @@ "MTN": { "ID": "SgtPickles.MTN", - "Default | UpdateKey": "Nexus:2256", - "~1.2.6 | Status": "AssumeBroken" // replaces Game1.multiplayer, which breaks SMAPI's multiplayer API. + "Default | UpdateKey": "Nexus:2256" }, "PyTK": { @@ -164,38 +162,45 @@ *********/ "Audio Devices": { "ID": "maxvollmer.audiodevices", - "~2.0.0 | Status": "AssumeBroken" // causes crash to desktop when starting the game + "~2.0.0 | Status": "AssumeBroken", + "~2.0.0 | StatusReasonDetails": "causes crash to desktop when starting the game" }, "Custom Localization": { "ID": "ZaneYork.CustomLocalization", "FormerIDs": "SMAPI.CustomLocalization", // changed in 1.0.1 - "~1.1 | Status": "AssumeBroken" // reflection error for _localizedAssets field + "~1.1 | Status": "AssumeBroken", + "~1.1 | StatusReasonDetails": "reflection error due to renamed _localizedAssets field" }, "Mod Settings Tab": { "ID": "GilarF.ModSettingsTab", - "~0.2.1 | Status": "AssumeBroken" // fails extending title menu + "~0.2.1 | Status": "AssumeBroken", + "~0.2.1 | StatusReasonDetails": "fails extending title menu" }, "More Grass": { "ID": "EpicBellyFlop45.MoreGrass", - "~1.0.8 | Status": "AssumeBroken" // crashes save load + "~1.0.8 | Status": "AssumeBroken", + "~1.0.8 | StatusReasonDetails": "crashes on save load" }, "Movement Speed": { "ID": "bcmpinc.MovementSpeed", - "~3.0.0 | Status": "AssumeBroken" // transpiler errors + "~3.0.0 | Status": "AssumeBroken", + "~3.0.0 | StatusReasonDetails": "broken due to transpiler errors" }, "Tree Spread": { "ID": "bcmpinc.TreeSpread", - "~3.0.0 | Status": "AssumeBroken" // transpiler errors + "~3.0.0 | Status": "AssumeBroken", + "~3.0.0 | StatusReasonDetails": "broken due to transpiler errors" }, "TreeTransplant": { "ID": "TreeTransplant", - "~1.0.9 | Status": "AssumeBroken" // causes AccessViolationException which prevents game launch + "~1.0.9 | Status": "AssumeBroken", + "~3.0.0 | StatusReasonDetails": "breaks game launch due to AccessViolationException" }, /********* @@ -203,17 +208,14 @@ *********/ "Auto Quality Patch": { "ID": "SilentOak.AutoQualityPatch", - "~2.1.3-unofficial.7-mizzion | Status": "AssumeBroken" // runtime errors + "~2.1.3-unofficial.7-mizzion | Status": "AssumeBroken", + "~2.1.3-unofficial.7-mizzion | StatusReasonDetails": "broken due to runtime errors" }, "Fix Dice": { "ID": "ashley.fixdice", - "~1.1.2 | Status": "AssumeBroken" // crashes game on startup - }, - - "Grass Growth": { - "ID": "bcmpinc.GrassGrowth", - "~1.0 | Status": "AssumeBroken" + "~1.1.2 | Status": "AssumeBroken", + "~1.1.2 | StatusReasonDetails": "crashes game on startup" }, "Invite Code Mod": { @@ -241,11 +243,6 @@ "~2.15 | Status": "AssumeBroken" }, - "Yet Another Harvest With Scythe Mod": { - "ID": "bcmpinc.HarvestWithScythe", - "~1.1 | Status": "AssumeBroken" - }, - /********* ** Broke in SMAPI 3.0 (runtime errors due to lifecycle changes) *********/ @@ -254,16 +251,6 @@ "~1.0.0 | Status": "AssumeBroken" }, - "Arcade 2048": { - "ID": "Platonymous.2048", - "~1.0.6 | Status": "AssumeBroken" // possibly due to PyTK - }, - - "Arcade Snake": { - "ID": "Platonymous.Snake", - "~1.1.0 | Status": "AssumeBroken" // possibly due to PyTK - }, - "Better Sprinklers": { "ID": "Speeder.BetterSprinklers", "~2.3.1-unofficial.7-pathoschild | Status": "AssumeBroken" @@ -281,12 +268,8 @@ "Decrafting Mod": { "ID": "MSCFC.DecraftingMod", - "~1.0 | Status": "AssumeBroken" // NRE in ModEntry - }, - - "JoJaBan - Arcade Sokoban": { - "ID": "Platonymous.JoJaBan", - "~0.4.3 | Status": "AssumeBroken" // possibly due to PyTK + "~1.0 | Status": "AssumeBroken", + "~1.0 | StatusReasonDetails": "fails due to NullReferenceException in ModEntry" }, "Level Extender": { @@ -304,11 +287,6 @@ "~1.5 | Status": "AssumeBroken" }, - "Seed Bag": { - "ID": "Platonymous.SeedBag", - "~1.2.7 | Status": "AssumeBroken" // possibly due to PyTK - }, - "Stardew Valley ESP": { "ID": "reimu.sdv-helper", "~1.1 | Status": "AssumeBroken" @@ -316,12 +294,14 @@ "Underdark Krobus": { "ID": "melnoelle.underdarkkrobus", - "~1.0.0 | Status": "AssumeBroken" // NRE in ModEntry + "~1.0 | Status": "AssumeBroken", + "~1.0 | StatusReasonDetails": "fails due to NullReferenceException in ModEntry" }, "Underdark Sewer": { "ID": "melnoelle.underdarksewer", - "~1.1.0 | Status": "AssumeBroken" // NRE in ModEntry + "~1.1.0 | Status": "AssumeBroken", + "~1.1.0 | StatusReasonDetails": "fails due to NullReferenceException in ModEntry" }, /********* @@ -330,60 +310,70 @@ "2cute FarmCave": { "ID": "taintedwheat.2CuteFarmCave", "Default | UpdateKey": "Nexus:843", - "~2.0 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + "~2.0 | Status": "AssumeBroken", + "~2.0 | StatusReasonDetails": "references the deleted Content/Mine asset" }, "Ace's Expanded Caves - Default Cave": { "ID": "Acerbicon.AECdefault", "Default | UpdateKey": "Nexus:2131", - "~1.2.2 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + "~1.2.2 | Status": "AssumeBroken", + "~1.2.2 | StatusReasonDetails": "references the deleted Content/Mine asset" }, "Ace's Expanded Caves - Desert Cave": { "ID": "Acerbicon.AECdesert", "Default | UpdateKey": "Nexus:2131", - "~1.2.2 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + "~1.2.2 | Status": "AssumeBroken", + "~1.2.2 | StatusReasonDetails": "references the deleted Content/Mine asset" }, "Ace's Expanded Caves - Ice Cave": { "ID": "Acerbicon.AECice", "Default | UpdateKey": "Nexus:2131", - "~1.2.2 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + "~1.2.2 | Status": "AssumeBroken", + "~1.2.2 | StatusReasonDetails": "references the deleted Content/Mine asset" }, "Ace's Expanded Caves - Lava Cave": { "ID": "Acerbicon.AEClava", "Default | UpdateKey": "Nexus:2131", - "~1.2.2 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + "~1.2.2 | Status": "AssumeBroken", + "~1.2.2 | StatusReasonDetails": "references the deleted Content/Mine asset" }, "Ace's Expanded Caves - Slime Cave": { "ID": "Acerbicon.AECslime", "Default | UpdateKey": "Nexus:2131", - "~1.2.2 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + "~1.2.2 | Status": "AssumeBroken", + "~1.2.2 | StatusReasonDetails": "references the deleted Content/Mine asset" }, "Green Pastures Farm": { "ID": "bugbuddy.GreenPasturesFarm", "Default | UpdateKey": "Nexus:2326", - "~1.0 | Status": "AssumeBroken" // references deleted Content/weapons.xnb + "~1.0 | Status": "AssumeBroken", + "~1.0 | StatusReasonDetails": "references the deleted Content/weapons asset" }, "Immersive Farm 2": { "ID": "zander.immersivefarm2", - "~2.0.1 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + "~2.0.1 | Status": "AssumeBroken", + "~2.0.1 | StatusReasonDetails": "references the deleted Content/Mine asset" }, "Karmylla's Immersive Map Edits": { "ID": "Karmylla.ImmersiveMapEdits", "Default | UpdateKey": "Nexus:1149", - "~2.4 | Status": "AssumeBroken" // references deleted Content/weapons.xnb + "~2.4 | Status": "AssumeBroken", + "~2.4 | StatusReasonDetails": "references the deleted Content/weapons asset" }, "Secret Gardens Greenhouse": { "ID": "jessebot.secretgardens", "Default | UpdateKey": "Nexus:3067", - "~2.0.1 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + "~2.0.1 | Status": "AssumeBroken", + "~2.0.1 | StatusReasonDetails": "references the deleted Content/Mine asset" }, /********* @@ -391,102 +381,55 @@ *********/ "Canon-Friendly Dialogue Expansion": { "ID": "gizzymo.canonfriendlyexpansion", - "~1.1.1 | Status": "AssumeBroken" // causes a save crash on certain dates + "~1.1.1 | Status": "AssumeBroken", + "~1.1.1 | StatusReasonDetails": "causes a save crash on certain dates" }, "Everytime Submarine": { "ID": "MustafaDemirel.EverytimeSubmarine", - "~1.0.0 | Status": "AssumeBroken" // breaks player saves if their beach bridge is fixed - }, - - "Always Scroll Map": { - "ID": "bcmpinc.AlwaysScrollMap", - "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) - }, - - "Arcade Pong": { - "ID": "Platonymous.ArcadePong", - "~1.0.2 | Status": "AssumeBroken" // broke in SMAPI 2.6-beta.16 due to reflection into SMAPI internals + "~1.0.0 | Status": "AssumeBroken", + "~1.1.1 | StatusReasonDetails": "breaks player saves if their beach bridge is fixed" }, "BJS Night Sounds": { "ID": "BunnyJumps.BJSNightSounds", - "~1.0.0 | Status": "AssumeBroken" // runtime errors with Harmony 1.2.0.1 in SMAPI 2.8+ - }, - - "Craft Counter": { - "ID": "bcmpinc.CraftCounter", - "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) + "~1.0.0 | Status": "AssumeBroken", + "~1.0.0 | StatusReasonDetails": "runtime errors with Harmony 1.2.0.1 in SMAPI 2.8+" }, "Fishing Adjust": { "ID": "shuaiz.FishingAdjustMod", - "~2.0.1 | Status": "AssumeBroken" // Method not found: 'Void Harmony.HarmonyInstance.Patch(System.Reflection.MethodBase, Harmony.HarmonyMethod, Harmony.HarmonyMethod, Harmony.HarmonyMethod)' + "~2.0.1 | Status": "AssumeBroken", + "~2.0.1 | StatusReasonDetails": "fails with 'method not found' error for 'Void Harmony.HarmonyInstance.Patch(System.Reflection.MethodBase, Harmony.HarmonyMethod, Harmony.HarmonyMethod, Harmony.HarmonyMethod)'" }, "Fishing Automaton": { "ID": "Drynwynn.FishingAutomaton", - "~1.1 | Status": "AssumeBroken" // runtime errors with Harmony 1.2.0.1 in SMAPI 2.8+ - }, - - "Fix Animal Tools": { - "ID": "bcmpinc.FixAnimalTools", - "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) - }, - - "Fix Scythe Exp": { - "ID": "bcmpinc.FixScytheExp", - "~0.3 | Status": "AssumeBroken" // broke in 1.3: Exception from HarmonyInstance "bcmpinc.FixScytheExp" [...] Bad label content in ILGenerator. + "~1.1 | Status": "AssumeBroken", + "~1.1 | StatusReasonDetails": "runtime errors with Harmony 1.2.0.1 in SMAPI 2.8+" }, "More Silo Storage": { "ID": "OrneryWalrus.MoreSiloStorage", - "~1.0.1 | Status": "AssumeBroken" // broke in SDV 1.3 + "~1.0.1 | Status": "AssumeBroken" }, "No Added Flying Mine Monsters": { "ID": "Drynwynn.NoAddedFlyingMineMonsters", - "~1.1 | Status": "AssumeBroken" // runtime errors with Harmony 1.2.0.1 in SMAPI 2.8+ + "~1.1 | Status": "AssumeBroken", + "~1.1 | StatusReasonDetails": "runtime errors with Harmony 1.2.0.1 in SMAPI 2.8+" }, "Server Bookmarker": { "ID": "Ilyaki.ServerBookmarker", - "~1.0.0 | Status": "AssumeBroken" // broke in Stardew Valley 1.3.29 (runtime errors) - }, - - "Skull Cave Saver": { - "ID": "cantorsdust.SkullCaveSaver", - "FormerIDs": "8ac06349-26f7-4394-806c-95d48fd35774 | community.SkullCaveSaver", // changed in 1.1 and 1.2.2 - "1.3-beta | Status": "AssumeBroken" // doesn't work in multiplayer, no longer maintained - }, - - "Stardew Hack": { - "ID": "bcmpinc.StardewHack", - "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) + "~1.0.0 | Status": "AssumeBroken", + "~1.0.0 | StatusReasonDetails": "runtime errors in Stardew Valley 1.3.29" }, "Stephan's Lots of Crops": { "ID": "stephansstardewcrops", - "~1.1 | Status": "AssumeBroken" // broke in SDV 1.3 (overwrites vanilla items) - }, - - "Summit Reborn": { - "ID": "KoihimeNakamura.summitreborn", - "FormerIDs": "emissaryofinfinity.summitreborn", // changed in 1.0.2 - "~1.0.2 | Status": "AssumeBroken" // broke in SDV 1.3 (runtime errors) - }, - - "Tilled Soil Decay": { - "ID": "bcmpinc.TilledSoilDecay", - "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) - }, - - /********* - ** Broke circa SDV 1.2 - *********/ - "Move Faster": { - "ID": "shuaiz.MoveFasterMod", - "~1.0.1 | Status": "AssumeBroken" // doesn't do anything as of SDV 1.2.33 (bad Harmony patch?) + "~1.1 | Status": "AssumeBroken", + "~1.1 | StatusReasonDetails": "causes errors due to overwritten Stardew Valley 1.3 items" } } } -- cgit From f95292953f95ec71071fce7a6438a5403dc85816 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 30 Dec 2020 19:38:48 -0500 Subject: fix repeated mods in 'skipped mods' section of console --- docs/release-notes.md | 1 + src/SMAPI/Framework/Logging/LogManager.cs | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/release-notes.md b/docs/release-notes.md index c68b3d62..dbc8e905 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -10,6 +10,7 @@ ## Upcoming release * For players: * Updated compatibility list. + * Fixed 'skipped mods' section repeating mods in some cases. * For modders: * When a mod is blocked by SMAPI's internal compatibility list, the `TRACE` messages while loading it now indicates that and specifies the reason. diff --git a/src/SMAPI/Framework/Logging/LogManager.cs b/src/SMAPI/Framework/Logging/LogManager.cs index ee013a85..4a8019af 100644 --- a/src/SMAPI/Framework/Logging/LogManager.cs +++ b/src/SMAPI/Framework/Logging/LogManager.cs @@ -425,9 +425,11 @@ namespace StardewModdingAPI.Framework.Logging this.Monitor.Log($" ({mod.ErrorDetails})"); } - // find skipped dependencies - IModMetadata[] skippedDependencies; + // group mods + List skippedDependencies = new List(); + List otherSkippedMods = new List(); { + // track broken dependencies HashSet skippedDependencyIds = new HashSet(StringComparer.OrdinalIgnoreCase); HashSet skippedModIds = new HashSet(from mod in skippedMods where mod.HasID() select mod.Manifest.UniqueID, StringComparer.OrdinalIgnoreCase); foreach (IModMetadata mod in skippedMods) @@ -435,7 +437,15 @@ namespace StardewModdingAPI.Framework.Logging foreach (string requiredId in skippedModIds.Intersect(mod.GetRequiredModIds())) skippedDependencyIds.Add(requiredId); } - skippedDependencies = skippedMods.Where(p => p.HasID() && skippedDependencyIds.Contains(p.Manifest.UniqueID)).ToArray(); + + // collect mod groups + foreach (IModMetadata mod in skippedMods) + { + if (mod.HasID() && skippedDependencyIds.Contains(mod.Manifest.UniqueID)) + skippedDependencies.Add(mod); + else + otherSkippedMods.Add(mod); + } } // log skipped mods @@ -451,7 +461,7 @@ namespace StardewModdingAPI.Framework.Logging this.Monitor.Newline(); } - foreach (IModMetadata mod in skippedMods.OrderBy(p => p.DisplayName)) + foreach (IModMetadata mod in otherSkippedMods.OrderBy(p => p.DisplayName)) LogSkippedMod(mod); this.Monitor.Newline(); } -- cgit From 0fdb09f5f9ef463dbf867c3a46ce680706305f0e Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 1 Jan 2021 11:51:57 -0500 Subject: fix network messages not using same JSON serializer settings (#745) --- docs/release-notes.md | 1 + src/SMAPI.Toolkit/Serialization/JsonHelper.cs | 6 ++++++ src/SMAPI/Events/ModMessageReceivedEventArgs.cs | 10 ++++++++-- src/SMAPI/Framework/SCore.cs | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/release-notes.md b/docs/release-notes.md index dbc8e905..dcd638a3 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -14,6 +14,7 @@ * For modders: * When a mod is blocked by SMAPI's internal compatibility list, the `TRACE` messages while loading it now indicates that and specifies the reason. + * Message data from the `ModMessageReceived` event now uses the same serializer settings as the rest of SMAPI. This mainly adds support for sending crossplatform `Color`, `Point`, `Vector2`, `Rectangle`, and `SemanticVersion` fields through network messages. ## 3.8.1 Released 26 December 2020 for Stardew Valley 1.5.1 or later. diff --git a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs index 031afbb0..00db9903 100644 --- a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs +++ b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs @@ -132,5 +132,11 @@ namespace StardewModdingAPI.Toolkit.Serialization { return JsonConvert.SerializeObject(model, formatting, this.JsonSettings); } + + /// Get a low-level JSON serializer matching the . + public JsonSerializer GetSerializer() + { + return JsonSerializer.CreateDefault(this.JsonSettings); + } } } diff --git a/src/SMAPI/Events/ModMessageReceivedEventArgs.cs b/src/SMAPI/Events/ModMessageReceivedEventArgs.cs index d4370028..d75a7540 100644 --- a/src/SMAPI/Events/ModMessageReceivedEventArgs.cs +++ b/src/SMAPI/Events/ModMessageReceivedEventArgs.cs @@ -1,5 +1,6 @@ using System; using StardewModdingAPI.Framework.Networking; +using StardewModdingAPI.Toolkit.Serialization; namespace StardewModdingAPI.Events { @@ -12,6 +13,9 @@ namespace StardewModdingAPI.Events /// The underlying message model. private readonly ModMessageModel Message; + /// The JSON helper used to deserialize models. + private readonly JsonHelper JsonHelper; + /********* ** Accessors @@ -31,16 +35,18 @@ namespace StardewModdingAPI.Events *********/ /// Construct an instance. /// The received message. - internal ModMessageReceivedEventArgs(ModMessageModel message) + /// The JSON helper used to deserialize models. + internal ModMessageReceivedEventArgs(ModMessageModel message, JsonHelper jsonHelper) { this.Message = message; + this.JsonHelper = jsonHelper; } /// Read the message data into the given model type. /// The message model type. public TModel ReadAs() { - return this.Message.Data.ToObject(); + return this.Message.Data.ToObject(this.JsonHelper.GetSerializer()); } } } diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 27540442..5dc33828 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -1128,7 +1128,7 @@ namespace StardewModdingAPI.Framework modIDs.Remove(message.FromModID); // don't send a broadcast back to the sender // raise events - this.EventManager.ModMessageReceived.Raise(new ModMessageReceivedEventArgs(message), mod => mod != null && modIDs.Contains(mod.Manifest.UniqueID)); + this.EventManager.ModMessageReceived.Raise(new ModMessageReceivedEventArgs(message, this.Toolkit.JsonHelper), mod => mod != null && modIDs.Contains(mod.Manifest.UniqueID)); } /// Constructor a content manager to read game content files. -- cgit From 251ee2121a870bd8210830a8bdb943f64c00e030 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 2 Jan 2021 12:33:19 -0500 Subject: fix players in split-screen mode sharing peer state (#747) --- docs/release-notes.md | 1 + src/SMAPI/Framework/SMultiplayer.cs | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/release-notes.md b/docs/release-notes.md index dcd638a3..a12a5482 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -10,6 +10,7 @@ ## Upcoming release * For players: * Updated compatibility list. + * Fixed errors when multiple players join in split-screen mode. * Fixed 'skipped mods' section repeating mods in some cases. * For modders: diff --git a/src/SMAPI/Framework/SMultiplayer.cs b/src/SMAPI/Framework/SMultiplayer.cs index f3b5e9b9..2f89fce9 100644 --- a/src/SMAPI/Framework/SMultiplayer.cs +++ b/src/SMAPI/Framework/SMultiplayer.cs @@ -10,6 +10,7 @@ using StardewModdingAPI.Framework.Events; using StardewModdingAPI.Framework.Networking; using StardewModdingAPI.Framework.Reflection; using StardewModdingAPI.Toolkit.Serialization; +using StardewModdingAPI.Utilities; using StardewValley; using StardewValley.Network; using StardewValley.SDKs; @@ -54,15 +55,25 @@ namespace StardewModdingAPI.Framework /// Whether to log network traffic. private readonly bool LogNetworkTraffic; + /// The backing field for . + private readonly PerScreen> PeersImpl = new(() => new Dictionary()); + + /// The backing field for . + private readonly PerScreen HostPeerImpl = new(); + /********* ** Accessors *********/ /// The metadata for each connected peer. - public IDictionary Peers { get; } = new Dictionary(); + public IDictionary Peers => this.PeersImpl.Value; /// The metadata for the host player, if the current player is a farmhand. - public MultiplayerPeer HostPeer; + public MultiplayerPeer HostPeer + { + get => this.HostPeerImpl.Value; + private set => this.HostPeerImpl.Value = value; + } /********* -- cgit From 456480ef918fc4d864b425fb7a8779618a91475a Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 2 Jan 2021 15:02:58 -0500 Subject: fix cursor position incorrectly handling UI mode (#741) --- docs/release-notes.md | 1 + src/SMAPI/Framework/CursorPosition.cs | 21 +++++++++++++++++++-- src/SMAPI/Framework/Input/SInputState.cs | 18 ++++++++---------- src/SMAPI/ICursorPosition.cs | 18 ++++++++++++++++-- 4 files changed, 44 insertions(+), 14 deletions(-) (limited to 'docs') diff --git a/docs/release-notes.md b/docs/release-notes.md index a12a5482..c4aa413e 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -16,6 +16,7 @@ * For modders: * When a mod is blocked by SMAPI's internal compatibility list, the `TRACE` messages while loading it now indicates that and specifies the reason. * Message data from the `ModMessageReceived` event now uses the same serializer settings as the rest of SMAPI. This mainly adds support for sending crossplatform `Color`, `Point`, `Vector2`, `Rectangle`, and `SemanticVersion` fields through network messages. + * Fixed how the input API handles UI scaling. This mainly affects `ICursorPosition` values returned by the API; see [the wiki docs](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Input#ICursorPosition) for how to account for UI scaling. ## 3.8.1 Released 26 December 2020 for Stardew Valley 1.5.1 or later. diff --git a/src/SMAPI/Framework/CursorPosition.cs b/src/SMAPI/Framework/CursorPosition.cs index 80d89994..107481e7 100644 --- a/src/SMAPI/Framework/CursorPosition.cs +++ b/src/SMAPI/Framework/CursorPosition.cs @@ -1,4 +1,5 @@ using Microsoft.Xna.Framework; +using StardewValley; namespace StardewModdingAPI.Framework { @@ -25,8 +26,8 @@ namespace StardewModdingAPI.Framework ** Public methods *********/ /// Construct an instance. - /// The pixel position relative to the top-left corner of the in-game map, adjusted for pixel zoom. - /// The pixel position relative to the top-left corner of the visible screen, adjusted for pixel zoom. + /// The pixel position relative to the top-left corner of the in-game map, adjusted for zoom but not UI scaling. + /// The pixel position relative to the top-left corner of the visible screen, adjusted for zoom but not UI scaling. /// The tile position relative to the top-left corner of the map. /// The tile position that the game considers under the cursor for purposes of clicking actions. public CursorPosition(Vector2 absolutePixels, Vector2 screenPixels, Vector2 tile, Vector2 grabTile) @@ -42,5 +43,21 @@ namespace StardewModdingAPI.Framework { return other != null && this.AbsolutePixels == other.AbsolutePixels; } + + /// + public Vector2 GetScaledAbsolutePixels() + { + return Game1.uiMode + ? Utility.ModifyCoordinatesForUIScale(this.AbsolutePixels) + : this.AbsolutePixels; + } + + /// + public Vector2 GetScaledScreenPixels() + { + return Game1.uiMode + ? Utility.ModifyCoordinatesForUIScale(this.ScreenPixels) + : this.ScreenPixels; + } } } diff --git a/src/SMAPI/Framework/Input/SInputState.cs b/src/SMAPI/Framework/Input/SInputState.cs index 23670202..a8d1f371 100644 --- a/src/SMAPI/Framework/Input/SInputState.cs +++ b/src/SMAPI/Framework/Input/SInputState.cs @@ -63,18 +63,16 @@ namespace StardewModdingAPI.Framework.Input base.Update(); // update SMAPI extended data + // note: Stardew Valley is *not* in UI mode when this code runs try { - float scale = Game1.options.uiScale; + float zoomMultiplier = (1f / Game1.options.zoomLevel); // get real values var controller = new GamePadStateBuilder(base.GetGamePadState()); var keyboard = new KeyboardStateBuilder(base.GetKeyboardState()); var mouse = new MouseStateBuilder(base.GetMouseState()); - Vector2 cursorAbsolutePos = new Vector2( - x: (mouse.X / scale) + Game1.uiViewport.X, - y: (mouse.Y / scale) + Game1.uiViewport.Y - ); + Vector2 cursorAbsolutePos = new Vector2((mouse.X * zoomMultiplier) + Game1.viewport.X, (mouse.Y * zoomMultiplier) + Game1.viewport.Y); Vector2? playerTilePos = Context.IsPlayerFree ? Game1.player.getTileLocation() : (Vector2?)null; HashSet reallyDown = new HashSet(this.GetPressedButtons(keyboard, mouse, controller)); @@ -109,7 +107,7 @@ namespace StardewModdingAPI.Framework.Input if (cursorAbsolutePos != this.CursorPositionImpl?.AbsolutePixels || playerTilePos != this.LastPlayerTile) { this.LastPlayerTile = playerTilePos; - this.CursorPositionImpl = this.GetCursorPosition(this.MouseState, cursorAbsolutePos, scale); + this.CursorPositionImpl = this.GetCursorPosition(this.MouseState, cursorAbsolutePos, zoomMultiplier); } } catch (InvalidOperationException) @@ -202,11 +200,11 @@ namespace StardewModdingAPI.Framework.Input /// Get the current cursor position. /// The current mouse state. /// The absolute pixel position relative to the map, adjusted for pixel zoom. - /// The UI scale applied to pixel coordinates. - private CursorPosition GetCursorPosition(MouseState mouseState, Vector2 absolutePixels, float scale) + /// The multiplier applied to pixel coordinates to adjust them for pixel zoom. + private CursorPosition GetCursorPosition(MouseState mouseState, Vector2 absolutePixels, float zoomMultiplier) { - Vector2 screenPixels = new Vector2(mouseState.X / scale, mouseState.Y / scale); - Vector2 tile = new Vector2((int)((Game1.uiViewport.X + screenPixels.X) / Game1.tileSize), (int)((Game1.uiViewport.Y + screenPixels.Y) / Game1.tileSize)); + Vector2 screenPixels = new Vector2(mouseState.X * zoomMultiplier, mouseState.Y * zoomMultiplier); + Vector2 tile = new Vector2((int)((Game1.viewport.X + screenPixels.X) / Game1.tileSize), (int)((Game1.viewport.Y + screenPixels.Y) / Game1.tileSize)); Vector2 grabTile = (Game1.mouseCursorTransparency > 0 && Utility.tileWithinRadiusOfPlayer((int)tile.X, (int)tile.Y, 1, Game1.player)) // derived from Game1.pressActionButton ? tile : Game1.player.GetGrabTile(); diff --git a/src/SMAPI/ICursorPosition.cs b/src/SMAPI/ICursorPosition.cs index 21c57db0..99c1b84d 100644 --- a/src/SMAPI/ICursorPosition.cs +++ b/src/SMAPI/ICursorPosition.cs @@ -1,15 +1,19 @@ using System; using Microsoft.Xna.Framework; +using StardewValley; namespace StardewModdingAPI { /// Represents a cursor position in the different coordinate systems. public interface ICursorPosition : IEquatable { - /// The pixel position relative to the top-left corner of the in-game map. + /********* + ** Accessors + *********/ + /// The pixel position relative to the top-left corner of the in-game map, adjusted for zoom but not UI scaling. See also . Vector2 AbsolutePixels { get; } - /// The pixel position relative to the top-left corner of the visible screen. + /// The pixel position relative to the top-left corner of the visible screen, adjusted for zoom but not UI scaling. See also . Vector2 ScreenPixels { get; } /// The tile position under the cursor relative to the top-left corner of the map. @@ -17,5 +21,15 @@ namespace StardewModdingAPI /// The tile position that the game considers under the cursor for purposes of clicking actions. This may be different than if that's too far from the player. Vector2 GrabTile { get; } + + + /********* + ** Public methods + *********/ + /// Get the , adjusted for UI scaling if needed. This is only different if is true. + Vector2 GetScaledAbsolutePixels(); + + /// Get the , adjusted for UI scaling if needed. This is only different if is true. + Vector2 GetScaledScreenPixels(); } } -- cgit From 76e08fc58b75be3dbcd852bfe53dfed40987871d Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 2 Jan 2021 15:49:25 -0500 Subject: detect flatpak Steam install paths (#739) --- build/find-game-folder.targets | 1 + docs/release-notes.md | 1 + 2 files changed, 2 insertions(+) (limited to 'docs') diff --git a/build/find-game-folder.targets b/build/find-game-folder.targets index f304d841..a4200662 100644 --- a/build/find-game-folder.targets +++ b/build/find-game-folder.targets @@ -11,6 +11,7 @@ $(HOME)/GOG Games/Stardew Valley/game $(HOME)/.steam/steam/steamapps/common/Stardew Valley $(HOME)/.local/share/Steam/steamapps/common/Stardew Valley + $(HOME)/.var/app/com.valvesoftware.Steam/data/Steam/steamapps/common/Stardew Valley /Applications/Stardew Valley.app/Contents/MacOS diff --git a/docs/release-notes.md b/docs/release-notes.md index c4aa413e..ecad1635 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -10,6 +10,7 @@ ## Upcoming release * For players: * Updated compatibility list. + * On Linux, the SMAPI installer now auto-detects flatpak Steam paths. * Fixed errors when multiple players join in split-screen mode. * Fixed 'skipped mods' section repeating mods in some cases. -- cgit From 68bcf28e6cd92dd843c2e461ccca74c0b432f1e6 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 2 Jan 2021 18:22:30 -0500 Subject: update error text linking to renamed wiki section --- docs/release-notes.md | 1 + src/SMAPI/Framework/Logging/LogManager.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/release-notes.md b/docs/release-notes.md index ecad1635..9fbfcbb3 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -13,6 +13,7 @@ * On Linux, the SMAPI installer now auto-detects flatpak Steam paths. * Fixed errors when multiple players join in split-screen mode. * Fixed 'skipped mods' section repeating mods in some cases. + * Fixed out-of-date error text. * For modders: * When a mod is blocked by SMAPI's internal compatibility list, the `TRACE` messages while loading it now indicates that and specifies the reason. diff --git a/src/SMAPI/Framework/Logging/LogManager.cs b/src/SMAPI/Framework/Logging/LogManager.cs index 4a8019af..e504218b 100644 --- a/src/SMAPI/Framework/Logging/LogManager.cs +++ b/src/SMAPI/Framework/Logging/LogManager.cs @@ -46,7 +46,7 @@ namespace StardewModdingAPI.Framework.Logging search: new Regex(@"^System\.InvalidOperationException: Steamworks is not initialized\.[\s\S]+$", RegexOptions.Compiled | RegexOptions.CultureInvariant), replacement: #if SMAPI_FOR_WINDOWS - "Oops! Steam achievements won't work because Steam isn't loaded. You can launch the game through Steam to fix that (see 'Part 2: Configure Steam' in the install guide for more info: https://smapi.io/install).", + "Oops! Steam achievements won't work because Steam isn't loaded. See 'Launch SMAPI through Steam or GOG Galaxy' in the install guide for more info: https://smapi.io/install.", #else "Oops! Steam achievements won't work because Steam isn't loaded. You can launch the game through Steam to fix that.", #endif -- cgit From 397f338394c31e2a9bad2e90383f1ff621ae5d91 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 2 Jan 2021 22:24:45 -0500 Subject: detect and block map replacements that would crash the game due to tilesheet changes --- docs/release-notes.md | 2 + src/SMAPI/Framework/ContentCoordinator.cs | 23 ++++++ .../ContentManagers/GameContentManager.cs | 84 +++++++++++++++++++--- src/SMAPI/Framework/DeprecationManager.cs | 5 ++ 4 files changed, 106 insertions(+), 8 deletions(-) (limited to 'docs') diff --git a/docs/release-notes.md b/docs/release-notes.md index 9fbfcbb3..e671f373 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -10,6 +10,7 @@ ## Upcoming release * For players: * Updated compatibility list. + * SMAPI now blocks farm map replacements that would crash the game in Stardew Valley 1.5. * On Linux, the SMAPI installer now auto-detects flatpak Steam paths. * Fixed errors when multiple players join in split-screen mode. * Fixed 'skipped mods' section repeating mods in some cases. @@ -18,6 +19,7 @@ * For modders: * When a mod is blocked by SMAPI's internal compatibility list, the `TRACE` messages while loading it now indicates that and specifies the reason. * Message data from the `ModMessageReceived` event now uses the same serializer settings as the rest of SMAPI. This mainly adds support for sending crossplatform `Color`, `Point`, `Vector2`, `Rectangle`, and `SemanticVersion` fields through network messages. + * Added warning when a map replacement changes the tilesheet order/IDs, which may cause crashes. * Fixed how the input API handles UI scaling. This mainly affects `ICursorPosition` values returned by the API; see [the wiki docs](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Input#ICursorPosition) for how to account for UI scaling. ## 3.8.1 diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs index f9027972..3d5bb29d 100644 --- a/src/SMAPI/Framework/ContentCoordinator.cs +++ b/src/SMAPI/Framework/ContentCoordinator.cs @@ -54,6 +54,9 @@ namespace StardewModdingAPI.Framework /// The game may adds content managers in asynchronous threads (e.g. when populating the load screen). private readonly ReaderWriterLockSlim ContentManagerLock = new ReaderWriterLockSlim(); + /// An unmodified content manager which doesn't intercept assets, used to compare asset data. + private readonly LocalizedContentManager VanillaContentManager; + /********* ** Accessors @@ -95,6 +98,7 @@ namespace StardewModdingAPI.Framework this.ContentManagers.Add( this.MainContentManager = new GameContentManager("Game1.content", serviceProvider, rootDirectory, currentCulture, this, monitor, reflection, this.OnDisposing, onLoadingFirstAsset) ); + this.VanillaContentManager = new LocalizedContentManager(serviceProvider, rootDirectory); this.CoreAssets = new CoreAssetPropagator(this.MainContentManager.AssertAndNormalizeAssetName, reflection); } @@ -150,6 +154,8 @@ namespace StardewModdingAPI.Framework { foreach (IContentManager contentManager in this.ContentManagers) contentManager.OnLocaleChanged(); + + this.VanillaContentManager.Unload(); }); } @@ -287,6 +293,23 @@ namespace StardewModdingAPI.Framework }); } + /// Get a vanilla asset without interception. + /// The type of asset to load. + /// The asset path relative to the loader root directory, not including the .xnb extension. + public bool TryLoadVanillaAsset(string assetName, out T asset) + { + try + { + asset = this.VanillaContentManager.Load(assetName); + return true; + } + catch + { + asset = default; + return false; + } + } + /// Dispose held resources. public void Dispose() { diff --git a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs index ad8f2ef1..424d6ff3 100644 --- a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs @@ -11,6 +11,7 @@ using StardewModdingAPI.Framework.Reflection; using StardewModdingAPI.Framework.Utilities; using StardewValley; using xTile; +using xTile.Tiles; namespace StardewModdingAPI.Framework.ContentManagers { @@ -308,15 +309,10 @@ namespace StardewModdingAPI.Framework.ContentManagers return null; } - // validate asset - if (data == null) - { - mod.LogAsMod($"Mod incorrectly set asset '{info.AssetName}' to a null value; ignoring override.", LogLevel.Error); - return null; - } - // return matched asset - return new AssetDataForObject(info, data, this.AssertAndNormalizeAssetName); + return this.TryValidateLoadedAsset(info, data, mod) + ? new AssetDataForObject(info, data, this.AssertAndNormalizeAssetName) + : null; } /// Apply any to a loaded asset. @@ -386,5 +382,77 @@ namespace StardewModdingAPI.Framework.ContentManagers // return result return asset; } + + /// Validate that an asset loaded by a mod is valid and won't cause issues. + /// The asset type. + /// The basic asset metadata. + /// The loaded asset data. + /// The mod which loaded the asset. + private bool TryValidateLoadedAsset(IAssetInfo info, T data, IModMetadata mod) + { + // can't load a null asset + if (data == null) + { + mod.LogAsMod($"SMAPI blocked asset replacement for '{info.AssetName}': mod incorrectly set asset to a null value.", LogLevel.Error); + return false; + } + + // when replacing a map, the vanilla tilesheets must have the same order and IDs + if (data is Map loadedMap && this.Coordinator.TryLoadVanillaAsset(info.AssetName, out Map vanillaMap)) + { + for (int i = 0; i < vanillaMap.TileSheets.Count; i++) + { + // check for match + TileSheet vanillaSheet = vanillaMap.TileSheets[i]; + bool found = this.TryFindTilesheet(loadedMap, vanillaSheet.Id, out int loadedIndex, out TileSheet loadedSheet); + if (found && loadedIndex == i) + continue; + + // handle mismatch + { + // only show warning if not farm map + // This is temporary: mods shouldn't do this for any vanilla map, but these are the ones we know will crash. Showing a warning for others instead gives modders time to update their mods, while still simplifying troubleshooting. + bool isFarmMap = info.AssetNameEquals("Maps/Farm") || info.AssetNameEquals("Maps/Farm_Combat") || info.AssetNameEquals("Maps/Farm_Fishing") || info.AssetNameEquals("Maps/Farm_Foraging") || info.AssetNameEquals("Maps/Farm_FourCorners") || info.AssetNameEquals("Maps/Farm_Island") || info.AssetNameEquals("Maps/Farm_Mining"); + + + string reason = found + ? $"mod reordered the original tilesheets, which {(isFarmMap ? "would cause a crash" : "often causes crashes")}.\n\nTechnical details for mod author:\nExpected order [{string.Join(", ", vanillaMap.TileSheets.Select(p => $"'{p.ImageSource}' (id: {p.Id})"))}], but found tilesheet '{vanillaSheet.Id}' at index {loadedIndex} instead of {i}. Make sure custom tilesheet IDs are prefixed with 'z_' to avoid reordering tilesheets." + : $"mod has no tilesheet with ID '{vanillaSheet.Id}'. Map replacements must keep the original tilesheets to avoid errors or crashes."; + + SCore.DeprecationManager.PlaceholderWarn("3.8.2", DeprecationLevel.PendingRemoval); + if (isFarmMap) + { + mod.LogAsMod($"SMAPI blocked asset replacement for '{info.AssetName}': {reason}", LogLevel.Error); + return false; + } + mod.LogAsMod($"SMAPI detected a potential issue with asset replacement for '{info.AssetName}' map: {reason}", LogLevel.Warn); + } + } + } + + return true; + } + + /// Find a map tilesheet by ID. + /// The map whose tilesheets to search. + /// The tilesheet ID to match. + /// The matched tilesheet index, if any. + /// The matched tilesheet, if any. + private bool TryFindTilesheet(Map map, string id, out int index, out TileSheet tilesheet) + { + for (int i = 0; i < map.TileSheets.Count; i++) + { + if (map.TileSheets[i].Id == id) + { + index = i; + tilesheet = map.TileSheets[i]; + return true; + } + } + + index = -1; + tilesheet = null; + return false; + } } } diff --git a/src/SMAPI/Framework/DeprecationManager.cs b/src/SMAPI/Framework/DeprecationManager.cs index c22b5718..fc1b434b 100644 --- a/src/SMAPI/Framework/DeprecationManager.cs +++ b/src/SMAPI/Framework/DeprecationManager.cs @@ -63,6 +63,11 @@ namespace StardewModdingAPI.Framework this.QueuedWarnings.Add(new DeprecationWarning(source, nounPhrase, version, severity, Environment.StackTrace)); } + /// A placeholder method used to track deprecated code for which a separate warning will be shown. + /// The SMAPI version which deprecated it. + /// How deprecated the code is. + public void PlaceholderWarn(string version, DeprecationLevel severity) { } + /// Print any queued messages. public void PrintQueued() { -- cgit From 2b3f0506a16622b25a702aae250e10005287c4f4 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 3 Jan 2021 14:31:10 -0500 Subject: prepare for release --- build/common.targets | 2 +- docs/release-notes.md | 14 ++++++++------ src/SMAPI.Mods.ConsoleCommands/manifest.json | 4 ++-- src/SMAPI.Mods.SaveBackup/manifest.json | 4 ++-- src/SMAPI/Constants.cs | 2 +- 5 files changed, 14 insertions(+), 12 deletions(-) (limited to 'docs') diff --git a/build/common.targets b/build/common.targets index 6c79d290..4332313b 100644 --- a/build/common.targets +++ b/build/common.targets @@ -4,7 +4,7 @@ - 3.8.1 + 3.8.2 SMAPI latest diff --git a/docs/release-notes.md b/docs/release-notes.md index e671f373..82709d3c 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -7,19 +7,21 @@ * Migrated to Harmony 2.0 (see [_migrate to Harmony 2.0_](https://stardewvalleywiki.com/Modding:Migrate_to_Harmony_2.0) for more info). --> -## Upcoming release +## 3.8.2 +Released 03 January 2021 for Stardew Valley 1.5.1 or later. + * For players: - * Updated compatibility list. * SMAPI now blocks farm map replacements that would crash the game in Stardew Valley 1.5. - * On Linux, the SMAPI installer now auto-detects flatpak Steam paths. + * On Linux, the SMAPI installer now auto-detects Flatpak Steam paths. + * Updated compatibility list. * Fixed errors when multiple players join in split-screen mode. * Fixed 'skipped mods' section repeating mods in some cases. * Fixed out-of-date error text. * For modders: - * When a mod is blocked by SMAPI's internal compatibility list, the `TRACE` messages while loading it now indicates that and specifies the reason. - * Message data from the `ModMessageReceived` event now uses the same serializer settings as the rest of SMAPI. This mainly adds support for sending crossplatform `Color`, `Point`, `Vector2`, `Rectangle`, and `SemanticVersion` fields through network messages. - * Added warning when a map replacement changes the tilesheet order/IDs, which may cause crashes. + * Added warning when a map replacement changes the order/IDs of the original tilesheets, which may cause errors and crashes. Doing so for a farm map is blocked outright since that causes a consistent crash in Stardew Valley 1.5. + * Message data from the `ModMessageReceived` event now uses the same serializer settings as the rest of SMAPI. That mainly adds support for sending crossplatform `Color`, `Point`, `Vector2`, `Rectangle`, and `SemanticVersion` fields through network messages. + * When a mod is blocked by SMAPI's compatibility override list, the `TRACE` messages while loading it now say so and indicate why. * Fixed how the input API handles UI scaling. This mainly affects `ICursorPosition` values returned by the API; see [the wiki docs](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Input#ICursorPosition) for how to account for UI scaling. ## 3.8.1 diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json index 61c610d0..13e85c70 100644 --- a/src/SMAPI.Mods.ConsoleCommands/manifest.json +++ b/src/SMAPI.Mods.ConsoleCommands/manifest.json @@ -1,9 +1,9 @@ { "Name": "Console Commands", "Author": "SMAPI", - "Version": "3.8.1", + "Version": "3.8.2", "Description": "Adds SMAPI console commands that let you manipulate the game.", "UniqueID": "SMAPI.ConsoleCommands", "EntryDll": "ConsoleCommands.dll", - "MinimumApiVersion": "3.8.1" + "MinimumApiVersion": "3.8.2" } diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json index 7cf63e66..475ec165 100644 --- a/src/SMAPI.Mods.SaveBackup/manifest.json +++ b/src/SMAPI.Mods.SaveBackup/manifest.json @@ -1,9 +1,9 @@ { "Name": "Save Backup", "Author": "SMAPI", - "Version": "3.8.1", + "Version": "3.8.2", "Description": "Automatically backs up all your saves once per day into its folder.", "UniqueID": "SMAPI.SaveBackup", "EntryDll": "SaveBackup.dll", - "MinimumApiVersion": "3.8.1" + "MinimumApiVersion": "3.8.2" } diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index 9d5501a3..ef996c0f 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -54,7 +54,7 @@ namespace StardewModdingAPI ** Public ****/ /// SMAPI's current semantic version. - public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("3.8.1"); + public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("3.8.2"); /// The minimum supported version of Stardew Valley. public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.5.1"); -- cgit