summaryrefslogtreecommitdiff
path: root/src/SMAPI
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI')
-rw-r--r--src/SMAPI/Metadata/CoreAssetPropagator.cs125
1 files changed, 102 insertions, 23 deletions
diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs
index 38b205a5..e54e0286 100644
--- a/src/SMAPI/Metadata/CoreAssetPropagator.cs
+++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs
@@ -7,6 +7,7 @@ using StardewModdingAPI.Framework.Reflection;
using StardewValley;
using StardewValley.BellsAndWhistles;
using StardewValley.Buildings;
+using StardewValley.Characters;
using StardewValley.Locations;
using StardewValley.Menus;
using StardewValley.Objects;
@@ -66,6 +67,16 @@ namespace StardewModdingAPI.Metadata
switch (key.ToLower().Replace("/", "\\")) // normalised key so we can compare statically
{
/****
+ ** Animals
+ ****/
+ case "animals\\cat":
+ return this.ReloadPetOrHorseSprites<Cat>(content, key);
+ case "animals\\dog":
+ return this.ReloadPetOrHorseSprites<Dog>(content, key);
+ case "animals\\horse":
+ return this.ReloadPetOrHorseSprites<Horse>(content, key);
+
+ /****
** Buildings
****/
case "buildings\\houses": // Farm
@@ -326,6 +337,9 @@ namespace StardewModdingAPI.Metadata
}
// dynamic textures
+ if (this.IsInFolder(key, "Animals"))
+ return this.ReloadFarmAnimalSprites(content, key);
+
if (this.IsInFolder(key, "Buildings"))
return this.ReloadBuildings(content, key);
@@ -351,6 +365,57 @@ namespace StardewModdingAPI.Metadata
/****
** Reload methods
****/
+ /// <summary>Reload the sprites for matching pets or horses.</summary>
+ /// <typeparam name="TAnimal">The animal type.</typeparam>
+ /// <param name="content">The content manager through which to reload the asset.</param>
+ /// <param name="key">The asset key to reload.</param>
+ /// <returns>Returns whether any textures were reloaded.</returns>
+ private bool ReloadPetOrHorseSprites<TAnimal>(LocalizedContentManager content, string key)
+ where TAnimal : NPC
+ {
+ // find matches
+ TAnimal[] animals = this.GetCharacters().OfType<TAnimal>().ToArray();
+ if (!animals.Any())
+ return false;
+
+ // update sprites
+ Texture2D texture = content.Load<Texture2D>(key);
+ foreach (TAnimal animal in animals)
+ this.SetSpriteTexture(animal.sprite, texture);
+ return true;
+ }
+
+ /// <summary>Reload the sprites for matching farm animals.</summary>
+ /// <param name="content">The content manager through which to reload the asset.</param>
+ /// <param name="key">The asset key to reload.</param>
+ /// <returns>Returns whether any textures were reloaded.</returns>
+ /// <remarks>Derived from <see cref="FarmAnimal.reload"/>.</remarks>
+ private bool ReloadFarmAnimalSprites(LocalizedContentManager content, string key)
+ {
+ // find matches
+ FarmAnimal[] animals = this.GetFarmAnimals().ToArray();
+ if (!animals.Any())
+ return false;
+
+ // update sprites
+ Lazy<Texture2D> texture = new Lazy<Texture2D>(() => content.Load<Texture2D>(key));
+ foreach (FarmAnimal animal in animals)
+ {
+ // get expected key
+ string expectedKey = animal.age < animal.ageWhenMature
+ ? $"Baby{(animal.type == "Duck" ? "White Chicken" : animal.type)}"
+ : animal.type;
+ if (animal.showDifferentTextureWhenReadyForHarvest && animal.currentProduce <= 0)
+ expectedKey = $"Sheared{expectedKey}";
+ expectedKey = $"Animals\\{expectedKey}";
+
+ // reload asset
+ if (expectedKey == key)
+ this.SetSpriteTexture(animal.sprite, texture.Value);
+ }
+ return texture.IsValueCreated;
+ }
+
/// <summary>Reload building textures.</summary>
/// <param name="content">The content manager through which to reload the asset.</param>
/// <param name="key">The asset key to reload.</param>
@@ -417,26 +482,14 @@ namespace StardewModdingAPI.Metadata
{
// get NPCs
string name = this.GetNpcNameFromFileName(Path.GetFileName(key));
- NPC[] characters =
- (
- from location in this.GetLocations()
- from npc in location.characters
- where npc.name == name && npc.IsMonster == monster
- select npc
- )
- .Distinct()
- .ToArray();
+ NPC[] characters = this.GetCharacters().Where(npc => npc.name == name && npc.IsMonster == monster).ToArray();
if (!characters.Any())
return false;
// update portrait
Texture2D texture = content.Load<Texture2D>(key);
foreach (NPC character in characters)
-#if STARDEW_VALLEY_1_3
- this.Reflection.GetField<Texture2D>(character.Sprite, "spriteTexture").SetValue(texture);
-#else
- character.Sprite.Texture = texture;
-#endif
+ this.SetSpriteTexture(character.Sprite, texture);
return true;
}
@@ -448,15 +501,7 @@ namespace StardewModdingAPI.Metadata
{
// get NPCs
string name = this.GetNpcNameFromFileName(Path.GetFileName(key));
- NPC[] villagers =
- (
- from location in this.GetLocations()
- from npc in location.characters
- where npc.name == name && npc.isVillager()
- select npc
- )
- .Distinct()
- .ToArray();
+ NPC[] villagers = this.GetCharacters().Where(npc => npc.name == name && npc.isVillager()).ToArray();
if (!villagers.Any())
return false;
@@ -497,6 +542,18 @@ namespace StardewModdingAPI.Metadata
/****
** Helpers
****/
+ /// <summary>Reload the texture for an animated sprite.</summary>
+ /// <param name="sprite">The animated sprite to update.</param>
+ /// <param name="texture">The texture to set.</param>
+ private void SetSpriteTexture(AnimatedSprite sprite, Texture2D texture)
+ {
+#if STARDEW_VALLEY_1_3
+ this.Reflection.GetField<Texture2D>(sprite, "spriteTexture").SetValue(texture);
+#else
+ sprite.Texture = texture;
+#endif
+ }
+
/// <summary>Get an NPC name from the name of their file under <c>Content/Characters</c>.</summary>
/// <param name="name">The file name.</param>
/// <remarks>Derived from <see cref="NPC.reloadSprite"/>.</remarks>
@@ -515,6 +572,28 @@ namespace StardewModdingAPI.Metadata
}
}
+ /// <summary>Get all NPCs in the game (excluding farm animals).</summary>
+ private IEnumerable<NPC> GetCharacters()
+ {
+ return this.GetLocations().SelectMany(p => p.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)
+ {
+ foreach (FarmAnimal animal in farm.animals.Values)
+ yield return animal;
+ }
+ else if (location is AnimalHouse animalHouse)
+ foreach (FarmAnimal animal in animalHouse.animals.Values)
+ yield return animal;
+ }
+ }
+
/// <summary>Get all locations in the game.</summary>
private IEnumerable<GameLocation> GetLocations()
{