From 31e31538f128f2a79b553a2cc20fe8a6f13e8a06 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 25 Sep 2021 20:22:26 -0400 Subject: fix farmhouse edits shifting player down one tile --- src/SMAPI/Metadata/CoreAssetPropagator.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/SMAPI/Metadata') diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs index 35ae26b3..8bf7a32b 100644 --- a/src/SMAPI/Metadata/CoreAssetPropagator.cs +++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using StardewModdingAPI.Framework.ContentManagers; using StardewModdingAPI.Framework.Reflection; @@ -908,6 +909,8 @@ namespace StardewModdingAPI.Metadata /// The location whose map to reload. private void ReloadMap(GameLocation location) { + Vector2? playerPos = Game1.player?.Position; + if (this.AggressiveMemoryOptimizations) location.map.DisposeTileSheets(Game1.mapDisplayDevice); @@ -926,6 +929,14 @@ namespace StardewModdingAPI.Metadata // update for changes location.updateWarps(); location.updateDoors(); + + // reset player position + // The game may move the player as part of the map changes, even if they're not in that + // location. That's not needed in this case, and it can have weird effects like players + // warping onto the wrong tile (or even off-screen) if a patch changes the farmhouse + // map on location change. + if (playerPos.HasValue) + Game1.player.Position = playerPos.Value; } /// Reload the disposition data for matching NPCs. -- cgit From 2a0a7191a7b943a50e30077b5cdd36eb11aa5dd1 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Oct 2021 23:37:48 -0400 Subject: fix barn/coop map edits resetting the exit warp --- docs/release-notes.md | 1 + src/SMAPI/Metadata/CoreAssetPropagator.cs | 49 +++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 6 deletions(-) (limited to 'src/SMAPI/Metadata') diff --git a/docs/release-notes.md b/docs/release-notes.md index 618dd696..65a2e93b 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -7,6 +7,7 @@ * For mod authors: * Fixed map tile rotations/flips not working for farmhands in split-screen mode. + * Fixed barn/coop exit warps being reset when you edit their interior map. * For the web UI: * Added support for unified [mod data overrides](https://stardewvalleywiki.com/Modding:Mod_compatibility#Mod_data_overrides) defined on the wiki. diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs index 8bf7a32b..b176185b 100644 --- a/src/SMAPI/Metadata/CoreAssetPropagator.cs +++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs @@ -184,8 +184,10 @@ namespace StardewModdingAPI.Metadata if (!ignoreWorld) { - foreach (GameLocation location in this.GetLocations()) + foreach (LocationInfo info in this.GetLocationsWithInfo()) { + GameLocation location = info.Location; + if (!string.IsNullOrWhiteSpace(location.mapPath.Value) && this.NormalizeAssetNameIgnoringEmpty(location.mapPath.Value) == key) { static ISet GetWarpSet(GameLocation location) @@ -196,7 +198,7 @@ namespace StardewModdingAPI.Metadata } var oldWarps = GetWarpSet(location); - this.ReloadMap(location); + this.ReloadMap(info); var newWarps = GetWarpSet(location); changedWarps = changedWarps || oldWarps.Count != newWarps.Count || oldWarps.Any(p => !newWarps.Contains(p)); @@ -906,9 +908,10 @@ namespace StardewModdingAPI.Metadata } /// Reload the map for a location. - /// The location whose map to reload. - private void ReloadMap(GameLocation location) + /// The location whose map to reload. + private void ReloadMap(LocationInfo locationInfo) { + GameLocation location = locationInfo.Location; Vector2? playerPos = Game1.player?.Position; if (this.AggressiveMemoryOptimizations) @@ -929,6 +932,7 @@ namespace StardewModdingAPI.Metadata // update for changes location.updateWarps(); location.updateDoors(); + locationInfo.ParentBuilding?.updateInteriorWarps(); // reset player position // The game may move the player as part of the map changes, even if they're not in that @@ -1212,6 +1216,13 @@ namespace StardewModdingAPI.Metadata /// Get all locations in the game. /// Whether to also get the interior locations for constructable buildings. private IEnumerable GetLocations(bool buildingInteriors = true) + { + return this.GetLocationsWithInfo(buildingInteriors).Select(info => info.Location); + } + + /// Get all locations in the game. + /// Whether to also get the interior locations for constructable buildings. + private IEnumerable GetLocationsWithInfo(bool buildingInteriors = true) { // get available root locations IEnumerable rootLocations = Game1.locations; @@ -1221,7 +1232,7 @@ namespace StardewModdingAPI.Metadata // yield root + child locations foreach (GameLocation location in rootLocations) { - yield return location; + yield return new(location, null); if (buildingInteriors && location is BuildableGameLocation buildableLocation) { @@ -1229,7 +1240,7 @@ namespace StardewModdingAPI.Metadata { GameLocation indoors = building.indoors.Value; if (indoors != null) - yield return indoors; + yield return new(indoors, building); } } } @@ -1317,5 +1328,31 @@ namespace StardewModdingAPI.Metadata // remove key from cache return BuildingPainter.paintMaskLookup.Remove(key); } + + /// Metadata about a location used in asset propagation. + private readonly struct LocationInfo + { + /********* + ** Accessors + *********/ + /// The location instance. + public GameLocation Location { get; } + + /// The building which contains the location, if any. + public Building ParentBuilding { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The location instance. + /// The building which contains the location, if any. + public LocationInfo(GameLocation location, Building parentBuilding) + { + this.Location = location; + this.ParentBuilding = parentBuilding; + } + } } } -- cgit From 2b76309b53f8cf322152801d0c1ca6e3b3c777f5 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 8 Oct 2021 19:53:43 -0400 Subject: fix compile errors on Linux --- src/SMAPI.Toolkit/Framework/Clients/Wiki/ChangeDescriptor.cs | 6 +++--- src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs | 2 +- src/SMAPI/Metadata/CoreAssetPropagator.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/SMAPI/Metadata') diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/ChangeDescriptor.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/ChangeDescriptor.cs index 44ebf297..f1feb44b 100644 --- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/ChangeDescriptor.cs +++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/ChangeDescriptor.cs @@ -86,7 +86,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki // add values if (this.Add.Any()) { - HashSet curValues = new(values.Select(p => p?.Trim() ?? string.Empty), StringComparer.OrdinalIgnoreCase); + HashSet curValues = new HashSet(values.Select(p => p?.Trim() ?? string.Empty), StringComparer.OrdinalIgnoreCase); foreach (string add in this.Add) { if (!curValues.Contains(add)) @@ -130,10 +130,10 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki // parse each change in the descriptor if (!string.IsNullOrWhiteSpace(descriptor)) { - List rawErrors = new(); + List rawErrors = new List(); foreach (string rawEntry in descriptor.Split(',')) { - // normalzie entry + // normalize entry string entry = rawEntry.Trim(); if (entry == string.Empty) continue; diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs index f48c4ffa..f85e82e1 100644 --- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs +++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs @@ -57,7 +57,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki betaVersion = null; // parse mod data overrides - Dictionary overrides = new(StringComparer.OrdinalIgnoreCase); + Dictionary overrides = new Dictionary(StringComparer.OrdinalIgnoreCase); { HtmlNodeCollection modNodes = doc.DocumentNode.SelectNodes("//table[@id='mod-overrides-list']//tr[@class='mod']"); if (modNodes == null) diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs index b176185b..7efd99a0 100644 --- a/src/SMAPI/Metadata/CoreAssetPropagator.cs +++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs @@ -1232,7 +1232,7 @@ namespace StardewModdingAPI.Metadata // yield root + child locations foreach (GameLocation location in rootLocations) { - yield return new(location, null); + yield return new LocationInfo(location, null); if (buildingInteriors && location is BuildableGameLocation buildableLocation) { @@ -1240,7 +1240,7 @@ namespace StardewModdingAPI.Metadata { GameLocation indoors = building.indoors.Value; if (indoors != null) - yield return new(indoors, building); + yield return new LocationInfo(indoors, building); } } } -- cgit