Line 173: |
Line 173: |
| ==What's new for items== | | ==What's new for items== |
| ===Custom items=== | | ===Custom items=== |
− | {{/doc status|[[Modding:Items]]|done=false}} | + | {{/doc status|[[Modding:Items]]|done=true}} |
| | | |
| ====Overview==== | | ====Overview==== |
Line 318: |
Line 318: |
| ====Define a custom item==== | | ====Define a custom item==== |
| You can define custom items for most vanilla item types using only [[Modding:Content Patcher|Content Patcher]] or [[Modding:Modder Guide/APIs/Content|SMAPI's content API]]. | | You can define custom items for most vanilla item types using only [[Modding:Content Patcher|Content Patcher]] or [[Modding:Modder Guide/APIs/Content|SMAPI's content API]]. |
− |
| |
− | For example, this content pack adds a new Pufferchick item with a custom image, custom gift tastes, and a custom crop that produces it. Note that item references in other data assets like <samp>Data/Crops</samp> and <samp>Data/NPCGiftTastes</samp> use the item ID.
| |
− |
| |
− | {{#tag:syntaxhighlight|<nowiki>
| |
− | {
| |
− | "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
| |
− | "Changes": [
| |
− | // add item
| |
− | {
| |
− | "Action": "EditData",
| |
− | "Target": "Data/Objects",
| |
− | "Entries": {
| |
− | "{{ModId}}_Pufferchick": {
| |
− | "Name": "{{ModId}}_Pufferchick", // best practice to match the ID, since it's sometimes used as an alternate ID (e.g. in Data/CraftingRecipes)
| |
− | "Displayname": "Pufferchick",
| |
− | "Description": "An example object.",
| |
− | "Type": "Seeds",
| |
− | "Category": -74,
| |
− | "Price": 1200,
| |
− |
| |
− | "Texture": "Mods/{{ModId}}/Objects",
| |
− | "SpriteIndex": 0
| |
− | }
| |
− | }
| |
− | },
| |
− |
| |
− | // add gift tastes
| |
− | {
| |
− | "Action": "EditData",
| |
− | "Target": "Data/NPCGiftTastes",
| |
− | "TextOperations": [
| |
− | {
| |
− | "Operation": "Append",
| |
− | "Target": ["Entries", "Universal_Love"],
| |
− | "Value": "{{ModId}}_Pufferchick",
| |
− | "Delimiter": " " // if there are already values, add a space between them and the new one
| |
− | }
| |
− | ]
| |
− | },
| |
− |
| |
− | // add crop (Pufferchick is both seed and produce, like coffee beans)
| |
− | {
| |
− | "Action": "EditData",
| |
− | "Target": "Data/Crops",
| |
− | "Entries": {
| |
− | "{{ModId}}_Pufferchick": {
| |
− | "Seasons": [ "spring", "summer", "fall" ],
| |
− | "DaysInPhase": [ 1, 1, 1, 1, 1 ],
| |
− | "HarvestItemId": "{{ModId}}_Pufferchick",
| |
− |
| |
− | "Texture": "Mods/{{ModId}}/Crops",
| |
− | "SpriteIndex": 0
| |
− | }
| |
− | }
| |
− | },
| |
− |
| |
− | // add item + crop images
| |
− | {
| |
− | "Action": "Load",
| |
− | "Target": "Mods/{{ModId}}/Crops, Mods/{{ModId}}/Objects",
| |
− | "FromFile": "assets/{{TargetWithoutPath}}.png" // assets/Crops.png, assets/Objects.png
| |
− | }
| |
− | ]
| |
− | }</nowiki>|lang=javascript}}
| |
| | | |
| Most item data assets work just like <samp>Data/Objects</samp>. See also specific info for [[#Custom fruit trees|custom fruit trees]], [[#Custom tools|custom tools]], and [[#Custom melee weapon data|melee weapons]]. | | Most item data assets work just like <samp>Data/Objects</samp>. See also specific info for [[#Custom fruit trees|custom fruit trees]], [[#Custom tools|custom tools]], and [[#Custom melee weapon data|melee weapons]]. |
Line 391: |
Line 327: |
| | | |
| ====For C# mods==== | | ====For C# mods==== |
− | <dl style="margin-left: 2em;">
| |
− |
| |
− | <dt>Compare items</dt>
| |
− | <dd>
| |
− | Since <samp>Item.QualifiedItemId</samp> is globally unique, it can be used to simplify comparing items. For example:
| |
− |
| |
− | {| class="wikitable"
| |
− | |-
| |
− | ! old code
| |
− | ! new code
| |
− | |-
| |
− | |-
| |
− | | <samp>item.ParentSheetIndex == 128</samp>
| |
− | | <samp>item.QualifiedItemId == "(O)128"</samp>
| |
− | |-
| |
− | | <samp>IsNormalObjectAtParentSheetIndex(item, 128)</samp>
| |
− | | <samp>item.QualifiedItemId == "(O)128"</samp>
| |
− | |-
| |
− | | <samp>!item.bigCraftable && item.ParentSheetIndex == 128</samp>
| |
− | | <samp>item.QualifiedItemId == "(O)128"</samp>
| |
− | |-
| |
− | | <samp>item is Boots && item.ParentSheetIndex == 505</samp>
| |
− | | <samp>item.QualifiedItemId == "(B)505"</samp>
| |
− | |}
| |
− |
| |
− | You can also use <samp>ItemRegistry.QualifyItemId</samp> to convert any item ID into a qualified one (if it's valid), and <samp>ItemRegistry.HasItemId</samp> to check if an item has a qualified or unqualified item ID.
| |
− |
| |
− | Note that flavored item don't have their own ID. For example, Blueberry Wine and Wine are both <samp>(O)348</samp>. This affects flavored jellies, juices, pickles, and wines. In those cases you should still compare their separate fields like <samp>preservedParentSheetIndex</samp> (which actually contains the preserved item's <samp>ItemId</samp>, not its <samp>ParentSheetIndex</samp>).
| |
− | </dd>
| |
− |
| |
− | <dt>Construct items</dt>
| |
− | <dd>Creating items works just like before, except that you now specify the item's <samp>ItemId</samp> (''not'' <samp>QualifiedItemId</samp>) instead of its <samp>ParentSheetIndex</samp>. For example:
| |
− |
| |
− | <syntaxhighlight lang="c#">
| |
− | new Object("128", 1); // vanilla item
| |
− | new Object("Example.ModId_Watermelon", 1); // custom item
| |
− | </syntaxhighlight>
| |
− |
| |
− | You can use a new utility method to construct items from their <samp>QualifiedItemId</samp>:
| |
− |
| |
− | <syntaxhighlight lang="c#">
| |
− | Item item = ItemRegistry.Create("(B)505"); // Rubber Boots
| |
− | </syntaxhighlight>
| |
− | </dd>
| |
| | | |
− | <dt>Define custom item types</dt>
| + | Stardew Valley 1.6 added new ways to compare/construct items, define custom item types, and work with item metadata. Please see [[Modding:Items]] for the migrated docs. |
− | <dd>You can implement <samp>IItemDataDefinition</samp> for your own item type, and call <samp>ItemRegistry.AddTypeDefinition</samp> to register it. This provides all the logic needed by the game to handle the item type: where to get item data, how to draw them, etc.
| |
− | | |
− | '''This is extremely specialized''', and multiplayer compatibility is unknown. Most mods should add custom items within the existing types instead.</dd>
| |
− | | |
− | <dt>New <samp>Is*</samp> methods</dt>
| |
− | <dd>1.6 adds some <samp>StardewValley.Object</samp> methods to handle custom items in a generic way (and to let mods patch the logic):
| |
− | {| class="wikitable"
| |
− | |-
| |
− | ! method
| |
− | ! effect
| |
− | |-
| |
− | | <samp>object.IsBar()</samp>
| |
− | | Whether the item is a [[Copper Bar|copper bar]], [[Iron Bar|iron bar]], [[Gold Bar|gold bar]], [[Iridium Bar|iridium bar]], or [[Radioactive Bar|radioactive bar]].
| |
− | |-
| |
− | | <samp>object.IsBreakableStone()</samp>
| |
− | | Whether the item is a stone debris item which can be broken by a pickaxe.
| |
− | |-
| |
− | | <samp>object.IsFence()</samp>
| |
− | | Whether the item is a [[Crafting#Fences|fence]].
| |
− | |-
| |
− | | <samp>object.IsFruitTreeSapling()</samp>
| |
− | | Whether the item is a [[Fruit Trees|fruit tree]] sapling. This checks the <samp>Data\fruitTrees</samp> keys, so it works with custom fruit trees too.
| |
− | |-
| |
− | | <samp>object.IsHeldOverHead()</samp>
| |
− | | Whether the player is shown holding up the item when it's selected in their toolbar. Default true (except for furniture).
| |
− | |-
| |
− | | <samp>object.IsIncubator()</samp>
| |
− | | Whether the item can incubate [[Animals|farm animal]] eggs when placed in a building.
| |
− | |-
| |
− | | <samp>object.IsTapper()</samp>
| |
− | | Whether the item is a [[Tapper|tapper]] or [[Heavy Tapper|heavy tapper]].
| |
− | |-
| |
− | | <samp>object.IsTeaSapling()</samp>
| |
− | | Whether the item is a [[Tea Sapling|tea sapling]].
| |
− | |-
| |
− | | <samp>object.IsTwig()</samp>
| |
− | | Whethere the item is a twig debris item.
| |
− | |-
| |
− | | <samp>object.IsWeeds()</samp>
| |
− | | Whether the item is a weed debris item.
| |
− | |}
| |
− | </dd>
| |
− | | |
− | <dt>Work with item metadata</dt>
| |
− | <dd>
| |
− | 1.6 adds an <samp>ItemRegistry</samp> API for working with the new item system. Some of the provided methods are:
| |
− | | |
− | {| class="wikitable"
| |
− | |-
| |
− | ! method
| |
− | ! effect
| |
− | |-
| |
− | | <samp>ItemRegistry.Create</samp>
| |
− | | Create an item from its item ID (qualified or unqualified). If the ID doesn't match a real item, the optional <samp>allowNull</samp> parameter indicates whether to return null or an Error Item. For example:
| |
− | <syntaxhighlight lang="c#">
| |
− | Item item = ItemRegistry.Create("(B)505"); // Rubber Boots
| |
− | </syntaxhighlight>
| |
− | | |
− | You can also get a specific value type instead of <samp>Item</samp> if needed. This will throw a descriptive exception if the type isn't compatible (e.g. you try to convert furniture to boots).
| |
− | <syntaxhighlight lang="c#">
| |
− | Boots item = ItemRegistry.Create<Boots>("(B)505"); // Rubber Boots
| |
− | </syntaxhighlight>
| |
− | |-
| |
− | | <samp>ItemRegistry.Exists</samp>
| |
− | | Get whether a qualified or unqualified item ID matches an existing item. For example:
| |
− | <syntaxhighlight lang="c#">
| |
− | bool pufferfishExist = ItemRegistry.Exists("(O)128");
| |
− | </syntaxhighlight>
| |
− | |-
| |
− | | <samp>ItemRegistry.IsQualifiedId</samp>
| |
− | | Get whether the given item ID is qualified with the type prefix (like <samp>(O)128</samp> instead of <samp>128</samp>).
| |
− | |-
| |
− | | <samp>ItemRegistry.QualifyItemId</samp>
| |
− | | Get the unique qualified item ID given an unqualified or qualified one. For example:
| |
− | <syntaxhighlight lang="c#">
| |
− | string qualifiedId = ItemRegistry.QualifyItemId("128"); // returns (O)128
| |
− | </syntaxhighlight>
| |
− | |-
| |
− | | <samp>ItemRegistry.GetMetadata</samp>
| |
− | | This lets you get high-level info about an item:
| |
− | <syntaxhighlight lang="c#">
| |
− | // get info about Rubber Boots
| |
− | ItemMetadata info = ItemRegistry.GetMetadata("(B)505");
| |
− | | |
− | // get item ID info
| |
− | $"The item has unqualified ID {info.LocalId}, qualified ID {info.QualifiedId}, and is defined by the {info.TypeIdentifier} item data definition.";
| |
− | | |
− | // does the item exist in the data files?
| |
− | bool exists = info.Exists();
| |
− | </syntaxhighlight>
| |
− | | |
− | And get common parsed item data:
| |
− | <syntaxhighlight lang="c#">
| |
− | // get parsed info
| |
− | ParsedItemData data = info.GetParsedData();
| |
− | $"The internal name is {data.InternalName}, translated name {data.DisplayName}, description {data.Description}, etc.";
| |
− | | |
− | // draw an item sprite
| |
− | Texture2D texture = data.GetTexture();
| |
− | Rectangle sourceRect = data.GetSourceRect();
| |
− | spriteBatch.Draw(texture, Vector2.Zero, sourceRect, Color.White);
| |
− | </syntaxhighlight>
| |
− | | |
− | And create an item:
| |
− | <syntaxhighlight lang="c#">
| |
− | Item item = metadata.CreateItem();
| |
− | </syntaxhighlight>
| |
− | | |
− | And get the type definition (note that this is very specialized, and you should usually use <samp>ItemRegistry</samp> instead to benefit from its caching and optimizations):
| |
− | <syntaxhighlight lang="c#">
| |
− | IItemDataDefinition typeDefinition = info.GetTypeDefinition();
| |
− | </syntaxhighlight>
| |
− | |-
| |
− | | <samp>ItemRegistry.ResolveMetadata</samp>
| |
− | | Equivalent to <samp>ItemRegistry.GetMetadata</samp>, except that it'll return null if the item doesn't exist.
| |
− | |-
| |
− | | <samp>ItemRegistry.GetData</samp>
| |
− | | Get the parsed data about an item, or <samp>null</samp> if the item doesn't exist. This is a shortcut for <code>ItemRegistry.ResolveMetadata(id)?.GetParsedData()</code>; see the previous method for info on the parsed data.
| |
− | |-
| |
− | | <samp>ItemRegistry.GetDataOrErrorItem</samp>
| |
− | | Equivalent to <samp>ItemRegistry.GetData</samp>, except that it'll return info for an Error Item if the item doesn't exist (e.g. for drawing in inventory).
| |
− | |-
| |
− | | <samp>ItemRegistry.GetErrorItemName</samp>
| |
− | | Get a translated ''Error Item'' label.
| |
− | |}
| |
− | </dd>
| |
− | </dl>
| |
| | | |
| ===Custom big craftables=== | | ===Custom big craftables=== |