diff options
author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2022-05-20 17:39:05 -0400 |
---|---|---|
committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2022-05-20 17:39:05 -0400 |
commit | e6ef71bae149b0d94055141075a84783f91e7c52 (patch) | |
tree | f74b681b9b6645b0d095d9a81613ea01e85287c6 /src/SMAPI/Metadata | |
parent | 7332879351f396572abd1785abf5d7807ef97ca4 (diff) | |
download | SMAPI-e6ef71bae149b0d94055141075a84783f91e7c52.tar.gz SMAPI-e6ef71bae149b0d94055141075a84783f91e7c52.tar.bz2 SMAPI-e6ef71bae149b0d94055141075a84783f91e7c52.zip |
add tick cache to asset propagation
Diffstat (limited to 'src/SMAPI/Metadata')
-rw-r--r-- | src/SMAPI/Metadata/CoreAssetPropagator.cs | 123 |
1 files changed, 86 insertions, 37 deletions
diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs index ce9ba7a8..8ed6b591 100644 --- a/src/SMAPI/Metadata/CoreAssetPropagator.cs +++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs @@ -7,6 +7,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using StardewModdingAPI.Framework.ContentManagers; using StardewModdingAPI.Framework.Reflection; +using StardewModdingAPI.Framework.Utilities; using StardewModdingAPI.Internal; using StardewModdingAPI.Toolkit.Utilities; using StardewValley; @@ -58,6 +59,9 @@ namespace StardewModdingAPI.Metadata Other }; + /// <summary>A cache of world data fetched for the current tick.</summary> + private readonly TickCacheDictionary<string> WorldCache = new(); + /********* ** Public methods @@ -842,8 +846,7 @@ namespace StardewModdingAPI.Metadata { Grass[] grasses = ( - from location in this.GetLocations() - from grass in location.terrainFeatures.Values.OfType<Grass>() + from grass in this.GetTerrainFeatures().OfType<Grass>() where this.IsSameBaseName(assetName, grass.textureName()) select grass ) @@ -978,8 +981,9 @@ namespace StardewModdingAPI.Metadata /// <returns>Returns whether any references were updated.</returns> private bool UpdateTreeTextures(int type) { - Tree[] trees = this.GetLocations() - .SelectMany(p => p.terrainFeatures.Values.OfType<Tree>()) + Tree[] trees = this + .GetTerrainFeatures() + .OfType<Tree>() .Where(tree => tree.treeType.Value == type) .ToArray(); @@ -1188,63 +1192,108 @@ namespace StardewModdingAPI.Metadata /// <summary>Get all NPCs in the game (excluding farm animals).</summary> private IEnumerable<NPC> GetCharacters() { - foreach (NPC character in this.GetLocations().SelectMany(p => p.characters)) - yield return character; + return this.WorldCache.GetOrSet( + nameof(this.GetCharacters), + () => + { + List<NPC> characters = new(); - if (Game1.CurrentEvent?.actors != null) - { - foreach (NPC character in Game1.CurrentEvent.actors) - yield return character; - } + foreach (NPC character in this.GetLocations().SelectMany(p => p.characters)) + characters.Add(character); + + if (Game1.CurrentEvent?.actors != null) + { + foreach (NPC character in Game1.CurrentEvent.actors) + characters.Add(character); + } + + return characters; + } + ); } /// <summary>Get all farm animals in the game.</summary> private IEnumerable<FarmAnimal> GetFarmAnimals() { - foreach (GameLocation location in this.GetLocations()) - { - if (location is Farm farm) + return this.WorldCache.GetOrSet( + nameof(this.GetFarmAnimals), + () => { - foreach (FarmAnimal animal in farm.animals.Values) - yield return animal; + List<FarmAnimal> animals = new(); + + foreach (GameLocation location in this.GetLocations()) + { + if (location is Farm farm) + { + foreach (FarmAnimal animal in farm.animals.Values) + animals.Add(animal); + } + else if (location is AnimalHouse animalHouse) + { + foreach (FarmAnimal animal in animalHouse.animals.Values) + animals.Add(animal); + } + } + + return animals; } - else if (location is AnimalHouse animalHouse) - foreach (FarmAnimal animal in animalHouse.animals.Values) - yield return animal; - } + ); } /// <summary>Get all locations in the game.</summary> /// <param name="buildingInteriors">Whether to also get the interior locations for constructable buildings.</param> private IEnumerable<GameLocation> GetLocations(bool buildingInteriors = true) { - return this.GetLocationsWithInfo(buildingInteriors).Select(info => info.Location); + return this.WorldCache.GetOrSet( + $"{nameof(this.GetLocations)}_{buildingInteriors}", + () => this.GetLocationsWithInfo(buildingInteriors).Select(info => info.Location).ToArray() + ); } /// <summary>Get all locations in the game.</summary> /// <param name="buildingInteriors">Whether to also get the interior locations for constructable buildings.</param> private IEnumerable<LocationInfo> GetLocationsWithInfo(bool buildingInteriors = true) { - // get available root locations - IEnumerable<GameLocation> rootLocations = Game1.locations; - if (SaveGame.loaded?.locations != null) - rootLocations = rootLocations.Concat(SaveGame.loaded.locations); + return this.WorldCache.GetOrSet( + $"{nameof(this.GetLocationsWithInfo)}_{buildingInteriors}", + () => + { + List<LocationInfo> locations = new(); - // yield root + child locations - foreach (GameLocation location in rootLocations) - { - yield return new LocationInfo(location, null); + // get root locations + foreach (GameLocation location in Game1.locations) + locations.Add(new LocationInfo(location, null)); + if (SaveGame.loaded?.locations != null) + { + foreach (GameLocation location in SaveGame.loaded.locations) + locations.Add(new LocationInfo(location, null)); + } - if (buildingInteriors && location is BuildableGameLocation buildableLocation) - { - foreach (Building building in buildableLocation.buildings) + // get child locations + if (buildingInteriors) { - GameLocation? indoors = building.indoors.Value; - if (indoors != null) - yield return new LocationInfo(indoors, building); + foreach (BuildableGameLocation location in locations.Select(p => p.Location).OfType<BuildableGameLocation>().ToArray()) + { + foreach (Building building in location.buildings) + { + GameLocation indoors = building.indoors.Value; + if (indoors is not null) + locations.Add(new LocationInfo(indoors, building)); + } + } } - } - } + + return locations; + }); + } + + /// <summary>Get all terrain features in the game.</summary> + private IEnumerable<TerrainFeature> GetTerrainFeatures() + { + return this.WorldCache.GetOrSet( + $"{nameof(this.GetTerrainFeatures)}", + () => this.GetLocations().SelectMany(p => p.terrainFeatures.Values).ToArray() + ); } /// <summary>Get whether two asset names are equivalent if you ignore the locale code.</summary> |