using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework.Graphics;
using StardewModdingAPI.Framework.Reflection;
using StardewValley;
using StardewValley.BellsAndWhistles;
using StardewValley.Buildings;
using StardewValley.Locations;
using StardewValley.Menus;
using StardewValley.Objects;
using StardewValley.Projectiles;
using StardewValley.TerrainFeatures;
namespace StardewModdingAPI.Metadata
{
/// Provides metadata about core assets in the game.
internal class CoreAssets
{
/*********
** Properties
*********/
/// Normalises an asset key to match the cache key.
protected readonly Func GetNormalisedPath;
/// Setters which update static or singleton texture fields indexed by normalised asset key.
private readonly IDictionary> SingletonSetters;
/*********
** Public methods
*********/
/// Initialise the core asset data.
/// Normalises an asset key to match the cache key.
/// Simplifies access to private code.
public CoreAssets(Func getNormalisedPath, Reflector reflection)
{
this.GetNormalisedPath = getNormalisedPath;
this.SingletonSetters =
new Dictionary>
{
// from CraftingRecipe.InitShared
["Data\\CraftingRecipes"] = (content, key) => CraftingRecipe.craftingRecipes = content.Load>(key),
["Data\\CookingRecipes"] = (content, key) => CraftingRecipe.cookingRecipes = content.Load>(key),
// from Game1.loadContent
["LooseSprites\\daybg"] = (content, key) => Game1.daybg = content.Load(key),
["LooseSprites\\nightbg"] = (content, key) => Game1.nightbg = content.Load(key),
["Maps\\MenuTiles"] = (content, key) => Game1.menuTexture = content.Load(key),
["LooseSprites\\Lighting\\lantern"] = (content, key) => Game1.lantern = content.Load(key),
["LooseSprites\\Lighting\\windowLight"] = (content, key) => Game1.windowLight = content.Load(key),
["LooseSprites\\Lighting\\sconceLight"] = (content, key) => Game1.sconceLight = content.Load(key),
["LooseSprites\\Lighting\\greenLight"] = (content, key) => Game1.cauldronLight = content.Load(key),
["LooseSprites\\Lighting\\indoorWindowLight"] = (content, key) => Game1.indoorWindowLight = content.Load(key),
["LooseSprites\\shadow"] = (content, key) => Game1.shadowTexture = content.Load(key),
["LooseSprites\\Cursors"] = (content, key) => Game1.mouseCursors = content.Load(key),
["LooseSprites\\ControllerMaps"] = (content, key) => Game1.controllerMaps = content.Load(key),
["TileSheets\\animations"] = (content, key) => Game1.animations = content.Load(key),
["Data\\Achievements"] = (content, key) => Game1.achievements = content.Load>(key),
["Data\\NPCGiftTastes"] = (content, key) => Game1.NPCGiftTastes = content.Load>(key),
["Fonts\\SpriteFont1"] = (content, key) => Game1.dialogueFont = content.Load(key),
["Fonts\\SmallFont"] = (content, key) => Game1.smallFont = content.Load(key),
["Fonts\\tinyFont"] = (content, key) => Game1.tinyFont = content.Load(key),
["Fonts\\tinyFontBorder"] = (content, key) => Game1.tinyFontBorder = content.Load(key),
["Maps\\springobjects"] = (content, key) => Game1.objectSpriteSheet = content.Load(key),
["TileSheets\\crops"] = (content, key) => Game1.cropSpriteSheet = content.Load(key),
["TileSheets\\emotes"] = (content, key) => Game1.emoteSpriteSheet = content.Load(key),
["TileSheets\\debris"] = (content, key) => Game1.debrisSpriteSheet = content.Load(key),
["TileSheets\\Craftables"] = (content, key) => Game1.bigCraftableSpriteSheet = content.Load(key),
["TileSheets\\rain"] = (content, key) => Game1.rainTexture = content.Load(key),
["TileSheets\\BuffsIcons"] = (content, key) => Game1.buffsIcons = content.Load(key),
["Data\\ObjectInformation"] = (content, key) => Game1.objectInformation = content.Load>(key),
["Data\\BigCraftablesInformation"] = (content, key) => Game1.bigCraftablesInformation = content.Load>(key),
["Characters\\Farmer\\hairstyles"] = (content, key) => FarmerRenderer.hairStylesTexture = content.Load(key),
["Characters\\Farmer\\shirts"] = (content, key) => FarmerRenderer.shirtsTexture = content.Load(key),
["Characters\\Farmer\\hats"] = (content, key) => FarmerRenderer.hatsTexture = content.Load(key),
["Characters\\Farmer\\accessories"] = (content, key) => FarmerRenderer.accessoriesTexture = content.Load(key),
["TileSheets\\furniture"] = (content, key) => Furniture.furnitureTexture = content.Load(key),
["LooseSprites\\font_bold"] = (content, key) => SpriteText.spriteTexture = content.Load(key),
["LooseSprites\\font_colored"] = (content, key) => SpriteText.coloredTexture = content.Load(key),
["TileSheets\\weapons"] = (content, key) => Tool.weaponsTexture = content.Load(key),
["TileSheets\\Projectiles"] = (content, key) => Projectile.projectileSheet = content.Load(key),
// from Game1.ResetToolSpriteSheet
["TileSheets\\tools"] = (content, key) => Game1.ResetToolSpriteSheet(),
#if STARDEW_VALLEY_1_3
// from Bush
["TileSheets\\bushes"] = (content, key) => reflection.GetField>(typeof(Bush), "texture").SetValue(new Lazy(() => content.Load(key))),
// from Farm
["Buildings\\houses"] = (content, key) => reflection.GetField(typeof(Farm), nameof(Farm.houseTextures)).SetValue(content.Load(key)),
// from Farmer
["Characters\\Farmer\\farmer_base"] = (content, key) =>
{
if (Game1.player != null && Game1.player.isMale)
Game1.player.FarmerRenderer = new FarmerRenderer(key);
},
["Characters\\Farmer\\farmer_girl_base"] = (content, key) =>
{
if (Game1.player != null && !Game1.player.isMale)
Game1.player.FarmerRenderer = new FarmerRenderer(key);
},
#else
// from Bush
["TileSheets\\bushes"] = (content, key) => Bush.texture = content.Load(key),
// from Critter
["TileSheets\\critters"] = (content, key) => Critter.critterTexture = content.Load(key),
// from Farm
["Buildings\\houses"] = (content, key) =>
{
Farm farm = Game1.getFarm();
if (farm != null)
farm.houseTextures = content.Load(key);
},
// from Farmer
["Characters\\Farmer\\farmer_base"] = (content, key) =>
{
if (Game1.player != null && Game1.player.isMale)
Game1.player.FarmerRenderer = new FarmerRenderer(content.Load(key));
},
["Characters\\Farmer\\farmer_girl_base"] = (content, key) =>
{
if (Game1.player != null && !Game1.player.isMale)
Game1.player.FarmerRenderer = new FarmerRenderer(content.Load(key));
},
#endif
// from Flooring
["TerrainFeatures\\Flooring"] = (content, key) => Flooring.floorsTexture = content.Load(key),
// from FruitTree
["TileSheets\\fruitTrees"] = (content, key) => FruitTree.texture = content.Load(key),
// from HoeDirt
["TerrainFeatures\\hoeDirt"] = (content, key) => HoeDirt.lightTexture = content.Load(key),
["TerrainFeatures\\hoeDirtDark"] = (content, key) => HoeDirt.darkTexture = content.Load(key),
["TerrainFeatures\\hoeDirtSnow"] = (content, key) => HoeDirt.snowTexture = content.Load(key),
// from TitleMenu
["Minigames\\Clouds"] = (content, key) =>
{
if (Game1.activeClickableMenu is TitleMenu)
reflection.GetField(Game1.activeClickableMenu, "cloudsTexture").SetValue(content.Load(key));
},
["Minigames\\TitleButtons"] = (content, key) =>
{
if (Game1.activeClickableMenu is TitleMenu titleMenu)
{
reflection.GetField(titleMenu, "titleButtonsTexture").SetValue(content.Load(key));
foreach (TemporaryAnimatedSprite bird in reflection.GetField>(titleMenu, "birds").GetValue())
#if STARDEW_VALLEY_1_3
bird.texture = content.Load(key);
#else
bird.Texture = content.Load(key);
#endif
}
},
// from Wallpaper
["Maps\\walls_and_floors"] = (content, key) => Wallpaper.wallpaperTexture = content.Load(key)
}
.ToDictionary(p => getNormalisedPath(p.Key), p => p.Value);
}
/// Reload one of the game's core assets (if applicable).
/// The content manager through which to reload the asset.
/// The asset key to reload.
/// Returns whether an asset was reloaded.
public bool ReloadForKey(LocalizedContentManager content, string key)
{
// static assets
if (this.SingletonSetters.TryGetValue(key, out Action reload))
{
reload(content, key);
return true;
}
// building textures
if (key.StartsWith(this.GetNormalisedPath("Buildings\\")))
{
Building[] buildings = this.GetAllBuildings().Where(p => key == this.GetNormalisedPath($"Buildings\\{p.buildingType}")).ToArray();
if (buildings.Any())
{
#if STARDEW_VALLEY_1_3
foreach (Building building in buildings)
building.texture = new Lazy(() => content.Load(key));
#else
Texture2D texture = content.Load(key);
foreach (Building building in buildings)
building.texture = texture;
#endif
return true;
}
return false;
}
return false;
}
/*********
** Private methods
*********/
/// Get all player-constructed buildings in the world.
private IEnumerable GetAllBuildings()
{
foreach (BuildableGameLocation location in Game1.locations.OfType())
{
foreach (Building building in location.buildings)
yield return building;
}
}
}
}