update item repo to allow creating instances later
This commit is contained in:
parent
70cf63c907
commit
7c652b0924
|
@ -12,9 +12,12 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.ItemData
|
||||||
/// <summary>The item type.</summary>
|
/// <summary>The item type.</summary>
|
||||||
public ItemType Type { get; }
|
public ItemType Type { get; }
|
||||||
|
|
||||||
/// <summary>The item instance.</summary>
|
/// <summary>A sample item instance.</summary>
|
||||||
public Item Item { get; }
|
public Item Item { get; }
|
||||||
|
|
||||||
|
/// <summary>Create an item instance.</summary>
|
||||||
|
public Func<Item> CreateItem { get; }
|
||||||
|
|
||||||
/// <summary>The item's unique ID for its type.</summary>
|
/// <summary>The item's unique ID for its type.</summary>
|
||||||
public int ID { get; }
|
public int ID { get; }
|
||||||
|
|
||||||
|
@ -31,12 +34,13 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.ItemData
|
||||||
/// <summary>Construct an instance.</summary>
|
/// <summary>Construct an instance.</summary>
|
||||||
/// <param name="type">The item type.</param>
|
/// <param name="type">The item type.</param>
|
||||||
/// <param name="id">The unique ID (if different from the item's parent sheet index).</param>
|
/// <param name="id">The unique ID (if different from the item's parent sheet index).</param>
|
||||||
/// <param name="item">The item instance.</param>
|
/// <param name="createItem">Create an item instance.</param>
|
||||||
public SearchableItem(ItemType type, int id, Item item)
|
public SearchableItem(ItemType type, int id, Func<SearchableItem, Item> createItem)
|
||||||
{
|
{
|
||||||
this.Type = type;
|
this.Type = type;
|
||||||
this.ID = id;
|
this.ID = id;
|
||||||
this.Item = item;
|
this.CreateItem = () => createItem(this);
|
||||||
|
this.Item = createItem(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Get whether the item name contains a case-insensitive substring.</summary>
|
/// <summary>Get whether the item name contains a case-insensitive substring.</summary>
|
||||||
|
|
|
@ -30,47 +30,60 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
[SuppressMessage("ReSharper", "AccessToModifiedClosure", Justification = "TryCreate invokes the lambda immediately.")]
|
[SuppressMessage("ReSharper", "AccessToModifiedClosure", Justification = "TryCreate invokes the lambda immediately.")]
|
||||||
public IEnumerable<SearchableItem> GetAll()
|
public IEnumerable<SearchableItem> GetAll()
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Be careful about closure variable capture here!
|
||||||
|
//
|
||||||
|
// SearchableItem stores the Func<Item> to create new instances later. Loop variables passed into the
|
||||||
|
// function will be captured, so every func in the loop will use the value from the last iteration. Use the
|
||||||
|
// TryCreate(type, id, entity => item) form to avoid the issue, or create a local variable to pass in.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
IEnumerable<SearchableItem> GetAllRaw()
|
IEnumerable<SearchableItem> GetAllRaw()
|
||||||
{
|
{
|
||||||
// get tools
|
// get tools
|
||||||
for (int quality = Tool.stone; quality <= Tool.iridium; quality++)
|
for (int q = Tool.stone; q <= Tool.iridium; q++)
|
||||||
{
|
{
|
||||||
yield return this.TryCreate(ItemType.Tool, ToolFactory.axe, () => ToolFactory.getToolFromDescription(ToolFactory.axe, quality));
|
int quality = q;
|
||||||
yield return this.TryCreate(ItemType.Tool, ToolFactory.hoe, () => ToolFactory.getToolFromDescription(ToolFactory.hoe, quality));
|
|
||||||
yield return this.TryCreate(ItemType.Tool, ToolFactory.pickAxe, () => ToolFactory.getToolFromDescription(ToolFactory.pickAxe, quality));
|
yield return this.TryCreate(ItemType.Tool, ToolFactory.axe, _ => ToolFactory.getToolFromDescription(ToolFactory.axe, quality));
|
||||||
yield return this.TryCreate(ItemType.Tool, ToolFactory.wateringCan, () => ToolFactory.getToolFromDescription(ToolFactory.wateringCan, quality));
|
yield return this.TryCreate(ItemType.Tool, ToolFactory.hoe, _ => ToolFactory.getToolFromDescription(ToolFactory.hoe, quality));
|
||||||
|
yield return this.TryCreate(ItemType.Tool, ToolFactory.pickAxe, _ => ToolFactory.getToolFromDescription(ToolFactory.pickAxe, quality));
|
||||||
|
yield return this.TryCreate(ItemType.Tool, ToolFactory.wateringCan, _ => ToolFactory.getToolFromDescription(ToolFactory.wateringCan, quality));
|
||||||
if (quality != Tool.iridium)
|
if (quality != Tool.iridium)
|
||||||
yield return this.TryCreate(ItemType.Tool, ToolFactory.fishingRod, () => ToolFactory.getToolFromDescription(ToolFactory.fishingRod, quality));
|
yield return this.TryCreate(ItemType.Tool, ToolFactory.fishingRod, _ => ToolFactory.getToolFromDescription(ToolFactory.fishingRod, quality));
|
||||||
}
|
}
|
||||||
yield return this.TryCreate(ItemType.Tool, this.CustomIDOffset, () => new MilkPail()); // these don't have any sort of ID, so we'll just assign some arbitrary ones
|
yield return this.TryCreate(ItemType.Tool, this.CustomIDOffset, _ => new MilkPail()); // these don't have any sort of ID, so we'll just assign some arbitrary ones
|
||||||
yield return this.TryCreate(ItemType.Tool, this.CustomIDOffset + 1, () => new Shears());
|
yield return this.TryCreate(ItemType.Tool, this.CustomIDOffset + 1, _ => new Shears());
|
||||||
yield return this.TryCreate(ItemType.Tool, this.CustomIDOffset + 2, () => new Pan());
|
yield return this.TryCreate(ItemType.Tool, this.CustomIDOffset + 2, _ => new Pan());
|
||||||
yield return this.TryCreate(ItemType.Tool, this.CustomIDOffset + 3, () => new Wand());
|
yield return this.TryCreate(ItemType.Tool, this.CustomIDOffset + 3, _ => new Wand());
|
||||||
|
|
||||||
// clothing
|
// clothing
|
||||||
foreach (int id in Game1.clothingInformation.Keys)
|
foreach (int id in Game1.clothingInformation.Keys)
|
||||||
yield return this.TryCreate(ItemType.Clothing, id, () => new Clothing(id));
|
yield return this.TryCreate(ItemType.Clothing, id, p => new Clothing(p.ID));
|
||||||
|
|
||||||
// wallpapers
|
// wallpapers
|
||||||
for (int id = 0; id < 112; id++)
|
for (int id = 0; id < 112; id++)
|
||||||
yield return this.TryCreate(ItemType.Wallpaper, id, () => new Wallpaper(id) { Category = SObject.furnitureCategory });
|
yield return this.TryCreate(ItemType.Wallpaper, id, p => new Wallpaper(p.ID) { Category = SObject.furnitureCategory });
|
||||||
|
|
||||||
// flooring
|
// flooring
|
||||||
for (int id = 0; id < 56; id++)
|
for (int id = 0; id < 56; id++)
|
||||||
yield return this.TryCreate(ItemType.Flooring, id, () => new Wallpaper(id, isFloor: true) { Category = SObject.furnitureCategory });
|
yield return this.TryCreate(ItemType.Flooring, id, p => new Wallpaper(p.ID, isFloor: true) { Category = SObject.furnitureCategory });
|
||||||
|
|
||||||
// equipment
|
// equipment
|
||||||
foreach (int id in this.TryLoad<int, string>("Data\\Boots").Keys)
|
foreach (int id in this.TryLoad<int, string>("Data\\Boots").Keys)
|
||||||
yield return this.TryCreate(ItemType.Boots, id, () => new Boots(id));
|
yield return this.TryCreate(ItemType.Boots, id, p => new Boots(p.ID));
|
||||||
foreach (int id in this.TryLoad<int, string>("Data\\hats").Keys)
|
foreach (int id in this.TryLoad<int, string>("Data\\hats").Keys)
|
||||||
yield return this.TryCreate(ItemType.Hat, id, () => new Hat(id));
|
yield return this.TryCreate(ItemType.Hat, id, p => new Hat(p.ID));
|
||||||
|
|
||||||
// weapons
|
// weapons
|
||||||
foreach (int id in this.TryLoad<int, string>("Data\\weapons").Keys)
|
foreach (int id in this.TryLoad<int, string>("Data\\weapons").Keys)
|
||||||
{
|
{
|
||||||
yield return this.TryCreate(ItemType.Weapon, id, () => (id >= 32 && id <= 34)
|
yield return this.TryCreate(ItemType.Weapon, id, p => (p.ID >= 32 && p.ID <= 34)
|
||||||
? (Item)new Slingshot(id)
|
? (Item)new Slingshot(p.ID)
|
||||||
: new MeleeWeapon(id)
|
: new MeleeWeapon(p.ID)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,14 +91,14 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
foreach (int id in this.TryLoad<int, string>("Data\\Furniture").Keys)
|
foreach (int id in this.TryLoad<int, string>("Data\\Furniture").Keys)
|
||||||
{
|
{
|
||||||
if (id == 1466 || id == 1468 || id == 1680)
|
if (id == 1466 || id == 1468 || id == 1680)
|
||||||
yield return this.TryCreate(ItemType.Furniture, id, () => new TV(id, Vector2.Zero));
|
yield return this.TryCreate(ItemType.Furniture, id, p => new TV(p.ID, Vector2.Zero));
|
||||||
else
|
else
|
||||||
yield return this.TryCreate(ItemType.Furniture, id, () => new Furniture(id, Vector2.Zero));
|
yield return this.TryCreate(ItemType.Furniture, id, p => new Furniture(p.ID, Vector2.Zero));
|
||||||
}
|
}
|
||||||
|
|
||||||
// craftables
|
// craftables
|
||||||
foreach (int id in Game1.bigCraftablesInformation.Keys)
|
foreach (int id in Game1.bigCraftablesInformation.Keys)
|
||||||
yield return this.TryCreate(ItemType.BigCraftable, id, () => new SObject(Vector2.Zero, id));
|
yield return this.TryCreate(ItemType.BigCraftable, id, p => new SObject(Vector2.Zero, p.ID));
|
||||||
|
|
||||||
// objects
|
// objects
|
||||||
foreach (int id in Game1.objectInformation.Keys)
|
foreach (int id in Game1.objectInformation.Keys)
|
||||||
|
@ -97,7 +110,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
{
|
{
|
||||||
foreach (int secretNoteId in this.TryLoad<int, string>("Data\\SecretNotes").Keys)
|
foreach (int secretNoteId in this.TryLoad<int, string>("Data\\SecretNotes").Keys)
|
||||||
{
|
{
|
||||||
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset + secretNoteId, () =>
|
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset + secretNoteId, _ =>
|
||||||
{
|
{
|
||||||
SObject note = new SObject(79, 1);
|
SObject note = new SObject(79, 1);
|
||||||
note.name = $"{note.name} #{secretNoteId}";
|
note.name = $"{note.name} #{secretNoteId}";
|
||||||
|
@ -108,18 +121,18 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
|
|
||||||
// ring
|
// ring
|
||||||
else if (id != 801 && fields?.Length >= 4 && fields[3] == "Ring") // 801 = wedding ring, which isn't an equippable ring
|
else if (id != 801 && fields?.Length >= 4 && fields[3] == "Ring") // 801 = wedding ring, which isn't an equippable ring
|
||||||
yield return this.TryCreate(ItemType.Ring, id, () => new Ring(id));
|
yield return this.TryCreate(ItemType.Ring, id, p => new Ring(p.ID));
|
||||||
|
|
||||||
// item
|
// item
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// spawn main item
|
// spawn main item
|
||||||
SObject item = null;
|
SObject item = null;
|
||||||
yield return this.TryCreate(ItemType.Object, id, () =>
|
yield return this.TryCreate(ItemType.Object, id, p =>
|
||||||
{
|
{
|
||||||
return item = (id == 812 // roe
|
return item = (p.ID == 812 // roe
|
||||||
? new ColoredObject(id, 1, Color.White)
|
? new ColoredObject(p.ID, 1, Color.White)
|
||||||
: new SObject(id, 1)
|
: new SObject(p.ID, 1)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
if (item == null)
|
if (item == null)
|
||||||
|
@ -131,7 +144,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
// fruit products
|
// fruit products
|
||||||
case SObject.FruitsCategory:
|
case SObject.FruitsCategory:
|
||||||
// wine
|
// wine
|
||||||
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 2 + id, () => new SObject(348, 1)
|
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 2 + id, _ => new SObject(348, 1)
|
||||||
{
|
{
|
||||||
Name = $"{item.Name} Wine",
|
Name = $"{item.Name} Wine",
|
||||||
Price = item.Price * 3,
|
Price = item.Price * 3,
|
||||||
|
@ -140,7 +153,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
});
|
});
|
||||||
|
|
||||||
// jelly
|
// jelly
|
||||||
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 3 + id, () => new SObject(344, 1)
|
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 3 + id, _ => new SObject(344, 1)
|
||||||
{
|
{
|
||||||
Name = $"{item.Name} Jelly",
|
Name = $"{item.Name} Jelly",
|
||||||
Price = 50 + item.Price * 2,
|
Price = 50 + item.Price * 2,
|
||||||
|
@ -152,7 +165,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
// vegetable products
|
// vegetable products
|
||||||
case SObject.VegetableCategory:
|
case SObject.VegetableCategory:
|
||||||
// juice
|
// juice
|
||||||
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 4 + id, () => new SObject(350, 1)
|
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 4 + id, _ => new SObject(350, 1)
|
||||||
{
|
{
|
||||||
Name = $"{item.Name} Juice",
|
Name = $"{item.Name} Juice",
|
||||||
Price = (int)(item.Price * 2.25d),
|
Price = (int)(item.Price * 2.25d),
|
||||||
|
@ -161,7 +174,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
});
|
});
|
||||||
|
|
||||||
// pickled
|
// pickled
|
||||||
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 5 + id, () => new SObject(342, 1)
|
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 5 + id, _ => new SObject(342, 1)
|
||||||
{
|
{
|
||||||
Name = $"Pickled {item.Name}",
|
Name = $"Pickled {item.Name}",
|
||||||
Price = 50 + item.Price * 2,
|
Price = 50 + item.Price * 2,
|
||||||
|
@ -172,7 +185,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
|
|
||||||
// flower honey
|
// flower honey
|
||||||
case SObject.flowersCategory:
|
case SObject.flowersCategory:
|
||||||
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 5 + id, () =>
|
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 5 + id, _ =>
|
||||||
{
|
{
|
||||||
SObject honey = new SObject(Vector2.Zero, 340, $"{item.Name} Honey", false, true, false, false)
|
SObject honey = new SObject(Vector2.Zero, 340, $"{item.Name} Honey", false, true, false, false)
|
||||||
{
|
{
|
||||||
|
@ -189,14 +202,14 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
foreach (var pair in Game1.objectInformation)
|
foreach (var pair in Game1.objectInformation)
|
||||||
{
|
{
|
||||||
// get input
|
// get input
|
||||||
SObject input = this.TryCreate(ItemType.Object, -1, () => new SObject(pair.Key, 1))?.Item as SObject;
|
SObject input = this.TryCreate(ItemType.Object, pair.Key, p => new SObject(p.ID, 1))?.Item as SObject;
|
||||||
if (input == null || input.Category != SObject.FishCategory)
|
if (input == null || input.Category != SObject.FishCategory)
|
||||||
continue;
|
continue;
|
||||||
Color color = this.GetRoeColor(input);
|
Color color = this.GetRoeColor(input);
|
||||||
|
|
||||||
// yield roe
|
// yield roe
|
||||||
SObject roe = null;
|
SObject roe = null;
|
||||||
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 7 + id, () =>
|
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 7 + id, _ =>
|
||||||
{
|
{
|
||||||
roe = new ColoredObject(812, 1, color)
|
roe = new ColoredObject(812, 1, color)
|
||||||
{
|
{
|
||||||
|
@ -211,7 +224,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
// aged roe
|
// aged roe
|
||||||
if (roe != null && pair.Key != 698) // aged sturgeon roe is caviar, which is a separate item
|
if (roe != null && pair.Key != 698) // aged sturgeon roe is caviar, which is a separate item
|
||||||
{
|
{
|
||||||
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 7 + id, () => new ColoredObject(447, 1, color)
|
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 7 + id, _ => new ColoredObject(447, 1, color)
|
||||||
{
|
{
|
||||||
name = $"Aged {input.Name} Roe",
|
name = $"Aged {input.Name} Roe",
|
||||||
Category = -27,
|
Category = -27,
|
||||||
|
@ -255,13 +268,13 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
||||||
/// <param name="type">The item type.</param>
|
/// <param name="type">The item type.</param>
|
||||||
/// <param name="id">The unique ID (if different from the item's parent sheet index).</param>
|
/// <param name="id">The unique ID (if different from the item's parent sheet index).</param>
|
||||||
/// <param name="createItem">Create an item instance.</param>
|
/// <param name="createItem">Create an item instance.</param>
|
||||||
private SearchableItem TryCreate(ItemType type, int id, Func<Item> createItem)
|
private SearchableItem TryCreate(ItemType type, int id, Func<SearchableItem, Item> createItem)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var item = createItem();
|
var item = new SearchableItem(type, id, createItem);
|
||||||
item.getDescription(); // force-load item data, so it crashes here if it's invalid
|
item.Item.getDescription(); // force-load item data, so it crashes here if it's invalid
|
||||||
return new SearchableItem(type, id, item);
|
return item;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue