diff options
author | Jesse Plamondon-Willard <github@jplamondonw.com> | 2018-03-13 20:25:06 -0400 |
---|---|---|
committer | Jesse Plamondon-Willard <github@jplamondonw.com> | 2018-03-13 20:25:06 -0400 |
commit | afb3c49bbaab07f3148f70d54f5140cdd83f8c20 (patch) | |
tree | dd60902c878c38617f97644b912afb38c568755e /src/SMAPI/Metadata | |
parent | 833d98f49136325edfc4463097710cf2391dd5b2 (diff) | |
parent | 76445dc3589265ba259070300120e96a17957e50 (diff) | |
download | SMAPI-afb3c49bbaab07f3148f70d54f5140cdd83f8c20.tar.gz SMAPI-afb3c49bbaab07f3148f70d54f5140cdd83f8c20.tar.bz2 SMAPI-afb3c49bbaab07f3148f70d54f5140cdd83f8c20.zip |
Merge branch 'develop' into stable
Diffstat (limited to 'src/SMAPI/Metadata')
-rw-r--r-- | src/SMAPI/Metadata/CoreAssets.cs | 68 | ||||
-rw-r--r-- | src/SMAPI/Metadata/InstructionMetadata.cs | 74 |
2 files changed, 108 insertions, 34 deletions
diff --git a/src/SMAPI/Metadata/CoreAssets.cs b/src/SMAPI/Metadata/CoreAssets.cs index 5a98da4b..87629682 100644 --- a/src/SMAPI/Metadata/CoreAssets.cs +++ b/src/SMAPI/Metadata/CoreAssets.cs @@ -2,11 +2,12 @@ using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework.Graphics; -using StardewModdingAPI.Framework; +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; @@ -23,7 +24,7 @@ namespace StardewModdingAPI.Metadata protected readonly Func<string, string> GetNormalisedPath; /// <summary>Setters which update static or singleton texture fields indexed by normalised asset key.</summary> - private readonly IDictionary<string, Action<SContentManager, string>> SingletonSetters; + private readonly IDictionary<string, Action<LocalizedContentManager, string>> SingletonSetters; /********* @@ -31,11 +32,12 @@ namespace StardewModdingAPI.Metadata *********/ /// <summary>Initialise the core asset data.</summary> /// <param name="getNormalisedPath">Normalises an asset key to match the cache key.</param> - public CoreAssets(Func<string, string> getNormalisedPath) + /// <param name="reflection">Simplifies access to private code.</param> + public CoreAssets(Func<string, string> getNormalisedPath, Reflector reflection) { this.GetNormalisedPath = getNormalisedPath; this.SingletonSetters = - new Dictionary<string, Action<SContentManager, string>> + new Dictionary<string, Action<LocalizedContentManager, string>> { // from CraftingRecipe.InitShared ["Data\\CraftingRecipes"] = (content, key) => CraftingRecipe.craftingRecipes = content.Load<Dictionary<string, string>>(key), @@ -82,6 +84,25 @@ namespace StardewModdingAPI.Metadata // from Game1.ResetToolSpriteSheet ["TileSheets\\tools"] = (content, key) => Game1.ResetToolSpriteSheet(), +#if STARDEW_VALLEY_1_3 + // from Bush + ["TileSheets\\bushes"] = (content, key) => reflection.GetField<Lazy<Texture2D>>(typeof(Bush), "texture").SetValue(new Lazy<Texture2D>(() => content.Load<Texture2D>(key))), + + // from Farm + ["Buildings\\houses"] = (content, key) => reflection.GetField<Texture2D>(typeof(Farm), nameof(Farm.houseTextures)).SetValue(content.Load<Texture2D>(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<Texture2D>(key), @@ -107,6 +128,7 @@ namespace StardewModdingAPI.Metadata if (Game1.player != null && !Game1.player.isMale) Game1.player.FarmerRenderer = new FarmerRenderer(content.Load<Texture2D>(key)); }, +#endif // from Flooring ["TerrainFeatures\\Flooring"] = (content, key) => Flooring.floorsTexture = content.Load<Texture2D>(key), @@ -119,6 +141,26 @@ namespace StardewModdingAPI.Metadata ["TerrainFeatures\\hoeDirtDark"] = (content, key) => HoeDirt.darkTexture = content.Load<Texture2D>(key), ["TerrainFeatures\\hoeDirtSnow"] = (content, key) => HoeDirt.snowTexture = content.Load<Texture2D>(key), + // from TitleMenu + ["Minigames\\Clouds"] = (content, key) => + { + if (Game1.activeClickableMenu is TitleMenu) + reflection.GetField<Texture2D>(Game1.activeClickableMenu, "cloudsTexture").SetValue(content.Load<Texture2D>(key)); + }, + ["Minigames\\TitleButtons"] = (content, key) => + { + if (Game1.activeClickableMenu is TitleMenu titleMenu) + { + reflection.GetField<Texture2D>(titleMenu, "titleButtonsTexture").SetValue(content.Load<Texture2D>(key)); + foreach (TemporaryAnimatedSprite bird in reflection.GetField<List<TemporaryAnimatedSprite>>(titleMenu, "birds").GetValue()) +#if STARDEW_VALLEY_1_3 + bird.texture = content.Load<Texture2D>(key); +#else + bird.Texture = content.Load<Texture2D>(key); +#endif + } + }, + // from Wallpaper ["Maps\\walls_and_floors"] = (content, key) => Wallpaper.wallpaperTexture = content.Load<Texture2D>(key) } @@ -129,10 +171,10 @@ namespace StardewModdingAPI.Metadata /// <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 an asset was reloaded.</returns> - public bool ReloadForKey(SContentManager content, string key) + public bool ReloadForKey(LocalizedContentManager content, string key) { // static assets - if (this.SingletonSetters.TryGetValue(key, out Action<SContentManager, string> reload)) + if (this.SingletonSetters.TryGetValue(key, out Action<LocalizedContentManager, string> reload)) { reload(content, key); return true; @@ -144,9 +186,15 @@ namespace StardewModdingAPI.Metadata 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<Texture2D>(() => content.Load<Texture2D>(key)); +#else Texture2D texture = content.Load<Texture2D>(key); foreach (Building building in buildings) building.texture = texture; +#endif + return true; } return false; @@ -162,9 +210,11 @@ namespace StardewModdingAPI.Metadata /// <summary>Get all player-constructed buildings in the world.</summary> private IEnumerable<Building> GetAllBuildings() { - return Game1.locations - .OfType<BuildableGameLocation>() - .SelectMany(p => p.buildings); + foreach (BuildableGameLocation location in Game1.locations.OfType<BuildableGameLocation>()) + { + foreach (Building building in location.buildings) + yield return building; + } } } } diff --git a/src/SMAPI/Metadata/InstructionMetadata.cs b/src/SMAPI/Metadata/InstructionMetadata.cs index 5bb461c1..4960a458 100644 --- a/src/SMAPI/Metadata/InstructionMetadata.cs +++ b/src/SMAPI/Metadata/InstructionMetadata.cs @@ -6,6 +6,9 @@ using StardewModdingAPI.Framework.ModLoading; using StardewModdingAPI.Framework.ModLoading.Finders; using StardewModdingAPI.Framework.ModLoading.Rewriters; using StardewValley; +#if STARDEW_VALLEY_1_3 +using SObject = StardewValley.Object; +#endif namespace StardewModdingAPI.Metadata { @@ -13,6 +16,14 @@ namespace StardewModdingAPI.Metadata internal class InstructionMetadata { /********* + ** Properties + *********/ + /// <summary>The assembly names to which to heuristically detect broken references.</summary> + /// <remarks>The current implementation only works correctly with assemblies that should always be present.</remarks> + private readonly string[] ValidateReferencesToAssemblies = { "StardewModdingAPI", "Stardew Valley", "StardewValley" }; + + + /********* ** Public methods *********/ /// <summary>Get rewriters which detect or fix incompatible CIL instructions in mod assemblies.</summary> @@ -21,12 +32,40 @@ namespace StardewModdingAPI.Metadata return new IInstructionHandler[] { /**** - ** throw exception for incompatible code + ** rewrite CIL to fix incompatible code + ****/ + // rewrite for crossplatform compatibility + new MethodParentRewriter(typeof(SpriteBatch), typeof(SpriteBatchMethods), onlyIfPlatformChanged: true), + +#if !STARDEW_VALLEY_1_3 + // rewrite for Stardew Valley 1.2 + new FieldToPropertyRewriter(typeof(Game1), nameof(Game1.activeClickableMenu)), + new FieldToPropertyRewriter(typeof(Game1), nameof(Game1.currentMinigame)), + new FieldToPropertyRewriter(typeof(Game1), nameof(Game1.gameMode)), + new FieldToPropertyRewriter(typeof(Game1), nameof(Game1.player)), + new FieldReplaceRewriter(typeof(Game1), "borderFont", nameof(Game1.smallFont)), + new FieldReplaceRewriter(typeof(Game1), "smoothFont", nameof(Game1.smallFont)), + + // rewrite for SMAPI 1.9 + new TypeReferenceRewriter("StardewModdingAPI.Inheritance.ItemStackChange", typeof(ItemStackChange)), +#endif + + // rewrite for SMAPI 2.0 + new VirtualEntryCallRemover(), + + // rewrite for Stardew Valley 1.3 +#if STARDEW_VALLEY_1_3 + new StaticFieldToConstantRewriter<int>(typeof(Game1), "tileSize", Game1.tileSize), +#endif + + /**** + ** detect incompatible code ****/ - // changes in Stardew Valley 1.2 (with no rewriters) + #if !STARDEW_VALLEY_1_3 + // detect changes in Stardew Valley 1.2 new FieldFinder("StardewValley.Item", "set_Name", InstructionHandleResult.NotCompatible), - // APIs removed in SMAPI 1.9 + // detect APIs removed in SMAPI 1.9 new TypeFinder("StardewModdingAPI.Advanced.ConfigFile", InstructionHandleResult.NotCompatible), new TypeFinder("StardewModdingAPI.Advanced.IConfigFile", InstructionHandleResult.NotCompatible), new TypeFinder("StardewModdingAPI.Entities.SPlayer", InstructionHandleResult.NotCompatible), @@ -43,7 +82,7 @@ namespace StardewModdingAPI.Metadata new EventFinder("StardewModdingAPI.Events.GraphicsEvents", "OnPreRenderHudEventNoCheck", InstructionHandleResult.NotCompatible), new EventFinder("StardewModdingAPI.Events.GraphicsEvents", "OnPreRenderGuiEventNoCheck", InstructionHandleResult.NotCompatible), - // APIs removed in SMAPI 2.0 + // detect APIs removed in SMAPI 2.0 new TypeFinder("StardewModdingAPI.Command", InstructionHandleResult.NotCompatible), new TypeFinder("StardewModdingAPI.Config", InstructionHandleResult.NotCompatible), new TypeFinder("StardewModdingAPI.Log", InstructionHandleResult.NotCompatible), @@ -65,6 +104,11 @@ namespace StardewModdingAPI.Metadata new PropertyFinder("StardewModdingAPI.Mod", "BaseConfigPath", InstructionHandleResult.NotCompatible), new PropertyFinder("StardewModdingAPI.Mod", "PerSaveConfigFolder", InstructionHandleResult.NotCompatible), new PropertyFinder("StardewModdingAPI.Mod", "PerSaveConfigPath", InstructionHandleResult.NotCompatible), + #endif + + // detect broken code + new ReferenceToMissingMemberFinder(this.ValidateReferencesToAssemblies), + new ReferenceToMemberWithUnexpectedTypeFinder(this.ValidateReferencesToAssemblies), /**** ** detect code which may impact game stability @@ -74,27 +118,7 @@ namespace StardewModdingAPI.Metadata new FieldFinder(typeof(SaveGame).FullName, nameof(SaveGame.serializer), InstructionHandleResult.DetectedSaveSerialiser), new FieldFinder(typeof(SaveGame).FullName, nameof(SaveGame.farmerSerializer), InstructionHandleResult.DetectedSaveSerialiser), new FieldFinder(typeof(SaveGame).FullName, nameof(SaveGame.locationSerializer), InstructionHandleResult.DetectedSaveSerialiser), - new EventFinder(typeof(SpecialisedEvents).FullName, nameof(SpecialisedEvents.UnvalidatedUpdateTick), InstructionHandleResult.DetectedUnvalidatedUpdateTick), - - /**** - ** rewrite CIL to fix incompatible code - ****/ - // crossplatform - new MethodParentRewriter(typeof(SpriteBatch), typeof(SpriteBatchMethods), onlyIfPlatformChanged: true), - - // Stardew Valley 1.2 - new FieldToPropertyRewriter(typeof(Game1), nameof(Game1.activeClickableMenu)), - new FieldToPropertyRewriter(typeof(Game1), nameof(Game1.currentMinigame)), - new FieldToPropertyRewriter(typeof(Game1), nameof(Game1.gameMode)), - new FieldToPropertyRewriter(typeof(Game1), nameof(Game1.player)), - new FieldReplaceRewriter(typeof(Game1), "borderFont", nameof(Game1.smallFont)), - new FieldReplaceRewriter(typeof(Game1), "smoothFont", nameof(Game1.smallFont)), - - // SMAPI 1.9 - new TypeReferenceRewriter("StardewModdingAPI.Inheritance.ItemStackChange", typeof(ItemStackChange)), - - // SMAPI 2.0 - new VirtualEntryCallRemover() // Mod.Entry changed from virtual to abstract in SMAPI 2.0, which breaks the few mods which called base.Entry() + new EventFinder(typeof(SpecialisedEvents).FullName, nameof(SpecialisedEvents.UnvalidatedUpdateTick), InstructionHandleResult.DetectedUnvalidatedUpdateTick) }; } } |