From 9c1617c9ee51a0f6b93242fe8fc789336957460c Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 11 Apr 2018 21:15:16 -0400 Subject: drop support for Stardew Valley 1.2 (#453) --- src/SMAPI/Metadata/CoreAssetPropagator.cs | 47 ++----------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) (limited to 'src/SMAPI/Metadata/CoreAssetPropagator.cs') diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs index e54e0286..01ea24df 100644 --- a/src/SMAPI/Metadata/CoreAssetPropagator.cs +++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs @@ -80,17 +80,8 @@ namespace StardewModdingAPI.Metadata ** 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 false; - return farm.houseTextures = content.Load(key); - } -#endif /**** ** Content\Characters\Farmer @@ -101,20 +92,12 @@ namespace StardewModdingAPI.Metadata case "characters\\farmer\\farmer_base": // Farmer if (Game1.player == null || !Game1.player.isMale) return false; -#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 false; -#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); @@ -206,11 +189,6 @@ namespace StardewModdingAPI.Metadata /**** ** Content\Critters ****/ -#if !STARDEW_VALLEY_1_3 - case "tilesheets\\critters": // Criter.InitShared - return Critter.critterTexture = content.Load(key); -#endif - case "tilesheets\\crops": // Game1.loadContent return Game1.cropSpriteSheet = content.Load(key); @@ -265,11 +243,7 @@ namespace StardewModdingAPI.Metadata 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 false; @@ -284,12 +258,8 @@ namespace StardewModdingAPI.Metadata 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); @@ -350,7 +320,7 @@ namespace StardewModdingAPI.Metadata return this.ReloadNpcSprites(content, key, monster: true); if (key.StartsWith(this.GetNormalisedPath("LooseSprites\\Fence"), StringComparison.InvariantCultureIgnoreCase)) - return this.ReloadFenceTextures(content, key); + return this.ReloadFenceTextures(key); if (this.IsInFolder(key, "Portraits")) return this.ReloadNpcPortraits(content, key); @@ -435,21 +405,16 @@ namespace StardewModdingAPI.Metadata { Lazy texture = new Lazy(() => content.Load(key)); foreach (Building building in buildings) -#if STARDEW_VALLEY_1_3 building.texture = texture; -#else - building.texture = texture.Value; -#endif return true; } return false; } /// Reload the sprites for a fence type. - /// The content manager through which to reload the asset. /// The asset key to reload. /// Returns whether any textures were reloaded. - private bool ReloadFenceTextures(LocalizedContentManager content, string key) + private bool ReloadFenceTextures(string key) { // get fence type if (!int.TryParse(this.GetSegments(key)[1].Substring("Fence".Length), out int fenceType)) @@ -528,11 +493,7 @@ namespace StardewModdingAPI.Metadata { Lazy texture = new Lazy(() => content.Load(key)); foreach (Tree tree in trees) -#if STARDEW_VALLEY_1_3 this.Reflection.GetField>(tree, "texture").SetValue(texture); -#else - this.Reflection.GetField(tree, "texture").SetValue(texture.Value); -#endif return true; } @@ -547,11 +508,7 @@ namespace StardewModdingAPI.Metadata /// The texture to set. private void SetSpriteTexture(AnimatedSprite sprite, Texture2D texture) { -#if STARDEW_VALLEY_1_3 this.Reflection.GetField(sprite, "spriteTexture").SetValue(texture); -#else - sprite.Texture = texture; -#endif } /// Get an NPC name from the name of their file under Content/Characters. -- cgit From 5997857064f4d6bb0747e84e1dbd1556c97b7481 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 12 Apr 2018 00:18:32 -0400 Subject: fix various net field conversions in SMAPI code (#453) --- src/SMAPI/Context.cs | 2 +- src/SMAPI/Framework/SGame.cs | 7 ++++--- src/SMAPI/Metadata/CoreAssetPropagator.cs | 27 ++++++++++++++------------- src/SMAPI/StardewModdingAPI.csproj | 3 +++ 4 files changed, 22 insertions(+), 17 deletions(-) (limited to 'src/SMAPI/Metadata/CoreAssetPropagator.cs') diff --git a/src/SMAPI/Context.cs b/src/SMAPI/Context.cs index 7ed9b052..79067b2d 100644 --- a/src/SMAPI/Context.cs +++ b/src/SMAPI/Context.cs @@ -35,7 +35,7 @@ namespace StardewModdingAPI ** Internal ****/ /// Whether a player save has been loaded. - internal static bool IsSaveLoaded => Game1.hasLoadedGame && !string.IsNullOrEmpty(Game1.player.name); + internal static bool IsSaveLoaded => Game1.hasLoadedGame && !string.IsNullOrEmpty(Game1.player.Name); /// Whether the game is currently writing to the save file. internal static bool IsSaving => Game1.activeClickableMenu is SaveGameMenu || Game1.activeClickableMenu is ShippingMenu; // saving is performed by SaveGameMenu, but it's wrapped by ShippingMenu on days when the player shipping something diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index b486f8cd..67390882 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -500,9 +500,9 @@ namespace StardewModdingAPI.Framework this.Events.Player_LeveledUp.Raise(new EventArgsLevelUp(EventArgsLevelUp.LevelType.Luck, Game1.player.luckLevel)); // raise player inventory changed - ItemStackChange[] changedItems = this.GetInventoryChanges(Game1.player.items, this.PreviousItems).ToArray(); + ItemStackChange[] changedItems = this.GetInventoryChanges(Game1.player.Items, this.PreviousItems).ToArray(); if (changedItems.Any()) - this.Events.Player_InventoryChanged.Raise(new EventArgsInventoryChanged(Game1.player.items, changedItems.ToList())); + this.Events.Player_InventoryChanged.Raise(new EventArgsInventoryChanged(Game1.player.Items, changedItems.ToList())); // raise current location's object list changed if (this.GetHash(Game1.currentLocation.objects) != this.PreviousLocationObjects) @@ -526,7 +526,7 @@ namespace StardewModdingAPI.Framework this.PreviousForagingLevel = Game1.player.foragingLevel; this.PreviousMiningLevel = Game1.player.miningLevel; this.PreviousLuckLevel = Game1.player.luckLevel; - this.PreviousItems = Game1.player.items.Where(n => n != null).Distinct().ToDictionary(n => n, n => n.Stack); + this.PreviousItems = Game1.player.Items.Where(n => n != null).Distinct().ToDictionary(n => n, n => n.Stack); this.PreviousLocationObjects = this.GetHash(Game1.currentLocation.objects); this.PreviousTime = Game1.timeOfDay; this.PreviousMineLevel = Game1.mine?.mineLevel ?? 0; @@ -633,6 +633,7 @@ namespace StardewModdingAPI.Framework [SuppressMessage("ReSharper", "RedundantCast", Justification = "copied from game code as-is")] [SuppressMessage("ReSharper", "RedundantExplicitNullableCreation", Justification = "copied from game code as-is")] [SuppressMessage("ReSharper", "RedundantTypeArgumentsOfMethod", Justification = "copied from game code as-is")] + [SuppressMessage("SMAPI.CommonErrors", "SMAPI002", Justification = "copied from game code as-is")] private void DrawImpl(GameTime gameTime) { if (Game1.debugMode) diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs index 01ea24df..37623f32 100644 --- a/src/SMAPI/Metadata/CoreAssetPropagator.cs +++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs @@ -90,12 +90,12 @@ namespace StardewModdingAPI.Metadata return FarmerRenderer.accessoriesTexture = content.Load(key); case "characters\\farmer\\farmer_base": // Farmer - if (Game1.player == null || !Game1.player.isMale) + if (Game1.player == null || !Game1.player.IsMale) return false; return Game1.player.FarmerRenderer = new FarmerRenderer(key); case "characters\\farmer\\farmer_girl_base": // Farmer - if (Game1.player == null || Game1.player.isMale) + if (Game1.player == null || Game1.player.IsMale) return false; return Game1.player.FarmerRenderer = new FarmerRenderer(key); @@ -372,16 +372,16 @@ namespace StardewModdingAPI.Metadata foreach (FarmAnimal animal in animals) { // get expected key - string expectedKey = animal.age < animal.ageWhenMature - ? $"Baby{(animal.type == "Duck" ? "White Chicken" : animal.type)}" + string expectedKey = animal.age.Value < animal.ageWhenMature.Value + ? $"Baby{(animal.type.Value == "Duck" ? "White Chicken" : animal.type.Value)}" : animal.type; - if (animal.showDifferentTextureWhenReadyForHarvest && animal.currentProduce <= 0) + if (animal.showDifferentTextureWhenReadyForHarvest && animal.currentProduce.Value <= 0) expectedKey = $"Sheared{expectedKey}"; expectedKey = $"Animals\\{expectedKey}"; // reload asset if (expectedKey == key) - this.SetSpriteTexture(animal.sprite, texture.Value); + this.SetSpriteTexture(animal.Sprite, texture.Value); } return texture.IsValueCreated; } @@ -397,7 +397,7 @@ namespace StardewModdingAPI.Metadata Building[] buildings = Game1.locations .OfType() .SelectMany(p => p.buildings) - .Where(p => p.buildingType == type) + .Where(p => p.buildingType.Value == type) .ToArray(); // reload buildings @@ -427,7 +427,7 @@ namespace StardewModdingAPI.Metadata from fence in location.Objects.Values.OfType() where fenceType == 1 ? fence.isGate - : fence.whichType == fenceType + : fence.whichType.Value == fenceType select fence ) .ToArray(); @@ -447,7 +447,7 @@ namespace StardewModdingAPI.Metadata { // get NPCs string name = this.GetNpcNameFromFileName(Path.GetFileName(key)); - NPC[] characters = this.GetCharacters().Where(npc => npc.name == name && npc.IsMonster == monster).ToArray(); + NPC[] characters = this.GetCharacters().Where(npc => npc.Name == name && npc.IsMonster == monster).ToArray(); if (!characters.Any()) return false; @@ -466,7 +466,7 @@ namespace StardewModdingAPI.Metadata { // get NPCs string name = this.GetNpcNameFromFileName(Path.GetFileName(key)); - NPC[] villagers = this.GetCharacters().Where(npc => npc.name == name && npc.isVillager()).ToArray(); + NPC[] villagers = this.GetCharacters().Where(npc => npc.Name == name && npc.isVillager()).ToArray(); if (!villagers.Any()) return false; @@ -486,7 +486,7 @@ namespace StardewModdingAPI.Metadata { Tree[] trees = Game1.locations .SelectMany(p => p.terrainFeatures.Values.OfType()) - .Where(tree => tree.treeType == type) + .Where(tree => tree.treeType.Value == type) .ToArray(); if (trees.Any()) @@ -562,8 +562,9 @@ namespace StardewModdingAPI.Metadata { foreach (Building building in buildableLocation.buildings) { - if (building.indoors != null) - yield return building.indoors; + GameLocation indoors = building.indoors; + if (indoors != null) + yield return indoors; } } } diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj index cf476193..c0d5386a 100644 --- a/src/SMAPI/StardewModdingAPI.csproj +++ b/src/SMAPI/StardewModdingAPI.csproj @@ -288,6 +288,9 @@ StardewModdingAPI.AssemblyRewriters + + + \ No newline at end of file -- cgit From ff571701b21f1f1a0f5c914bdb756312f07fb134 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 25 Apr 2018 19:24:55 -0400 Subject: fix a few implicit net field conversions (#453) --- src/SMAPI/Metadata/CoreAssetPropagator.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/SMAPI/Metadata/CoreAssetPropagator.cs') diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs index 37623f32..f057eebe 100644 --- a/src/SMAPI/Metadata/CoreAssetPropagator.cs +++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs @@ -351,7 +351,7 @@ namespace StardewModdingAPI.Metadata // update sprites Texture2D texture = content.Load(key); foreach (TAnimal animal in animals) - this.SetSpriteTexture(animal.sprite, texture); + this.SetSpriteTexture(animal.Sprite, texture); return true; } @@ -374,8 +374,8 @@ namespace StardewModdingAPI.Metadata // get expected key string expectedKey = animal.age.Value < animal.ageWhenMature.Value ? $"Baby{(animal.type.Value == "Duck" ? "White Chicken" : animal.type.Value)}" - : animal.type; - if (animal.showDifferentTextureWhenReadyForHarvest && animal.currentProduce.Value <= 0) + : animal.type.Value; + if (animal.showDifferentTextureWhenReadyForHarvest.Value && animal.currentProduce.Value <= 0) expectedKey = $"Sheared{expectedKey}"; expectedKey = $"Animals\\{expectedKey}"; @@ -426,7 +426,7 @@ namespace StardewModdingAPI.Metadata from location in this.GetLocations() from fence in location.Objects.Values.OfType() where fenceType == 1 - ? fence.isGate + ? fence.isGate.Value : fence.whichType.Value == fenceType select fence ) @@ -562,7 +562,7 @@ namespace StardewModdingAPI.Metadata { foreach (Building building in buildableLocation.buildings) { - GameLocation indoors = building.indoors; + GameLocation indoors = building.indoors.Value; if (indoors != null) yield return indoors; } -- cgit From 591b1aca780b4460c7845534eb624697025b891e Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 5 May 2018 22:20:15 -0400 Subject: update fence asset propagation in SDV 1.3 --- src/SMAPI/Metadata/CoreAssetPropagator.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src/SMAPI/Metadata/CoreAssetPropagator.cs') diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs index f057eebe..7ca0bd82 100644 --- a/src/SMAPI/Metadata/CoreAssetPropagator.cs +++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs @@ -320,7 +320,7 @@ namespace StardewModdingAPI.Metadata return this.ReloadNpcSprites(content, key, monster: true); if (key.StartsWith(this.GetNormalisedPath("LooseSprites\\Fence"), StringComparison.InvariantCultureIgnoreCase)) - return this.ReloadFenceTextures(key); + return this.ReloadFenceTextures(content, key); if (this.IsInFolder(key, "Portraits")) return this.ReloadNpcPortraits(content, key); @@ -412,9 +412,10 @@ namespace StardewModdingAPI.Metadata } /// Reload the sprites for a fence type. + /// The content manager through which to reload the asset. /// The asset key to reload. /// Returns whether any textures were reloaded. - private bool ReloadFenceTextures(string key) + private bool ReloadFenceTextures(LocalizedContentManager content, string key) { // get fence type if (!int.TryParse(this.GetSegments(key)[1].Substring("Fence".Length), out int fenceType)) @@ -425,16 +426,16 @@ namespace StardewModdingAPI.Metadata ( from location in this.GetLocations() from fence in location.Objects.Values.OfType() - where fenceType == 1 - ? fence.isGate.Value - : fence.whichType.Value == fenceType + where + fence.whichType.Value == fenceType + || (fence.isGate.Value && fenceType == 1) // gates are hardcoded to draw fence type 1 select fence ) .ToArray(); // update fence textures foreach (Fence fence in fences) - fence.reloadSprite(); + this.Reflection.GetField>(fence, "fenceTexture").SetValue(new Lazy(fence.loadFenceTexture)); return true; } -- cgit From d8ee422405614a9b5d56ae0f42a003835fc57a8c Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 1 Jul 2018 17:37:19 -0400 Subject: add support for reloading NPC schedules through the content API --- docs/release-notes.md | 1 + src/SMAPI/Metadata/CoreAssetPropagator.cs | 38 ++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'src/SMAPI/Metadata/CoreAssetPropagator.cs') diff --git a/docs/release-notes.md b/docs/release-notes.md index ae078e20..bbf04556 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -48,6 +48,7 @@ * Added option to suppress update checks for a specific mod in `StardewModdingAPI.config.json`. * Added absolute pixels to `ICursorPosition`. * Added support for reading/writing `ISemanticVersion` to JSON. + * Added support for reloading NPC schedules through the content API. * Improved update alerts to use update key order when choosing a display URL. * Fixed assets loaded by temporary content managers not being editable by mods. * Fixed assets not reloaded consistently when the player switches language. diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs index 7ca0bd82..12abeb10 100644 --- a/src/SMAPI/Metadata/CoreAssetPropagator.cs +++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs @@ -325,6 +325,10 @@ namespace StardewModdingAPI.Metadata if (this.IsInFolder(key, "Portraits")) return this.ReloadNpcPortraits(content, key); + // dynamic data + if (this.IsInFolder(key, "Characters\\schedules")) + return this.ReloadNpcSchedules(content, key); + return false; } @@ -333,7 +337,7 @@ namespace StardewModdingAPI.Metadata ** Private methods *********/ /**** - ** Reload methods + ** Reload texture methods ****/ /// Reload the sprites for matching pets or horses. /// The animal type. @@ -501,6 +505,38 @@ namespace StardewModdingAPI.Metadata return false; } + /**** + ** Reload data methods + ****/ + /// Reload the schedules for matching NPCs. + /// The content manager through which to reload the asset. + /// The asset key to reload. + /// Returns whether any assets were reloaded. + private bool ReloadNpcSchedules(LocalizedContentManager content, string key) + { + // get NPCs + string name = Path.GetFileName(key); + NPC[] villagers = this.GetCharacters().Where(npc => npc.Name == name && npc.isVillager()).ToArray(); + if (!villagers.Any()) + return false; + + // update schedule + foreach (NPC villager in villagers) + { + // reload schedule + villager.Schedule = villager.getSchedule(Game1.dayOfMonth); + + // switch to new schedule if needed + int lastScheduleTime = villager.Schedule.Keys.Where(p => p <= Game1.timeOfDay).OrderByDescending(p => p).FirstOrDefault(); + if (lastScheduleTime != 0) + { + this.Reflection.GetField(villager, "scheduleTimeToTry").SetValue(this.Reflection.GetField(typeof(NPC), "NO_TRY").GetValue()); // use time that's passed in to checkSchedule + villager.checkSchedule(lastScheduleTime); + } + } + return true; + } + /**** ** Helpers ****/ -- cgit