From 431bbcffb57d499b1baccfd4ff494ab116e4acd5 Mon Sep 17 00:00:00 2001 From: Matthew <3005344+LeFauxMatt@users.noreply.github.com> Date: Wed, 22 Jan 2025 23:17:57 -0800 Subject: [PATCH 1/2] api changes for custom bush 2.0 --- Common/Common.projitems | 2 ++ .../CustomBush/CustomBushIntegration.cs | 27 +++++++++++++++- .../Integrations/CustomBush/CustomBushType.cs | 22 +++++++++++++ Common/Integrations/CustomBush/ICustomBush.cs | 32 +++++++++++++------ .../Integrations/CustomBush/ICustomBushApi.cs | 25 ++++++--------- .../CustomBush/ICustomBushDrop.cs | 9 ++++-- .../CustomBush/ICustomBushDrops.cs | 8 +++++ .../Lookups/TerrainFeatures/BushSubject.cs | 30 ++++++----------- 8 files changed, 104 insertions(+), 51 deletions(-) create mode 100644 Common/Integrations/CustomBush/CustomBushType.cs create mode 100644 Common/Integrations/CustomBush/ICustomBushDrops.cs diff --git a/Common/Common.projitems b/Common/Common.projitems index 2676c68ef..41486721d 100644 --- a/Common/Common.projitems +++ b/Common/Common.projitems @@ -28,9 +28,11 @@ + + diff --git a/Common/Integrations/CustomBush/CustomBushIntegration.cs b/Common/Integrations/CustomBush/CustomBushIntegration.cs index cc49a02da..38deb4354 100644 --- a/Common/Integrations/CustomBush/CustomBushIntegration.cs +++ b/Common/Integrations/CustomBush/CustomBushIntegration.cs @@ -1,4 +1,7 @@ +using Microsoft.Xna.Framework.Graphics; +using System.Diagnostics.CodeAnalysis; using StardewModdingAPI; +using StardewValley.TerrainFeatures; namespace Pathoschild.Stardew.Common.Integrations.CustomBush; @@ -12,5 +15,27 @@ internal class CustomBushIntegration : BaseIntegration /// An API for fetching metadata about loaded mods. /// Encapsulates monitoring and logging. public CustomBushIntegration(IModRegistry modRegistry, IMonitor monitor) - : base("CustomBush", "furyx639.CustomBush", "1.2.0", modRegistry, monitor) { } + : base("CustomBush", "furyx639.CustomBush", "2.0.0-beta.1", modRegistry, monitor) { } + + /// Try to get the custom bush model associated with the given bush. + /// The bush to check. + /// The resulting custom bush, if applicable. + /// True if the custom bush associated with the given bush is found. + public bool TryGetBush(Bush bush, [NotNullWhen(true)] out ICustomBush? customBush) + { + customBush = null; + + return this.IsLoaded && this.ModApi.TryGetBush(bush, out customBush); + } + + /// Try to get the currently relevant texture for the given bush. + /// The bush. + /// The bush's texture. + /// True if a custom bush is associated with the given bush and a texture is found. + public bool TryGetTexture(Bush bush, [NotNullWhen(true)] out Texture2D? texture) + { + texture = null; + + return this.IsLoaded && this.ModApi.TryGetTexture(bush, out texture); + } } diff --git a/Common/Integrations/CustomBush/CustomBushType.cs b/Common/Integrations/CustomBush/CustomBushType.cs new file mode 100644 index 000000000..3239363b8 --- /dev/null +++ b/Common/Integrations/CustomBush/CustomBushType.cs @@ -0,0 +1,22 @@ +using StardewValley.TerrainFeatures; + +namespace Pathoschild.Stardew.Common.Integrations.CustomBush; + +/// Represents the bush types. +public enum CustomBushType +{ + /// Small bush + Small = Bush.smallBush, + + /// Medium bush + Medium = Bush.mediumBush, + + /// Large bush + Large = Bush.largeBush, + + /// Tea bush + Tea = Bush.greenTeaBush, + + /// Walnut bush + Walnut = Bush.walnutBush +} diff --git a/Common/Integrations/CustomBush/ICustomBush.cs b/Common/Integrations/CustomBush/ICustomBush.cs index 76dfca923..dbf6b2c34 100644 --- a/Common/Integrations/CustomBush/ICustomBush.cs +++ b/Common/Integrations/CustomBush/ICustomBush.cs @@ -8,29 +8,41 @@ namespace Pathoschild.Stardew.Common.Integrations.CustomBush; public interface ICustomBush { /// Gets the age needed to produce. - int AgeToProduce { get; } + public int AgeToProduce { get; } + + /// Gets the busy type. + public CustomBushType BushType { get; } + + /// Gets a list of conditions where any have to match for the bush to produce items. + public List ConditionsToProduce { get; } /// Gets the day of month to begin producing. - int DayToBeginProducing { get; } + public int DayToBeginProducing { get; } /// Gets the description of the bush. - string Description { get; } + public string Description { get; } /// Gets the display name of the bush. - string DisplayName { get; } + public string DisplayName { get; } + + /// Gets a unique identifier for the custom bush. + public string Id { get; } /// Gets the default texture used when planted indoors. - string IndoorTexture { get; } + public string IndoorTexture { get; } - /// Gets the season in which this bush will produce its drops. - List Seasons { get; } + /// Gets or sets the items produced by this custom bush. + public ICustomBushDrops ItemsProduced { get; } /// Gets the rules which override the locations that custom bushes can be planted in. - List PlantableLocationRules { get; } + public List PlantableLocationRules { get; } + + /// Gets the season in which this bush will produce its drops. + public List Seasons { get; } /// Gets the texture of the tea bush. - string Texture { get; } + public string Texture { get; } /// Gets the row index for the custom bush's sprites. - int TextureSpriteRow { get; } + public int TextureSpriteRow { get; } } diff --git a/Common/Integrations/CustomBush/ICustomBushApi.cs b/Common/Integrations/CustomBush/ICustomBushApi.cs index 8fc6891c9..709b3ea35 100644 --- a/Common/Integrations/CustomBush/ICustomBushApi.cs +++ b/Common/Integrations/CustomBush/ICustomBushApi.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using Microsoft.Xna.Framework.Graphics; using StardewValley.TerrainFeatures; namespace Pathoschild.Stardew.Common.Integrations.CustomBush; @@ -9,21 +9,14 @@ namespace Pathoschild.Stardew.Common.Integrations.CustomBush; public interface ICustomBushApi { /// Try to get the custom bush model associated with the given bush. - /// The bush. - /// When this method returns, contains the custom bush associated with the given bush, if found; otherwise, it contains null. - /// True if the custom bush associated with the given bush is found; otherwise, false. - bool TryGetCustomBush(Bush bush, out ICustomBush? customBush); + /// The bush to check. + /// The resulting custom bush, if applicable. + /// Returns whether a custom bush was found. + bool TryGetBush(Bush bush, [NotNullWhen(true)] out ICustomBush? customBush); - /// Try to get the custom bush model and id associated with the given bush. + /// Try to get the currently relevant texture for the given bush. /// The bush. - /// When this method returns, contains the custom bush associated with the given bush, if found; otherwise, it contains null. - /// The internal bush ID. - /// True if the custom bush associated with the given bush is found; otherwise, false. - bool TryGetCustomBush(Bush bush, out ICustomBush? customBush, [NotNullWhen(true)] out string? id); - - /// Try to get the custom bush drop associated with the given bush id. - /// The id of the bush. - /// When this method returns, contains the items produced by the custom bush. - /// True if the drops associated with the given id is found; otherwise, false. - bool TryGetDrops(string id, [NotNullWhen(true)] out IList? drops); + /// The bush's texture. + /// True if a custom bush is associated with the given bush and a texture is found. + bool TryGetTexture(Bush bush, [NotNullWhen(true)] out Texture2D? texture); } diff --git a/Common/Integrations/CustomBush/ICustomBushDrop.cs b/Common/Integrations/CustomBush/ICustomBushDrop.cs index 5326eca16..2fed0bbe0 100644 --- a/Common/Integrations/CustomBush/ICustomBushDrop.cs +++ b/Common/Integrations/CustomBush/ICustomBushDrop.cs @@ -6,9 +6,6 @@ namespace Pathoschild.Stardew.Common.Integrations.CustomBush; /// An item produced by a Custom Bush bush. public interface ICustomBushDrop : ISpawnItemData { - /// Gets the specific season when the item can be produced. - Season? Season { get; } - /// Gets the probability that the item will be produced. float Chance { get; } @@ -17,4 +14,10 @@ public interface ICustomBushDrop : ISpawnItemData /// An ID for this entry within the current list (not the item itself, which is ). This only needs to be unique within the current list. For a custom entry, you should use a globally unique ID which includes your mod ID like ExampleMod.Id_ItemName. string? Id { get; } + + /// Gets the specific season when the item can be produced. + Season? Season { get; } + + /// Gets or sets an offset to the texture sprite which the item is produced. + public int SpriteOffset { get; } } diff --git a/Common/Integrations/CustomBush/ICustomBushDrops.cs b/Common/Integrations/CustomBush/ICustomBushDrops.cs new file mode 100644 index 000000000..f35b8f5b0 --- /dev/null +++ b/Common/Integrations/CustomBush/ICustomBushDrops.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Pathoschild.Stardew.Common.Integrations.CustomBush; + +/// Model used for the collection of custom bush drops. +public interface ICustomBushDrops : IList +{ +} diff --git a/LookupAnything/Framework/Lookups/TerrainFeatures/BushSubject.cs b/LookupAnything/Framework/Lookups/TerrainFeatures/BushSubject.cs index 6e6322fd8..a11cdd65a 100644 --- a/LookupAnything/Framework/Lookups/TerrainFeatures/BushSubject.cs +++ b/LookupAnything/Framework/Lookups/TerrainFeatures/BushSubject.cs @@ -89,7 +89,7 @@ public override IEnumerable GetData() string nextHarvestStr = nextHarvest == today ? I18n.Generic_Now() : $"{this.Stringify(nextHarvest)} ({this.GetRelativeDateStr(nextHarvest)})"; - if (this.TryGetCustomBushDrops(bush, out IList? drops)) + if (this.TryGetCustomBushDrops(bush, out List? drops)) yield return new ItemDropListField(this.GameHelper, I18n.Bush_NextHarvest(), drops, preface: nextHarvestStr); else { @@ -146,14 +146,7 @@ public override bool DrawPortrait(SpriteBatch spriteBatch, Vector2 position, Vec Vector2 offset = new Vector2(size.X - targetSize.X, size.Y - targetSize.Y) / 2; // get texture - Texture2D texture; - if (this.TryGetCustomBush(bush, out ICustomBush? customBush)) - { - texture = bush.IsSheltered() - ? Game1.content.Load(customBush.IndoorTexture) - : Game1.content.Load(customBush.Texture); - } - else + if (!this.GameHelper.CustomBush.TryGetTexture(bush, out Texture2D? texture)) texture = Bush.texture.Value; // draw portrait @@ -194,27 +187,22 @@ private bool IsTeaBush(Bush bush) /// Returns whether a custom bush was found. private bool TryGetCustomBush(Bush bush, [NotNullWhen(true)] out ICustomBush? customBush) { - customBush = null; - return - this.GameHelper.CustomBush.IsLoaded - && this.GameHelper.CustomBush.ModApi.TryGetCustomBush(bush, out customBush); + return this.GameHelper.CustomBush.TryGetBush(bush, out customBush); } /// Get bush drops from the Custom Bush mod if applicable. /// The bush to check. /// The items produced by the custom bush, if applicable. /// Returns whether custom bush drops were found. - private bool TryGetCustomBushDrops(Bush bush, [NotNullWhen(true)] out IList? drops) + private bool TryGetCustomBushDrops(Bush bush, [NotNullWhen(true)] out List? drops) { - CustomBushIntegration customBush = this.GameHelper.CustomBush; - - if (customBush.IsLoaded && customBush.ModApi.TryGetCustomBush(bush, out _, out string? id) && customBush.ModApi.TryGetDrops(id, out IList? rawDrops)) + if (this.GameHelper.CustomBush.TryGetBush(bush, out ICustomBush? customBush)) { - drops = new List(rawDrops.Count); - - foreach (ICustomBushDrop drop in rawDrops) + drops = new List(customBush.ItemsProduced.Count); + foreach (var drop in customBush.ItemsProduced) + { drops.Add(new ItemDropData(drop.ItemId, drop.MinStack, drop.MaxStack, drop.Chance, drop.Condition)); - + } return true; } From 3bb5988fdc82d17e6439da2ca6787093511aaf76 Mon Sep 17 00:00:00 2001 From: Matthew <3005344+LeFauxMatt@users.noreply.github.com> Date: Sat, 25 Jan 2025 00:00:33 -0800 Subject: [PATCH 2/2] Enhance custom bush integration with new interfaces Added several new interfaces for custom bush data, drops, progress rules, and stages to improve the structure and functionality of the custom bush system. Updated `CustomBushIntegration.cs` to remove the old texture retrieval method and utilize the new data structures. Modified the `ICustomBush` and `ICustomBushApi` interfaces to reflect a more data-driven approach, introducing new properties and methods. Updated the `BushSubject` class to access and display custom bush information using the new structures, enhancing modularity and maintainability. --- Common/Common.projitems | 5 ++ .../CustomBush/CustomBushIntegration.cs | 11 ---- Common/Integrations/CustomBush/ICustomBush.cs | 62 ++++++++++--------- .../Integrations/CustomBush/ICustomBushApi.cs | 22 ++++--- .../CustomBush/ICustomBushData.cs | 38 ++++++++++++ .../CustomBush/ICustomBushDrop.cs | 24 ++++--- .../CustomBush/ICustomBushProgressRule.cs | 21 +++++++ .../CustomBush/ICustomBushProgressRules.cs | 12 ++++ .../CustomBush/ICustomBushStage.cs | 28 +++++++++ .../CustomBush/ICustomBushStages.cs | 11 ++++ .../Lookups/TerrainFeatures/BushSubject.cs | 23 ++++--- 11 files changed, 188 insertions(+), 69 deletions(-) create mode 100644 Common/Integrations/CustomBush/ICustomBushData.cs create mode 100644 Common/Integrations/CustomBush/ICustomBushProgressRule.cs create mode 100644 Common/Integrations/CustomBush/ICustomBushProgressRules.cs create mode 100644 Common/Integrations/CustomBush/ICustomBushStage.cs create mode 100644 Common/Integrations/CustomBush/ICustomBushStages.cs diff --git a/Common/Common.projitems b/Common/Common.projitems index 41486721d..22229437e 100644 --- a/Common/Common.projitems +++ b/Common/Common.projitems @@ -31,8 +31,13 @@ + + + + + diff --git a/Common/Integrations/CustomBush/CustomBushIntegration.cs b/Common/Integrations/CustomBush/CustomBushIntegration.cs index 38deb4354..03c5613b5 100644 --- a/Common/Integrations/CustomBush/CustomBushIntegration.cs +++ b/Common/Integrations/CustomBush/CustomBushIntegration.cs @@ -27,15 +27,4 @@ public bool TryGetBush(Bush bush, [NotNullWhen(true)] out ICustomBush? customBus return this.IsLoaded && this.ModApi.TryGetBush(bush, out customBush); } - - /// Try to get the currently relevant texture for the given bush. - /// The bush. - /// The bush's texture. - /// True if a custom bush is associated with the given bush and a texture is found. - public bool TryGetTexture(Bush bush, [NotNullWhen(true)] out Texture2D? texture) - { - texture = null; - - return this.IsLoaded && this.ModApi.TryGetTexture(bush, out texture); - } } diff --git a/Common/Integrations/CustomBush/ICustomBush.cs b/Common/Integrations/CustomBush/ICustomBush.cs index dbf6b2c34..ce5fac8b0 100644 --- a/Common/Integrations/CustomBush/ICustomBush.cs +++ b/Common/Integrations/CustomBush/ICustomBush.cs @@ -1,48 +1,50 @@ -using System.Collections.Generic; +using Microsoft.Xna.Framework.Graphics; +using System.Diagnostics.CodeAnalysis; using StardewValley; -using StardewValley.GameData; namespace Pathoschild.Stardew.Common.Integrations.CustomBush; -/// Model used for custom bushes. +/// Represents a distinct instance of a custom bush. public interface ICustomBush { - /// Gets the age needed to produce. - public int AgeToProduce { get; } + /// Gets the condition pertaining to the bush's current season. + public string? Condition { get; } - /// Gets the busy type. - public CustomBushType BushType { get; } + /// Gets the bush data. + public ICustomBushData Data { get; } - /// Gets a list of conditions where any have to match for the bush to produce items. - public List ConditionsToProduce { get; } - - /// Gets the day of month to begin producing. - public int DayToBeginProducing { get; } + /// Gets the custom bush's id. + public string Id { get; } - /// Gets the description of the bush. - public string Description { get; } + /// Gets a value indicating whether the bush is in season. + public bool IsInSeason { get; } - /// Gets the display name of the bush. - public string DisplayName { get; } + /// Gets the current shake off item (if any). + public Item? Item { get; } - /// Gets a unique identifier for the custom bush. - public string Id { get; } + /// Gets an offset to the bush sprite. + public int SpriteOffset { get; } - /// Gets the default texture used when planted indoors. - public string IndoorTexture { get; } + /// Gets the current bush stage. + public ICustomBushStage Stage { get; } - /// Gets or sets the items produced by this custom bush. - public ICustomBushDrops ItemsProduced { get; } + /// Gets the number of counted days in the stage. + public int StageCounter { get; } - /// Gets the rules which override the locations that custom bushes can be planted in. - public List PlantableLocationRules { get; } + /// Gets the bush's stage id. + public string StageId { get; } - /// Gets the season in which this bush will produce its drops. - public List Seasons { get; } + /// Gets the bush's texture. + public Texture2D Texture { get; } - /// Gets the texture of the tea bush. - public string Texture { get; } + /// Tests a Game State Query condition, passing the relevant parameters. + /// The condition to test. + /// True if the condition is null or empty, or if the condition passes. + bool TestCondition(string? condition); - /// Gets the row index for the custom bush's sprites. - public int TextureSpriteRow { get; } + /// Try to produce an item drop. + /// The drop to produce. + /// The item produced from the drop. + /// True if the drop could be produced. + bool TryProduceDrop(ICustomBushDrop drop, [NotNullWhen(true)] out Item? item); } diff --git a/Common/Integrations/CustomBush/ICustomBushApi.cs b/Common/Integrations/CustomBush/ICustomBushApi.cs index 709b3ea35..3030b9545 100644 --- a/Common/Integrations/CustomBush/ICustomBushApi.cs +++ b/Common/Integrations/CustomBush/ICustomBushApi.cs @@ -1,5 +1,4 @@ using System.Diagnostics.CodeAnalysis; -using Microsoft.Xna.Framework.Graphics; using StardewValley.TerrainFeatures; namespace Pathoschild.Stardew.Common.Integrations.CustomBush; @@ -8,15 +7,20 @@ namespace Pathoschild.Stardew.Common.Integrations.CustomBush; [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "The naming convention is defined by the Custom Bush mod.")] public interface ICustomBushApi { - /// Try to get the custom bush model associated with the given bush. + /// Determine if the bush is a custom bush. + /// The bush to check. + /// True if the bush is a custom bush. + public bool IsCustomBush(Bush bush); + + /// Try to get the custom bush instance associated with the given bush. /// The bush to check. /// The resulting custom bush, if applicable. - /// Returns whether a custom bush was found. - bool TryGetBush(Bush bush, [NotNullWhen(true)] out ICustomBush? customBush); + /// True if a custom bush was found. + public bool TryGetBush(Bush bush, [NotNullWhen(true)] out ICustomBush? customBush); - /// Try to get the currently relevant texture for the given bush. - /// The bush. - /// The bush's texture. - /// True if a custom bush is associated with the given bush and a texture is found. - bool TryGetTexture(Bush bush, [NotNullWhen(true)] out Texture2D? texture); + /// Try to get the custom bush model associated with the given bush. + /// The bush to check. + /// The resulting custom bush, if applicable. + /// True if a custom bush was found. + public bool TryGetData(Bush bush, [NotNullWhen(true)] out ICustomBushData? customBushData); } diff --git a/Common/Integrations/CustomBush/ICustomBushData.cs b/Common/Integrations/CustomBush/ICustomBushData.cs new file mode 100644 index 000000000..4bd2ed685 --- /dev/null +++ b/Common/Integrations/CustomBush/ICustomBushData.cs @@ -0,0 +1,38 @@ +using StardewValley; +using StardewValley.GameData; +using System.Collections.Generic; + +namespace Pathoschild.Stardew.Common.Integrations.CustomBush; + +/// Model used for custom bush data. +public interface ICustomBushData +{ + /// Gets a list of conditions where any have to match for the bush to produce items. + public List ConditionsToProduce { get; } + + /// Gets the description of the bush. + public string Description { get; } + + /// Gets the display name of the bush. + public string DisplayName { get; } + + /// Gets a unique identifier for the custom bush. + public string Id { get; } + + /// Gets the initial bush stage. + public string InitialStage { get; } + + /// Gets the rules which override the locations that custom bushes can be planted in. + public List PlantableLocationRules { get; } + + /// Gets all the growth stages. + public ICustomBushStages Stages { get; } + + /// Try to get the age to mature. + /// The age in which will return true; otherwise, 0. + public int GetAgeToMature(); + + /// Try to get the seasons. + /// The seasons in which will return true. + public List GetSeasons(); +} diff --git a/Common/Integrations/CustomBush/ICustomBushDrop.cs b/Common/Integrations/CustomBush/ICustomBushDrop.cs index 2fed0bbe0..cc908091b 100644 --- a/Common/Integrations/CustomBush/ICustomBushDrop.cs +++ b/Common/Integrations/CustomBush/ICustomBushDrop.cs @@ -1,4 +1,3 @@ -using StardewValley; using StardewValley.GameData; namespace Pathoschild.Stardew.Common.Integrations.CustomBush; @@ -6,18 +5,23 @@ namespace Pathoschild.Stardew.Common.Integrations.CustomBush; /// An item produced by a Custom Bush bush. public interface ICustomBushDrop : ISpawnItemData { - /// Gets the probability that the item will be produced. - float Chance { get; } - /// A game state query which indicates whether the item should be added. Defaults to always added. - string? Condition { get; } + public string? Condition { get; } - /// An ID for this entry within the current list (not the item itself, which is ). This only needs to be unique within the current list. For a custom entry, you should use a globally unique ID which includes your mod ID like ExampleMod.Id_ItemName. - string? Id { get; } + /// Gets a unique ID for this entry within the current list. + public string? Id { get; } - /// Gets the specific season when the item can be produced. - Season? Season { get; } + /// Gets a value indicating whether the drop can replace an existing item. + public bool ReplaceItem { get; } - /// Gets or sets an offset to the texture sprite which the item is produced. + /// Gets an offset to the bush sprite when this item is produced. public int SpriteOffset { get; } + + /// Try to get the chance for the drop based on its condition. + /// Returns the chance of the drop being produced. + public float GetChance(); + + /// Try to get the earliest day for the drop based on its condition. + /// Returns the first day of the drop being produced. + public int GetDay(); } diff --git a/Common/Integrations/CustomBush/ICustomBushProgressRule.cs b/Common/Integrations/CustomBush/ICustomBushProgressRule.cs new file mode 100644 index 000000000..a0a294357 --- /dev/null +++ b/Common/Integrations/CustomBush/ICustomBushProgressRule.cs @@ -0,0 +1,21 @@ +namespace Pathoschild.Stardew.Common.Integrations.CustomBush; + +/// Represents rules for a custom bush to progress into a different stage. +public interface ICustomBushProgressRule +{ + /// A game state query which determines whether the bush should grow to the indicated stage. + public string? Condition { get; } + + /// Gets a unique ID for this entry within the current list. + public string? Id { get; } + + /// Gets the items dropped when the conditions for this rule are met. + public ICustomBushDrops ItemsDropped { get; } + + /// Gets the stage that the bush should grow to. + public string StageId { get; } + + /// Get the stage counter condition for this rule. + /// Returns the stage counter. + public int GetStageCounter(); +} diff --git a/Common/Integrations/CustomBush/ICustomBushProgressRules.cs b/Common/Integrations/CustomBush/ICustomBushProgressRules.cs new file mode 100644 index 000000000..98dbb5f9d --- /dev/null +++ b/Common/Integrations/CustomBush/ICustomBushProgressRules.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace Pathoschild.Stardew.Common.Integrations.CustomBush; + +/// +public interface ICustomBushProgressRules : IList +{ + /// Try to get the minimum stage counter for any condition with the given stage id. + /// The stage id, or any. + /// Returns the stage counter or -1 if the stage id cannot be reached. + public int GetCounterTo(string? id); +} diff --git a/Common/Integrations/CustomBush/ICustomBushStage.cs b/Common/Integrations/CustomBush/ICustomBushStage.cs new file mode 100644 index 000000000..5892ce4f1 --- /dev/null +++ b/Common/Integrations/CustomBush/ICustomBushStage.cs @@ -0,0 +1,28 @@ +using Microsoft.Xna.Framework; + +namespace Pathoschild.Stardew.Common.Integrations.CustomBush; + +/// Represents a stage that a custom bush can change into. +public interface ICustomBushStage +{ + /// Gets the bush type for the growth stage. + public CustomBushType BushType { get; } + + /// A game state query which indicates whether the bush should increment the days in its current stage. + public string? ConditionToProgress { get; } + + /// Gets the default texture used when planted indoors. + public string IndoorTexture { get; } + + /// Gets or sets the items produced by this custom bush. + public ICustomBushDrops ItemsProduced { get; } + + /// Gets the rules for progressing. + public ICustomBushProgressRules ProgressRules { get; } + + /// Gets the coordinates for the sprite at this stage. + public Point SpritePosition { get; } + + /// Gets the texture of the tea bush. + public string Texture { get; } +} diff --git a/Common/Integrations/CustomBush/ICustomBushStages.cs b/Common/Integrations/CustomBush/ICustomBushStages.cs new file mode 100644 index 000000000..5dca4b8dc --- /dev/null +++ b/Common/Integrations/CustomBush/ICustomBushStages.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace Pathoschild.Stardew.Common.Integrations.CustomBush; + +/// +public interface ICustomBushStages : IDictionary +{ + /// Try to get sequential stages starting from an initial stage. + /// Stages that go from initial to last without any repeated elements. + public IEnumerable<(ICustomBushStage Stage, string Id, int Counter)> GetSequentialStages(); +} diff --git a/LookupAnything/Framework/Lookups/TerrainFeatures/BushSubject.cs b/LookupAnything/Framework/Lookups/TerrainFeatures/BushSubject.cs index a11cdd65a..2701a72c7 100644 --- a/LookupAnything/Framework/Lookups/TerrainFeatures/BushSubject.cs +++ b/LookupAnything/Framework/Lookups/TerrainFeatures/BushSubject.cs @@ -38,7 +38,7 @@ public BushSubject(GameHelper gameHelper, Bush bush) this.Target = bush; if (this.TryGetCustomBush(bush, out ICustomBush? customBush)) - this.Initialize(TokenParser.ParseText(customBush.DisplayName), TokenParser.ParseText(customBush.Description), I18n.Type_Bush()); + this.Initialize(TokenParser.ParseText(customBush.Data.DisplayName), TokenParser.ParseText(customBush.Data.Description), I18n.Type_Bush()); else if (this.IsBerryBush(bush)) this.Initialize(I18n.Bush_Name_Berry(), I18n.Bush_Description_Berry(), I18n.Type_Bush()); else if (this.IsTeaBush(bush)) @@ -146,8 +146,11 @@ public override bool DrawPortrait(SpriteBatch spriteBatch, Vector2 position, Vec Vector2 offset = new Vector2(size.X - targetSize.X, size.Y - targetSize.Y) / 2; // get texture - if (!this.GameHelper.CustomBush.TryGetTexture(bush, out Texture2D? texture)) - texture = Bush.texture.Value; + Texture2D texture = Bush.texture.Value; + if (this.GameHelper.CustomBush.TryGetBush(bush, out ICustomBush? customBush)) + { + texture = customBush.Texture; + } // draw portrait spriteBatch.Draw( @@ -198,10 +201,10 @@ private bool TryGetCustomBushDrops(Bush bush, [NotNullWhen(true)] out List(customBush.ItemsProduced.Count); - foreach (var drop in customBush.ItemsProduced) + drops = new List(customBush.Stage.ItemsProduced.Count); + foreach (var drop in customBush.Stage.ItemsProduced) { - drops.Add(new ItemDropData(drop.ItemId, drop.MinStack, drop.MaxStack, drop.Chance, drop.Condition)); + drops.Add(new ItemDropData(drop.ItemId, drop.MinStack, drop.MaxStack, drop.GetChance(), drop.Condition)); } return true; } @@ -244,7 +247,7 @@ private SDate GetDateFullyGrown(Bush bush) SDate date = this.GetDatePlanted(bush); if (this.TryGetCustomBush(bush, out ICustomBush? customBush)) - date = date.AddDays(customBush.AgeToProduce); + date = date.AddDays(customBush.Data.GetAgeToMature()); else if (this.IsTeaBush(bush)) date = date.AddDays(Bush.daysToMatureGreenTeaBush); @@ -256,7 +259,9 @@ private SDate GetDateFullyGrown(Bush bush) private int GetDayToBeginProducing(Bush bush) { if (this.TryGetCustomBush(bush, out ICustomBush? customBush)) - return customBush.DayToBeginProducing; + return customBush.Stage.ItemsProduced.Any() + ? customBush.Stage.ItemsProduced.Min(drop => drop.GetDay()) + : -1; if (this.IsTeaBush(bush)) return 22; // tea bushes produce on day 22+ of season @@ -269,7 +274,7 @@ private int GetDayToBeginProducing(Bush bush) private List GetProducingSeasons(Bush bush) { if (this.TryGetCustomBush(bush, out ICustomBush? customBush)) - return customBush.Seasons; + return customBush.Data.GetSeasons(); if (this.IsTeaBush(bush)) return [Season.Spring, Season.Summer, Season.Fall];