From 66a8de883dd2897af3c79cb0cd0ff03f9b7b1b7c Mon Sep 17 00:00:00 2001
From: Matthew <3005344+LeFauxMatt@users.noreply.github.com>
Date: Tue, 17 Dec 2024 18:38:43 -0800
Subject: [PATCH 1/5] draft api
---
CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs | 30 +++++++++++++++++++
CJBItemSpawner/ICJBItemSpawnerAPI.cs | 10 +++++++
CJBItemSpawner/ModEntry.cs | 5 ++++
3 files changed, 45 insertions(+)
create mode 100644 CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs
create mode 100644 CJBItemSpawner/ICJBItemSpawnerAPI.cs
diff --git a/CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs b/CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs
new file mode 100644
index 00000000..7c808eec
--- /dev/null
+++ b/CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs
@@ -0,0 +1,30 @@
+using System;
+using StardewValley;
+
+namespace CJBItemSpawner.Framework;
+
+///
+public sealed class CJBItemSpawnerAPI : ICJBItemSpawnerAPI
+{
+ /*********
+ ** Fields
+ *********/
+ /// Build an item spawner menu.
+ private readonly Func BuildMenu;
+
+ /*********
+ ** Public methods
+ *********/
+ /// Construct an instance.
+ /// Method for building an item spawner menu.
+ internal CJBItemSpawnerAPI(Func buildMenu)
+ {
+ this.BuildMenu = buildMenu;
+ }
+
+ ///
+ public void OpenItemSpawnerMenu()
+ {
+ Game1.activeClickableMenu = this.BuildMenu();
+ }
+}
diff --git a/CJBItemSpawner/ICJBItemSpawnerAPI.cs b/CJBItemSpawner/ICJBItemSpawnerAPI.cs
new file mode 100644
index 00000000..ea7a5252
--- /dev/null
+++ b/CJBItemSpawner/ICJBItemSpawnerAPI.cs
@@ -0,0 +1,10 @@
+namespace CJBItemSpawner;
+
+/// The API which lets other mods interact with CJB Item Spawner.
+internal interface ICJBItemSpawnerAPI
+{
+ ///
+ /// Open the item spawner menu.
+ ///
+ void OpenItemSpawnerMenu();
+}
diff --git a/CJBItemSpawner/ModEntry.cs b/CJBItemSpawner/ModEntry.cs
index 4a6b8e6f..762e76f3 100644
--- a/CJBItemSpawner/ModEntry.cs
+++ b/CJBItemSpawner/ModEntry.cs
@@ -65,6 +65,11 @@ public override void Entry(IModHelper helper)
helper.Events.GameLoop.UpdateTicked += this.OnUpdateTicked;
}
+ ///
+ public override object GetApi()
+ {
+ return new CJBItemSpawnerAPI(this.BuildMenu);
+ }
/*********
** Private methods
From 7d1aa3e70f5fc9613d51ac847b410c831e3dd1c1 Mon Sep 17 00:00:00 2001
From: Matthew <3005344+LeFauxMatt@users.noreply.github.com>
Date: Tue, 14 Jan 2025 10:24:09 -0800
Subject: [PATCH 2/5] Add api method for adding custom repository of searchable
items
---
.../Framework/ItemData/ItemRepository.cs | 28 ++++++-------
.../Framework/ItemData/SearchableItem.cs | 30 ++++++-------
.../Framework/Models/ModDataCategory.cs | 2 +-
.../Framework/Models/ModDataCategoryRule.cs | 2 +-
CJBItemSpawner/Framework/SpawnableItem.cs | 2 +-
CJBItemSpawner/ICJBItemSpawnerAPI.cs | 4 ++
CJBItemSpawner/IItemRepository.cs | 17 ++++++++
CJBItemSpawner/ISearchableItem.cs | 42 +++++++++++++++++++
CJBItemSpawner/ModEntry.cs | 4 +-
9 files changed, 95 insertions(+), 36 deletions(-)
create mode 100644 CJBItemSpawner/IItemRepository.cs
create mode 100644 CJBItemSpawner/ISearchableItem.cs
diff --git a/CJBItemSpawner/Framework/ItemData/ItemRepository.cs b/CJBItemSpawner/Framework/ItemData/ItemRepository.cs
index 73ff7d1b..bc9c5d7e 100644
--- a/CJBItemSpawner/Framework/ItemData/ItemRepository.cs
+++ b/CJBItemSpawner/Framework/ItemData/ItemRepository.cs
@@ -13,16 +13,14 @@ namespace CJBItemSpawner.Framework.ItemData;
/// Provides methods for searching and constructing items.
/// This is copied from the SMAPI source code and should be kept in sync with it.
-internal class ItemRepository
+internal class ItemRepository : IItemRepository
{
/*********
** Public methods
*********/
- /// Get all spawnable items.
- /// Only include items for the given .
- /// Whether to include flavored variants like "Sunflower Honey".
+ ///
[SuppressMessage("ReSharper", "AccessToModifiedClosure", Justification = $"{nameof(ItemRepository.TryCreate)} invokes the lambda immediately.")]
- public IEnumerable GetAll(string? onlyType = null, bool includeVariants = true)
+ public IEnumerable GetAll(string? onlyType = null, bool includeVariants = true)
{
//
//
@@ -34,7 +32,7 @@ public IEnumerable GetAll(string? onlyType = null, bool includeV
//
//
- IEnumerable GetAllRaw()
+ IEnumerable GetAllRaw()
{
// get from item data definitions
foreach (IItemDataDefinition itemType in ItemRegistry.ItemTypes)
@@ -52,7 +50,7 @@ public IEnumerable GetAll(string? onlyType = null, bool includeV
foreach (string id in itemType.GetAllIds())
{
// base item
- SearchableItem? result = this.TryCreate(itemType.Identifier, id, p => ItemRegistry.Create(itemType.Identifier + p.Id));
+ ISearchableItem? result = this.TryCreate(itemType.Identifier, id, p => ItemRegistry.Create(itemType.Identifier + p.Id));
// ring
if (result?.Item is Ring)
@@ -61,14 +59,14 @@ public IEnumerable GetAll(string? onlyType = null, bool includeV
// journal scraps
else if (result?.QualifiedItemId == "(O)842")
{
- foreach (SearchableItem? journalScrap in this.GetSecretNotes(itemType, isJournalScrap: true))
+ foreach (ISearchableItem? journalScrap in this.GetSecretNotes(itemType, isJournalScrap: true))
yield return journalScrap;
}
// secret notes
else if (result?.QualifiedItemId == "(O)79")
{
- foreach (SearchableItem? secretNote in this.GetSecretNotes(itemType, isJournalScrap: false))
+ foreach (ISearchableItem? secretNote in this.GetSecretNotes(itemType, isJournalScrap: false))
yield return secretNote;
}
@@ -97,7 +95,7 @@ public IEnumerable GetAll(string? onlyType = null, bool includeV
if (includeVariants)
{
- foreach (SearchableItem? variant in this.GetFlavoredObjectVariants(objectDataDefinition, result?.Item as SObject, itemType))
+ foreach (ISearchableItem? variant in this.GetFlavoredObjectVariants(objectDataDefinition, result?.Item as SObject, itemType))
yield return variant;
}
}
@@ -129,7 +127,7 @@ select item
/// The object data definition.
/// Whether to get journal scraps.
/// Derived from .
- private IEnumerable GetSecretNotes(IItemDataDefinition itemType, bool isJournalScrap)
+ private IEnumerable GetSecretNotes(IItemDataDefinition itemType, bool isJournalScrap)
{
// get base item ID
string baseId = isJournalScrap ? "842" : "79";
@@ -165,7 +163,7 @@ select item
/// The item data definition for object items.
/// A sample of the base item.
/// The object data definition.
- private IEnumerable GetFlavoredObjectVariants(ObjectDataDefinition objectDataDefinition, SObject? item, IItemDataDefinition itemType)
+ private IEnumerable GetFlavoredObjectVariants(ObjectDataDefinition objectDataDefinition, SObject? item, IItemDataDefinition itemType)
{
if (item is null)
yield break;
@@ -226,7 +224,7 @@ select item
continue;
// create roe
- SearchableItem? roe = this.TryCreate(itemType.Identifier, $"812/{input.ItemId}", _ => objectDataDefinition.CreateFlavoredRoe(input));
+ ISearchableItem? roe = this.TryCreate(itemType.Identifier, $"812/{input.ItemId}", _ => objectDataDefinition.CreateFlavoredRoe(input));
yield return roe;
// create aged roe
@@ -286,11 +284,11 @@ private TAsset TryLoad(Func load)
/// The item type.
/// The locally unique item key.
/// Create an item instance.
- private SearchableItem? TryCreate(string type, string key, Func createItem)
+ private ISearchableItem? TryCreate(string type, string key, Func createItem)
{
try
{
- SearchableItem item = new SearchableItem(type, key, createItem);
+ ISearchableItem item = new SearchableItem(type, key, createItem);
item.Item.getDescription(); // force-load item data, so it crashes here if it's invalid
if (item.Item.Name is null or "Error Item")
diff --git a/CJBItemSpawner/Framework/ItemData/SearchableItem.cs b/CJBItemSpawner/Framework/ItemData/SearchableItem.cs
index 33e050d3..1b9da2c4 100644
--- a/CJBItemSpawner/Framework/ItemData/SearchableItem.cs
+++ b/CJBItemSpawner/Framework/ItemData/SearchableItem.cs
@@ -1,35 +1,33 @@
using System;
using StardewValley;
-using StardewValley.ItemTypeDefinitions;
namespace CJBItemSpawner.Framework.ItemData;
-/// A game item with metadata.
-/// This is copied from the SMAPI source code and should be kept in sync with it.
-internal class SearchableItem
+///
+internal class SearchableItem : ISearchableItem
{
/*********
** Accessors
*********/
- /// The value for the item type.
+ ///
public string Type { get; }
- /// A sample item instance.
+ ///
public Item Item { get; }
- /// Create an item instance.
+ ///
public Func- CreateItem { get; }
- /// The unqualified item ID.
+ ///
public string Id { get; }
- /// The qualified item ID.
+ ///
public string QualifiedItemId { get; }
- /// The item's default name.
+ ///
public string Name => this.Item.Name;
- /// The item's display name for the current language.
+ ///
public string DisplayName => this.Item.DisplayName;
@@ -40,7 +38,7 @@ internal class SearchableItem
/// The item type.
/// The unqualified item ID.
/// Create an item instance.
- public SearchableItem(string type, string id, Func createItem)
+ public SearchableItem(string type, string id, Func createItem)
{
this.Type = type;
this.Id = id;
@@ -51,7 +49,7 @@ public SearchableItem(string type, string id, Func createI
/// Construct an instance.
/// The item metadata to copy.
- public SearchableItem(SearchableItem item)
+ public SearchableItem(ISearchableItem item)
{
this.Type = item.Type;
this.Id = item.Id;
@@ -60,8 +58,7 @@ public SearchableItem(SearchableItem item)
this.Item = item.Item;
}
- /// Get whether the item name contains a case-insensitive substring.
- /// The substring to find.
+ ///
public bool NameContains(string substring)
{
return
@@ -69,8 +66,7 @@ public bool NameContains(string substring)
|| this.DisplayName.IndexOf(substring, StringComparison.OrdinalIgnoreCase) != -1;
}
- /// Get whether the item name is exactly equal to a case-insensitive string.
- /// The substring to find.
+ ///
public bool NameEquivalentTo(string name)
{
return
diff --git a/CJBItemSpawner/Framework/Models/ModDataCategory.cs b/CJBItemSpawner/Framework/Models/ModDataCategory.cs
index 1d479ef3..4adc6b17 100644
--- a/CJBItemSpawner/Framework/Models/ModDataCategory.cs
+++ b/CJBItemSpawner/Framework/Models/ModDataCategory.cs
@@ -13,7 +13,7 @@ internal record ModDataCategory(string Label, ModDataCategoryRule? When, ModData
*********/
/// Get whether a given item matches the rules for this category.
/// The item to check.
- public bool IsMatch(SearchableItem item)
+ public bool IsMatch(ISearchableItem item)
{
return
this.When != null
diff --git a/CJBItemSpawner/Framework/Models/ModDataCategoryRule.cs b/CJBItemSpawner/Framework/Models/ModDataCategoryRule.cs
index 13e778d7..eb45ebe4 100644
--- a/CJBItemSpawner/Framework/Models/ModDataCategoryRule.cs
+++ b/CJBItemSpawner/Framework/Models/ModDataCategoryRule.cs
@@ -46,7 +46,7 @@ public ModDataCategoryRule(HashSet? @class, HashSet? objType, Ha
/// Get whether a given item matches the rules for this category.
/// The searchable item to check.
- public bool IsMatch(SearchableItem entry)
+ public bool IsMatch(ISearchableItem entry)
{
Item item = entry.Item;
SObject? obj = item as SObject;
diff --git a/CJBItemSpawner/Framework/SpawnableItem.cs b/CJBItemSpawner/Framework/SpawnableItem.cs
index c05628cc..7e1d2c74 100644
--- a/CJBItemSpawner/Framework/SpawnableItem.cs
+++ b/CJBItemSpawner/Framework/SpawnableItem.cs
@@ -18,7 +18,7 @@ internal class SpawnableItem : SearchableItem
/// Construct an instance.
/// The item metadata.
/// The item's category filter label for the spawn menu.
- public SpawnableItem(SearchableItem item, string category)
+ public SpawnableItem(ISearchableItem item, string category)
: base(item)
{
this.Category = category;
diff --git a/CJBItemSpawner/ICJBItemSpawnerAPI.cs b/CJBItemSpawner/ICJBItemSpawnerAPI.cs
index ea7a5252..91d0decf 100644
--- a/CJBItemSpawner/ICJBItemSpawnerAPI.cs
+++ b/CJBItemSpawner/ICJBItemSpawnerAPI.cs
@@ -7,4 +7,8 @@ internal interface ICJBItemSpawnerAPI
/// Open the item spawner menu.
///
void OpenItemSpawnerMenu();
+
+ /// Add an item repository.
+ /// An item repository which returns all spawnable items.
+ void AddRepository(IItemRepository repository);
}
diff --git a/CJBItemSpawner/IItemRepository.cs b/CJBItemSpawner/IItemRepository.cs
new file mode 100644
index 00000000..8c8649f9
--- /dev/null
+++ b/CJBItemSpawner/IItemRepository.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using StardewValley.ItemTypeDefinitions;
+
+namespace CJBItemSpawner;
+
+/// Provides methods for searching and constructing items.
+/// This is copied from the SMAPI source code and should be kept in sync with it.
+public interface IItemRepository
+{
+ /*********
+ ** Public methods
+ *********/
+ /// Get all spawnable items.
+ /// Only include items for the given .
+ /// Whether to include flavored variants like "Sunflower Honey".
+ public IEnumerable GetAll(string? onlyType = null, bool includeVariants = true);
+}
diff --git a/CJBItemSpawner/ISearchableItem.cs b/CJBItemSpawner/ISearchableItem.cs
new file mode 100644
index 00000000..ee81ea6a
--- /dev/null
+++ b/CJBItemSpawner/ISearchableItem.cs
@@ -0,0 +1,42 @@
+using System;
+using StardewValley;
+using StardewValley.ItemTypeDefinitions;
+
+namespace CJBItemSpawner;
+
+/// A game item with metadata.
+/// This is copied from the SMAPI source code and should be kept in sync with it.
+public interface ISearchableItem
+{
+ /*********
+ ** Accessors
+ *********/
+ /// The value for the item type.
+ public string Type { get; }
+
+ /// A sample item instance.
+ public Item Item { get; }
+
+ /// Create an item instance.
+ public Func
- CreateItem { get; }
+
+ /// The unqualified item ID.
+ public string Id { get; }
+
+ /// The qualified item ID.
+ public string QualifiedItemId { get; }
+
+ /// The item's default name.
+ public string Name { get; }
+
+ /// The item's display name for the current language.
+ public string DisplayName { get; }
+
+ /// Get whether the item name contains a case-insensitive substring.
+ /// The substring to find.
+ public bool NameContains(string substring);
+
+ /// Get whether the item name is exactly equal to a case-insensitive string.
+ /// The substring to find.
+ public bool NameEquivalentTo(string name);
+}
diff --git a/CJBItemSpawner/ModEntry.cs b/CJBItemSpawner/ModEntry.cs
index 762e76f3..65895e0a 100644
--- a/CJBItemSpawner/ModEntry.cs
+++ b/CJBItemSpawner/ModEntry.cs
@@ -127,7 +127,7 @@ private ItemMenu BuildMenu()
/// Get the items which can be spawned.
private IEnumerable GetSpawnableItems()
{
- foreach (SearchableItem entry in new ItemRepository().GetAll())
+ foreach (ISearchableItem entry in new ItemRepository().GetAll())
{
ModDataCategory? category = this.Categories.FirstOrDefault(rule => rule.IsMatch(entry));
@@ -140,6 +140,8 @@ private IEnumerable GetSpawnableItems()
yield return new SpawnableItem(entry, categoryLabel);
}
+
+ // TODO: get items from api
}
/// Log a trace message which summarizes the user's current config.
From cc93f8185c191bc4406219beeafa8a039377f89f Mon Sep 17 00:00:00 2001
From: Matthew <3005344+LeFauxMatt@users.noreply.github.com>
Date: Tue, 14 Jan 2025 10:32:34 -0800
Subject: [PATCH 3/5] Implemented the interface
---
CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs | 13 ++++++-
CJBItemSpawner/ModEntry.cs | 37 +++++++++++++------
2 files changed, 38 insertions(+), 12 deletions(-)
diff --git a/CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs b/CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs
index 7c808eec..e764bb82 100644
--- a/CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs
+++ b/CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using StardewValley;
namespace CJBItemSpawner.Framework;
@@ -12,14 +13,18 @@ public sealed class CJBItemSpawnerAPI : ICJBItemSpawnerAPI
/// Build an item spawner menu.
private readonly Func BuildMenu;
+ /// The item repositories which returns all spawnable items.
+ private readonly IList ItemRepositories;
+
/*********
** Public methods
*********/
/// Construct an instance.
/// Method for building an item spawner menu.
- internal CJBItemSpawnerAPI(Func buildMenu)
+ internal CJBItemSpawnerAPI(Func buildMenu, IList itemRepositories)
{
this.BuildMenu = buildMenu;
+ this.ItemRepositories = itemRepositories;
}
///
@@ -27,4 +32,10 @@ public void OpenItemSpawnerMenu()
{
Game1.activeClickableMenu = this.BuildMenu();
}
+
+ ///
+ public void AddRepository(IItemRepository repository)
+ {
+ this.ItemRepositories.Add(repository);
+ }
}
diff --git a/CJBItemSpawner/ModEntry.cs b/CJBItemSpawner/ModEntry.cs
index 65895e0a..93d4ccdd 100644
--- a/CJBItemSpawner/ModEntry.cs
+++ b/CJBItemSpawner/ModEntry.cs
@@ -26,6 +26,9 @@ internal class ModEntry : Mod
/// The item category filters available in the item spawner menu.
private ModDataCategory[] Categories = null!; // set in Entry
+ /// The item repositories which returns all spawnable items.
+ private readonly IList ItemRepositories = new List();
+
/// Manages the gamepad text entry UI.
private readonly TextEntryManager TextEntryManager = new();
@@ -68,7 +71,7 @@ public override void Entry(IModHelper helper)
///
public override object GetApi()
{
- return new CJBItemSpawnerAPI(this.BuildMenu);
+ return new CJBItemSpawnerAPI(this.BuildMenu, this.ItemRepositories);
}
/*********
@@ -124,24 +127,36 @@ private ItemMenu BuildMenu()
return new ItemMenu(items, this.TextEntryManager, this.ItemData, this.Helper.ModContent, this.Monitor, this.Config.ReclaimPriceInMenuTrashCan);
}
+ /// Get the item repositories.
+ private IEnumerable GetRepositories()
+ {
+ yield return new ItemRepository();
+
+ foreach (IItemRepository repository in this.ItemRepositories)
+ {
+ yield return repository;
+ }
+ }
+
/// Get the items which can be spawned.
private IEnumerable GetSpawnableItems()
{
- foreach (ISearchableItem entry in new ItemRepository().GetAll())
+ foreach (IItemRepository repository in this.GetRepositories())
{
- ModDataCategory? category = this.Categories.FirstOrDefault(rule => rule.IsMatch(entry));
+ foreach (ISearchableItem entry in repository.GetAll())
+ {
+ ModDataCategory? category = this.Categories.FirstOrDefault(rule => rule.IsMatch(entry));
- if (category?.Label != null && this.Config.HideCategories.Contains(category.Label))
- continue;
+ if (category?.Label != null && this.Config.HideCategories.Contains(category.Label))
+ continue;
- string categoryLabel = category != null
- ? I18n.GetByKey(category.Label).Default(category.Label)
- : I18n.Filter_Miscellaneous();
+ string categoryLabel = category != null
+ ? I18n.GetByKey(category.Label).Default(category.Label)
+ : I18n.Filter_Miscellaneous();
- yield return new SpawnableItem(entry, categoryLabel);
+ yield return new SpawnableItem(entry, categoryLabel);
+ }
}
-
- // TODO: get items from api
}
/// Log a trace message which summarizes the user's current config.
From c70ad10a4d21fa37dde48041e294ee57ffd96372 Mon Sep 17 00:00:00 2001
From: Matthew <3005344+LeFauxMatt@users.noreply.github.com>
Date: Tue, 14 Jan 2025 10:52:35 -0800
Subject: [PATCH 4/5] Alternative api proposal
---
CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs | 7 +--
.../Framework/ItemData/ItemRepository.cs | 6 ++-
CJBItemSpawner/ICJBItemSpawnerAPI.cs | 19 +++++++-
CJBItemSpawner/IItemRepository.cs | 17 -------
CJBItemSpawner/ModEntry.cs | 47 ++++++++++---------
5 files changed, 50 insertions(+), 46 deletions(-)
delete mode 100644 CJBItemSpawner/IItemRepository.cs
diff --git a/CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs b/CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs
index e764bb82..11608139 100644
--- a/CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs
+++ b/CJBItemSpawner/Framework/CJBItemSpawnerAPI.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using StardewValley;
+using static CJBItemSpawner.ICJBItemSpawnerAPI;
namespace CJBItemSpawner.Framework;
@@ -14,14 +15,14 @@ public sealed class CJBItemSpawnerAPI : ICJBItemSpawnerAPI
private readonly Func BuildMenu;
/// The item repositories which returns all spawnable items.
- private readonly IList ItemRepositories;
+ private readonly IList ItemRepositories;
/*********
** Public methods
*********/
/// Construct an instance.
/// Method for building an item spawner menu.
- internal CJBItemSpawnerAPI(Func buildMenu, IList itemRepositories)
+ internal CJBItemSpawnerAPI(Func buildMenu, IList itemRepositories)
{
this.BuildMenu = buildMenu;
this.ItemRepositories = itemRepositories;
@@ -34,7 +35,7 @@ public void OpenItemSpawnerMenu()
}
///
- public void AddRepository(IItemRepository repository)
+ public void AddRepository(Repository repository)
{
this.ItemRepositories.Add(repository);
}
diff --git a/CJBItemSpawner/Framework/ItemData/ItemRepository.cs b/CJBItemSpawner/Framework/ItemData/ItemRepository.cs
index bc9c5d7e..5b1214f6 100644
--- a/CJBItemSpawner/Framework/ItemData/ItemRepository.cs
+++ b/CJBItemSpawner/Framework/ItemData/ItemRepository.cs
@@ -13,12 +13,14 @@ namespace CJBItemSpawner.Framework.ItemData;
/// Provides methods for searching and constructing items.
/// This is copied from the SMAPI source code and should be kept in sync with it.
-internal class ItemRepository : IItemRepository
+internal class ItemRepository
{
/*********
** Public methods
*********/
- ///
+ /// Get all spawnable items.
+ /// Only include items for the given .
+ /// Whether to include flavored variants like "Sunflower Honey".
[SuppressMessage("ReSharper", "AccessToModifiedClosure", Justification = $"{nameof(ItemRepository.TryCreate)} invokes the lambda immediately.")]
public IEnumerable GetAll(string? onlyType = null, bool includeVariants = true)
{
diff --git a/CJBItemSpawner/ICJBItemSpawnerAPI.cs b/CJBItemSpawner/ICJBItemSpawnerAPI.cs
index 91d0decf..cb7a4bc2 100644
--- a/CJBItemSpawner/ICJBItemSpawnerAPI.cs
+++ b/CJBItemSpawner/ICJBItemSpawnerAPI.cs
@@ -1,7 +1,12 @@
+using System;
+using System.Collections.Generic;
+using StardewValley;
+using StardewValley.ItemTypeDefinitions;
+
namespace CJBItemSpawner;
/// The API which lets other mods interact with CJB Item Spawner.
-internal interface ICJBItemSpawnerAPI
+public interface ICJBItemSpawnerAPI
{
///
/// Open the item spawner menu.
@@ -10,5 +15,15 @@ internal interface ICJBItemSpawnerAPI
/// Add an item repository.
/// An item repository which returns all spawnable items.
- void AddRepository(IItemRepository repository);
+ void AddRepository(Repository repository);
+
+ /// Get all spawnable items.
+ /// Only include items for the given .
+ /// Whether to include flavored variants like "Sunflower Honey".
+ public delegate IEnumerable<(string Type, string Id, CreateItem CreateItem)> Repository(string? onlyType = null, bool includeVariants = true);
+
+ /// Create an item instance.
+ /// The item type.
+ /// The unqualified item ID.
+ public delegate Item CreateItem(string type, string id);
}
diff --git a/CJBItemSpawner/IItemRepository.cs b/CJBItemSpawner/IItemRepository.cs
deleted file mode 100644
index 8c8649f9..00000000
--- a/CJBItemSpawner/IItemRepository.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Collections.Generic;
-using StardewValley.ItemTypeDefinitions;
-
-namespace CJBItemSpawner;
-
-/// Provides methods for searching and constructing items.
-/// This is copied from the SMAPI source code and should be kept in sync with it.
-public interface IItemRepository
-{
- /*********
- ** Public methods
- *********/
- /// Get all spawnable items.
- /// Only include items for the given .
- /// Whether to include flavored variants like "Sunflower Honey".
- public IEnumerable GetAll(string? onlyType = null, bool includeVariants = true);
-}
diff --git a/CJBItemSpawner/ModEntry.cs b/CJBItemSpawner/ModEntry.cs
index 93d4ccdd..93835276 100644
--- a/CJBItemSpawner/ModEntry.cs
+++ b/CJBItemSpawner/ModEntry.cs
@@ -8,6 +8,7 @@
using StardewModdingAPI;
using StardewModdingAPI.Events;
using StardewValley;
+using static CJBItemSpawner.ICJBItemSpawnerAPI;
namespace CJBItemSpawner;
@@ -27,7 +28,7 @@ internal class ModEntry : Mod
private ModDataCategory[] Categories = null!; // set in Entry
/// The item repositories which returns all spawnable items.
- private readonly IList ItemRepositories = new List();
+ private readonly IList ItemRepositories = new List();
/// Manages the gamepad text entry UI.
private readonly TextEntryManager TextEntryManager = new();
@@ -127,35 +128,37 @@ private ItemMenu BuildMenu()
return new ItemMenu(items, this.TextEntryManager, this.ItemData, this.Helper.ModContent, this.Monitor, this.Config.ReclaimPriceInMenuTrashCan);
}
- /// Get the item repositories.
- private IEnumerable GetRepositories()
- {
- yield return new ItemRepository();
-
- foreach (IItemRepository repository in this.ItemRepositories)
- {
- yield return repository;
- }
- }
-
/// Get the items which can be spawned.
private IEnumerable GetSpawnableItems()
{
- foreach (IItemRepository repository in this.GetRepositories())
+ IEnumerable GetSpawnableItemsRaw()
{
- foreach (ISearchableItem entry in repository.GetAll())
+ foreach (ISearchableItem entry in new ItemRepository().GetAll())
+ {
+ yield return entry;
+ }
+
+ foreach (Repository getAll in this.ItemRepositories)
{
- ModDataCategory? category = this.Categories.FirstOrDefault(rule => rule.IsMatch(entry));
+ foreach ((string type, string id, CreateItem createItem) in getAll())
+ {
+ yield return new SearchableItem(type, id, p => createItem(p.Type, p.Id));
+ }
+ }
+ }
- if (category?.Label != null && this.Config.HideCategories.Contains(category.Label))
- continue;
+ foreach (ISearchableItem entry in GetSpawnableItemsRaw())
+ {
+ ModDataCategory? category = this.Categories.FirstOrDefault(rule => rule.IsMatch(entry));
- string categoryLabel = category != null
- ? I18n.GetByKey(category.Label).Default(category.Label)
- : I18n.Filter_Miscellaneous();
+ if (category?.Label != null && this.Config.HideCategories.Contains(category.Label))
+ continue;
- yield return new SpawnableItem(entry, categoryLabel);
- }
+ string categoryLabel = category != null
+ ? I18n.GetByKey(category.Label).Default(category.Label)
+ : I18n.Filter_Miscellaneous();
+
+ yield return new SpawnableItem(entry, categoryLabel);
}
}
From 6b806c85ef2980ec197745ef114d96d900651cb9 Mon Sep 17 00:00:00 2001
From: Matthew <3005344+LeFauxMatt@users.noreply.github.com>
Date: Tue, 14 Jan 2025 10:56:48 -0800
Subject: [PATCH 5/5] Removed unused interface from proposal 1
---
.../Framework/ItemData/ItemRepository.cs | 22 +++++-----
.../Framework/ItemData/SearchableItem.cs | 29 +++++++------
.../Framework/Models/ModDataCategory.cs | 2 +-
.../Framework/Models/ModDataCategoryRule.cs | 2 +-
CJBItemSpawner/Framework/SpawnableItem.cs | 2 +-
CJBItemSpawner/ISearchableItem.cs | 42 -------------------
CJBItemSpawner/ModEntry.cs | 6 +--
7 files changed, 33 insertions(+), 72 deletions(-)
delete mode 100644 CJBItemSpawner/ISearchableItem.cs
diff --git a/CJBItemSpawner/Framework/ItemData/ItemRepository.cs b/CJBItemSpawner/Framework/ItemData/ItemRepository.cs
index 5b1214f6..73ff7d1b 100644
--- a/CJBItemSpawner/Framework/ItemData/ItemRepository.cs
+++ b/CJBItemSpawner/Framework/ItemData/ItemRepository.cs
@@ -22,7 +22,7 @@ internal class ItemRepository
/// Only include items for the given .
/// Whether to include flavored variants like "Sunflower Honey".
[SuppressMessage("ReSharper", "AccessToModifiedClosure", Justification = $"{nameof(ItemRepository.TryCreate)} invokes the lambda immediately.")]
- public IEnumerable GetAll(string? onlyType = null, bool includeVariants = true)
+ public IEnumerable GetAll(string? onlyType = null, bool includeVariants = true)
{
//
//
@@ -34,7 +34,7 @@ public IEnumerable GetAll(string? onlyType = null, bool include
//
//
- IEnumerable GetAllRaw()
+ IEnumerable GetAllRaw()
{
// get from item data definitions
foreach (IItemDataDefinition itemType in ItemRegistry.ItemTypes)
@@ -52,7 +52,7 @@ public IEnumerable GetAll(string? onlyType = null, bool include
foreach (string id in itemType.GetAllIds())
{
// base item
- ISearchableItem? result = this.TryCreate(itemType.Identifier, id, p => ItemRegistry.Create(itemType.Identifier + p.Id));
+ SearchableItem? result = this.TryCreate(itemType.Identifier, id, p => ItemRegistry.Create(itemType.Identifier + p.Id));
// ring
if (result?.Item is Ring)
@@ -61,14 +61,14 @@ public IEnumerable GetAll(string? onlyType = null, bool include
// journal scraps
else if (result?.QualifiedItemId == "(O)842")
{
- foreach (ISearchableItem? journalScrap in this.GetSecretNotes(itemType, isJournalScrap: true))
+ foreach (SearchableItem? journalScrap in this.GetSecretNotes(itemType, isJournalScrap: true))
yield return journalScrap;
}
// secret notes
else if (result?.QualifiedItemId == "(O)79")
{
- foreach (ISearchableItem? secretNote in this.GetSecretNotes(itemType, isJournalScrap: false))
+ foreach (SearchableItem? secretNote in this.GetSecretNotes(itemType, isJournalScrap: false))
yield return secretNote;
}
@@ -97,7 +97,7 @@ public IEnumerable GetAll(string? onlyType = null, bool include
if (includeVariants)
{
- foreach (ISearchableItem? variant in this.GetFlavoredObjectVariants(objectDataDefinition, result?.Item as SObject, itemType))
+ foreach (SearchableItem? variant in this.GetFlavoredObjectVariants(objectDataDefinition, result?.Item as SObject, itemType))
yield return variant;
}
}
@@ -129,7 +129,7 @@ select item
/// The object data definition.
/// Whether to get journal scraps.
/// Derived from .
- private IEnumerable GetSecretNotes(IItemDataDefinition itemType, bool isJournalScrap)
+ private IEnumerable GetSecretNotes(IItemDataDefinition itemType, bool isJournalScrap)
{
// get base item ID
string baseId = isJournalScrap ? "842" : "79";
@@ -165,7 +165,7 @@ select item
/// The item data definition for object items.
/// A sample of the base item.
/// The object data definition.
- private IEnumerable GetFlavoredObjectVariants(ObjectDataDefinition objectDataDefinition, SObject? item, IItemDataDefinition itemType)
+ private IEnumerable GetFlavoredObjectVariants(ObjectDataDefinition objectDataDefinition, SObject? item, IItemDataDefinition itemType)
{
if (item is null)
yield break;
@@ -226,7 +226,7 @@ select item
continue;
// create roe
- ISearchableItem? roe = this.TryCreate(itemType.Identifier, $"812/{input.ItemId}", _ => objectDataDefinition.CreateFlavoredRoe(input));
+ SearchableItem? roe = this.TryCreate(itemType.Identifier, $"812/{input.ItemId}", _ => objectDataDefinition.CreateFlavoredRoe(input));
yield return roe;
// create aged roe
@@ -286,11 +286,11 @@ private TAsset TryLoad(Func load)
/// The item type.
/// The locally unique item key.
/// Create an item instance.
- private ISearchableItem? TryCreate(string type, string key, Func createItem)
+ private SearchableItem? TryCreate(string type, string key, Func createItem)
{
try
{
- ISearchableItem item = new SearchableItem(type, key, createItem);
+ SearchableItem item = new SearchableItem(type, key, createItem);
item.Item.getDescription(); // force-load item data, so it crashes here if it's invalid
if (item.Item.Name is null or "Error Item")
diff --git a/CJBItemSpawner/Framework/ItemData/SearchableItem.cs b/CJBItemSpawner/Framework/ItemData/SearchableItem.cs
index 1b9da2c4..dc4aa5fd 100644
--- a/CJBItemSpawner/Framework/ItemData/SearchableItem.cs
+++ b/CJBItemSpawner/Framework/ItemData/SearchableItem.cs
@@ -3,31 +3,32 @@
namespace CJBItemSpawner.Framework.ItemData;
-///
-internal class SearchableItem : ISearchableItem
+/// A game item with metadata.
+/// This is copied from the SMAPI source code and should be kept in sync with it.
+internal class SearchableItem
{
/*********
** Accessors
*********/
- ///
+ /// The value for the item type.
public string Type { get; }
- ///
+ /// A sample item instance.
public Item Item { get; }
- ///
+ /// Create an item instance.
public Func
- CreateItem { get; }
- ///
+ /// The unqualified item ID.
public string Id { get; }
- ///
+ /// The qualified item ID.
public string QualifiedItemId { get; }
- ///
+ /// The item's default name.
public string Name => this.Item.Name;
- ///
+ /// The item's display name for the current language.
public string DisplayName => this.Item.DisplayName;
@@ -38,7 +39,7 @@ internal class SearchableItem : ISearchableItem
/// The item type.
/// The unqualified item ID.
/// Create an item instance.
- public SearchableItem(string type, string id, Func createItem)
+ public SearchableItem(string type, string id, Func createItem)
{
this.Type = type;
this.Id = id;
@@ -49,7 +50,7 @@ public SearchableItem(string type, string id, Func create
/// Construct an instance.
/// The item metadata to copy.
- public SearchableItem(ISearchableItem item)
+ public SearchableItem(SearchableItem item)
{
this.Type = item.Type;
this.Id = item.Id;
@@ -58,7 +59,8 @@ public SearchableItem(ISearchableItem item)
this.Item = item.Item;
}
- ///
+ /// Get whether the item name contains a case-insensitive substring.
+ /// The substring to find.
public bool NameContains(string substring)
{
return
@@ -66,7 +68,8 @@ public bool NameContains(string substring)
|| this.DisplayName.IndexOf(substring, StringComparison.OrdinalIgnoreCase) != -1;
}
- ///
+ /// Get whether the item name is exactly equal to a case-insensitive string.
+ /// The substring to find.
public bool NameEquivalentTo(string name)
{
return
diff --git a/CJBItemSpawner/Framework/Models/ModDataCategory.cs b/CJBItemSpawner/Framework/Models/ModDataCategory.cs
index 4adc6b17..1d479ef3 100644
--- a/CJBItemSpawner/Framework/Models/ModDataCategory.cs
+++ b/CJBItemSpawner/Framework/Models/ModDataCategory.cs
@@ -13,7 +13,7 @@ internal record ModDataCategory(string Label, ModDataCategoryRule? When, ModData
*********/
/// Get whether a given item matches the rules for this category.
/// The item to check.
- public bool IsMatch(ISearchableItem item)
+ public bool IsMatch(SearchableItem item)
{
return
this.When != null
diff --git a/CJBItemSpawner/Framework/Models/ModDataCategoryRule.cs b/CJBItemSpawner/Framework/Models/ModDataCategoryRule.cs
index eb45ebe4..13e778d7 100644
--- a/CJBItemSpawner/Framework/Models/ModDataCategoryRule.cs
+++ b/CJBItemSpawner/Framework/Models/ModDataCategoryRule.cs
@@ -46,7 +46,7 @@ public ModDataCategoryRule(HashSet? @class, HashSet? objType, Ha
/// Get whether a given item matches the rules for this category.
/// The searchable item to check.
- public bool IsMatch(ISearchableItem entry)
+ public bool IsMatch(SearchableItem entry)
{
Item item = entry.Item;
SObject? obj = item as SObject;
diff --git a/CJBItemSpawner/Framework/SpawnableItem.cs b/CJBItemSpawner/Framework/SpawnableItem.cs
index 7e1d2c74..c05628cc 100644
--- a/CJBItemSpawner/Framework/SpawnableItem.cs
+++ b/CJBItemSpawner/Framework/SpawnableItem.cs
@@ -18,7 +18,7 @@ internal class SpawnableItem : SearchableItem
/// Construct an instance.
/// The item metadata.
/// The item's category filter label for the spawn menu.
- public SpawnableItem(ISearchableItem item, string category)
+ public SpawnableItem(SearchableItem item, string category)
: base(item)
{
this.Category = category;
diff --git a/CJBItemSpawner/ISearchableItem.cs b/CJBItemSpawner/ISearchableItem.cs
deleted file mode 100644
index ee81ea6a..00000000
--- a/CJBItemSpawner/ISearchableItem.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System;
-using StardewValley;
-using StardewValley.ItemTypeDefinitions;
-
-namespace CJBItemSpawner;
-
-/// A game item with metadata.
-/// This is copied from the SMAPI source code and should be kept in sync with it.
-public interface ISearchableItem
-{
- /*********
- ** Accessors
- *********/
- /// The value for the item type.
- public string Type { get; }
-
- /// A sample item instance.
- public Item Item { get; }
-
- /// Create an item instance.
- public Func
- CreateItem { get; }
-
- /// The unqualified item ID.
- public string Id { get; }
-
- /// The qualified item ID.
- public string QualifiedItemId { get; }
-
- /// The item's default name.
- public string Name { get; }
-
- /// The item's display name for the current language.
- public string DisplayName { get; }
-
- /// Get whether the item name contains a case-insensitive substring.
- /// The substring to find.
- public bool NameContains(string substring);
-
- /// Get whether the item name is exactly equal to a case-insensitive string.
- /// The substring to find.
- public bool NameEquivalentTo(string name);
-}
diff --git a/CJBItemSpawner/ModEntry.cs b/CJBItemSpawner/ModEntry.cs
index 93835276..4622b9ee 100644
--- a/CJBItemSpawner/ModEntry.cs
+++ b/CJBItemSpawner/ModEntry.cs
@@ -131,9 +131,9 @@ private ItemMenu BuildMenu()
/// Get the items which can be spawned.
private IEnumerable GetSpawnableItems()
{
- IEnumerable GetSpawnableItemsRaw()
+ IEnumerable GetSpawnableItemsRaw()
{
- foreach (ISearchableItem entry in new ItemRepository().GetAll())
+ foreach (SearchableItem entry in new ItemRepository().GetAll())
{
yield return entry;
}
@@ -147,7 +147,7 @@ IEnumerable GetSpawnableItemsRaw()
}
}
- foreach (ISearchableItem entry in GetSpawnableItemsRaw())
+ foreach (SearchableItem entry in GetSpawnableItemsRaw())
{
ModDataCategory? category = this.Categories.FirstOrDefault(rule => rule.IsMatch(entry));