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
{
/// Propagates changes to core assets to the game state.
internal class CoreAssetPropagator
{
/*********
** Properties
*********/
/// Normalises an asset key to match the cache key.
private readonly Func GetNormalisedPath;
/// Simplifies access to private game code.
private readonly Reflector Reflection;
/*********
** Public methods
*********/
/// Initialise the core asset data.
/// Normalises an asset key to match the cache key.
/// Simplifies access to private code.
public CoreAssetPropagator(Func getNormalisedPath, Reflector reflection)
{
this.GetNormalisedPath = getNormalisedPath;
this.Reflection = reflection;
}
/// 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 Propagate(LocalizedContentManager content, string key)
{
return this.PropagateImpl(content, key) != null;
}
/*********
** Private methods
*********/
/// 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 any non-null value to indicate an asset was loaded..
private object PropagateImpl(LocalizedContentManager content, string key)
{
Reflector reflection = this.Reflection;
switch (key.ToLower().Replace("/", "\\")) // normalised key so we can compare statically
{
/****
** Buildings
****/
case "buildings\\houses": // Farm
#if STARDEW_VALLEY_1_3
reflection.GetField(typeof(Farm), nameof(Farm.houseTextures)).SetValue(content.Load(key));
return true;
#else
{
Farm farm = Game1.getFarm();
if (farm == null)
return null;
return farm.houseTextures = content.Load(key);
}
#endif
/****
** Content\Characters\Farmer
****/
case "characters\\farmer\\accessories": // Game1.loadContent
return FarmerRenderer.accessoriesTexture = content.Load(key);
case "characters\\farmer\\farmer_base": // Farmer
if (Game1.player == null || !Game1.player.isMale)
return null;
#if STARDEW_VALLEY_1_3
return Game1.player.FarmerRenderer = new FarmerRenderer(key);
#else
return Game1.player.FarmerRenderer = new FarmerRenderer(content.Load(key));
#endif
case "characters\\farmer\\farmer_girl_base": // Farmer
if (Game1.player == null || Game1.player.isMale)
return null;
#if STARDEW_VALLEY_1_3
return Game1.player.FarmerRenderer = new FarmerRenderer(key);
#else
return Game1.player.FarmerRenderer = new FarmerRenderer(content.Load(key));
#endif
case "characters\\farmer\\hairstyles": // Game1.loadContent
return FarmerRenderer.hairStylesTexture = content.Load(key);
case "characters\\farmer\\hats": // Game1.loadContent
return FarmerRenderer.hatsTexture = content.Load(key);
case "characters\\farmer\\shirts": // Game1.loadContent
return FarmerRenderer.shirtsTexture = content.Load(key);
/****
** Content\Data
****/
case "data\\achievements": // Game1.loadContent
return Game1.achievements = content.Load>(key);
case "data\\bigcraftablesinformation": // Game1.loadContent
return Game1.bigCraftablesInformation = content.Load>(key);
case "data\\cookingrecipes": // CraftingRecipe.InitShared
return CraftingRecipe.cookingRecipes = content.Load>(key);
case "data\\craftingrecipes": // CraftingRecipe.InitShared
return CraftingRecipe.craftingRecipes = content.Load>(key);
case "data\\npcgifttastes": // Game1.loadContent
return Game1.NPCGiftTastes = content.Load>(key);
case "data\\objectinformation": // Game1.loadContent
return Game1.objectInformation = content.Load>(key);
/****
** Content\Fonts
****/
case "fonts\\spritefont1": // Game1.loadContent
return Game1.dialogueFont = content.Load(key);
case "fonts\\smallfont": // Game1.loadContent
return Game1.smallFont = content.Load(key);
case "fonts\\tinyfont": // Game1.loadContent
return Game1.tinyFont = content.Load(key);
case "fonts\\tinyfontborder": // Game1.loadContent
return Game1.tinyFontBorder = content.Load(key);
/****
** Content\Lighting
****/
case "loosesprites\\lighting\\greenlight": // Game1.loadContent
return Game1.cauldronLight = content.Load(key);
case "loosesprites\\lighting\\indoorwindowlight": // Game1.loadContent
return Game1.indoorWindowLight = content.Load(key);
case "loosesprites\\lighting\\lantern": // Game1.loadContent
return Game1.lantern = content.Load(key);
case "loosesprites\\lighting\\sconcelight": // Game1.loadContent
return Game1.sconceLight = content.Load(key);
case "loosesprites\\lighting\\windowlight": // Game1.loadContent
return Game1.windowLight = content.Load(key);
/****
** Content\LooseSprites
****/
case "loosesprites\\controllermaps": // Game1.loadContent
return Game1.controllerMaps = content.Load(key);
case "loosesprites\\cursors": // Game1.loadContent
return Game1.mouseCursors = content.Load(key);
case "loosesprites\\daybg": // Game1.loadContent
return Game1.daybg = content.Load(key);
case "loosesprites\\font_bold": // Game1.loadContent
return SpriteText.spriteTexture = content.Load(key);
case "loosesprites\\font_colored": // Game1.loadContent
return SpriteText.coloredTexture = content.Load(key);
case "loosesprites\\nightbg": // Game1.loadContent
return Game1.nightbg = content.Load(key);
case "loosesprites\\shadow": // Game1.loadContent
return Game1.shadowTexture = content.Load(key);
/****
** Content\Critters
****/
case "tilesheets\\critters": // Criter.InitShared
return Critter.critterTexture = content.Load(key);
case "tilesheets\\crops": // Game1.loadContent
return Game1.cropSpriteSheet = content.Load(key);
case "tilesheets\\debris": // Game1.loadContent
return Game1.debrisSpriteSheet = content.Load(key);
case "tilesheets\\emotes": // Game1.loadContent
return Game1.emoteSpriteSheet = content.Load(key);
case "tilesheets\\furniture": // Game1.loadContent
return Furniture.furnitureTexture = content.Load(key);
case "tilesheets\\projectiles": // Game1.loadContent
return Projectile.projectileSheet = content.Load(key);
case "tilesheets\\rain": // Game1.loadContent
return Game1.rainTexture = content.Load(key);
case "tilesheets\\tools": // Game1.ResetToolSpriteSheet
Game1.ResetToolSpriteSheet();
return true;
case "tilesheets\\weapons": // Game1.loadContent
return Tool.weaponsTexture = content.Load(key);
/****
** Content\Maps
****/
case "maps\\menutiles": // Game1.loadContent
return Game1.menuTexture = content.Load(key);
case "maps\\springobjects": // Game1.loadContent
return Game1.objectSpriteSheet = content.Load(key);
case "maps\\walls_and_floors": // Wallpaper
return Wallpaper.wallpaperTexture = content.Load(key);
/****
** Content\Minigames
****/
case "minigames\\clouds": // TitleMenu
if (Game1.activeClickableMenu is TitleMenu)
{
reflection.GetField(Game1.activeClickableMenu, "cloudsTexture").SetValue(content.Load(key));
return true;
}
return null;
case "minigames\\titlebuttons": // TitleMenu
if (Game1.activeClickableMenu is TitleMenu titleMenu)
{
Texture2D texture = content.Load(key);
reflection.GetField(titleMenu, "titleButtonsTexture").SetValue(texture);
foreach (TemporaryAnimatedSprite bird in reflection.GetField>(titleMenu, "birds").GetValue())
#if STARDEW_VALLEY_1_3
bird.texture = texture;
#else
bird.Texture = texture;
#endif
return true;
}
return null;
/****
** Content\TileSheets
****/
case "tilesheets\\animations": // Game1.loadContent
return Game1.animations = content.Load(key);
case "tilesheets\\buffsicons": // Game1.loadContent
return Game1.buffsIcons = content.Load(key);
case "tilesheets\\bushes": // new Bush()
#if STARDEW_VALLEY_1_3
reflection.GetField>(typeof(Bush), "texture").SetValue(new Lazy(() => content.Load(key)));
return true;
#else
return Bush.texture = content.Load(key);
#endif
case "tilesheets\\craftables": // Game1.loadContent
return Game1.bigCraftableSpriteSheet = content.Load(key);
case "tilesheets\\fruittrees": // FruitTree
return FruitTree.texture = content.Load(key);
/****
** Content\TerrainFeatures
****/
case "terrainfeatures\\flooring": // Flooring
return Flooring.floorsTexture = content.Load(key);
case "terrainfeatures\\hoedirt": // from HoeDirt
return HoeDirt.lightTexture = content.Load(key);
case "Terrainfeatures\\hoedirtdark": // from HoeDirt
return HoeDirt.darkTexture = content.Load(key);
case "Terrainfeatures\\hoedirtsnow": // from HoeDirt
return HoeDirt.snowTexture = content.Load(key);
}
// building textures
if (key.StartsWith(this.GetNormalisedPath("Buildings\\"), StringComparison.InvariantCultureIgnoreCase))
{
Building[] buildings = this.GetAllBuildings().Where(p => key.Equals(this.GetNormalisedPath($"Buildings\\{p.buildingType?.ToLower()}"), StringComparison.InvariantCultureIgnoreCase)).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 null;
}
return null;
}
/*********
** 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;
}
}
}
}